@@ -17,6 +17,7 @@ const (
1717 settingKeyModelEvals = "recommendation.model_evals"
1818 modelEvalDatasetPath = "evals/workload.json"
1919 modelEvalTimeout = 45 * time .Second
20+ modelEvalStaleAfter = modelEvalTimeout + 15 * time .Second
2021)
2122
2223type modelEvalStatus struct {
@@ -69,16 +70,20 @@ func (s *Server) handleModelEval(w http.ResponseWriter, r *http.Request) {
6970 return
7071 }
7172 defer s .modelEvalMu .Unlock ()
72- if err := s .saveModelEval (r .Context (), provider , modelID , runningModelEval (provider , modelID )); err != nil {
73+ saveCtx , saveCancel := context .WithTimeout (context .Background (), 5 * time .Second )
74+ defer saveCancel ()
75+ if err := s .saveModelEval (saveCtx , provider , modelID , runningModelEval (provider , modelID )); err != nil {
7376 http .Error (w , err .Error (), http .StatusServiceUnavailable )
7477 return
7578 }
7679
7780 caps := s .lookupCapsFor (r .Context (), provider , modelID )
78- ctx , cancel := context .WithTimeout (r . Context (), modelEvalTimeout )
81+ ctx , cancel := context .WithTimeout (context . Background (), modelEvalTimeout )
7982 defer cancel ()
8083 status := s .runModelEval (ctx , provider , modelID , caps )
81- if err := s .saveModelEval (ctx , provider , modelID , status ); err != nil {
84+ saveCtx , saveCancel = context .WithTimeout (context .Background (), 5 * time .Second )
85+ defer saveCancel ()
86+ if err := s .saveModelEval (saveCtx , provider , modelID , status ); err != nil {
8287 http .Error (w , err .Error (), http .StatusServiceUnavailable )
8388 return
8489 }
@@ -258,9 +263,30 @@ func normalizeSingleModelEval(provider, modelID string, status modelEvalStatus)
258263 if status .CheckedAt == "" && status .FinishedAt != "" {
259264 status .CheckedAt = status .FinishedAt
260265 }
266+ if status .Status == "running" && isStaleModelEval (status , time .Now ()) {
267+ now := time .Now ().Format (time .RFC3339 )
268+ status .Status = "error"
269+ status .FinishedAt = now
270+ status .UpdatedAt = now
271+ status .CheckedAt = now
272+ status .Failed = 1
273+ status .Error = "model eval timed out before completion"
274+ status .Failures = []string {status .Error }
275+ }
261276 return status
262277}
263278
279+ func isStaleModelEval (status modelEvalStatus , now time.Time ) bool {
280+ if status .StartedAt == "" {
281+ return false
282+ }
283+ started , err := time .Parse (time .RFC3339 , status .StartedAt )
284+ if err != nil {
285+ return false
286+ }
287+ return now .Sub (started ) > modelEvalStaleAfter
288+ }
289+
264290type modelOpsData struct {
265291 ActiveTab string
266292 Checks []modelCheckStatus
0 commit comments