fix(backend): split final UpdateAIJob + add goroutine recover() for AI job handlers
Some checks failed
Release / Test UI (push) Has been cancelled
Release / Build and push images (push) Has been cancelled
Release / Test backend (push) Has been cancelled
Release / Deploy to prod (push) Has been cancelled
Release / Deploy to homelab (push) Has been cancelled
Release / Gitea Release (push) Has been cancelled
Some checks failed
Release / Test UI (push) Has been cancelled
Release / Build and push images (push) Has been cancelled
Release / Test backend (push) Has been cancelled
Release / Deploy to prod (push) Has been cancelled
Release / Deploy to homelab (push) Has been cancelled
Release / Gitea Release (push) Has been cancelled
Split the single combined UpdateAIJob call at the end of each async goroutine into two sequential calls (status first, payload second) so that a failure writing the large results payload does not silently prevent the job from being marked done. Added recover() to each goroutine to catch and log panics. Affects chapter-names, description, and image-gen handlers.
This commit is contained in:
@@ -559,6 +559,11 @@ func (s *Server) handleAdminImageGenAsync(w http.ResponseWriter, r *http.Request
|
||||
go func() {
|
||||
defer deregisterCancelJob(jobID)
|
||||
defer jobCancel()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
logger.Error("admin: image-gen goroutine panic", "job_id", jobID, "recover", r)
|
||||
}
|
||||
}()
|
||||
|
||||
if jobCtx.Err() != nil {
|
||||
_ = store.UpdateAIJob(context.Background(), jobID, map[string]any{
|
||||
@@ -625,13 +630,19 @@ func (s *Server) handleAdminImageGenAsync(w http.ResponseWriter, r *http.Request
|
||||
Guidance: capturedReq.Guidance,
|
||||
})
|
||||
|
||||
_ = store.UpdateAIJob(context.Background(), jobID, map[string]any{
|
||||
if err := store.UpdateAIJob(context.Background(), jobID, map[string]any{
|
||||
"status": string(domain.TaskStatusDone),
|
||||
"items_done": 1,
|
||||
"items_total": 1,
|
||||
"payload": string(resultJSON),
|
||||
"finished": time.Now().Format(time.RFC3339),
|
||||
})
|
||||
}); err != nil {
|
||||
logger.Error("admin: image-gen failed to mark job done", "job_id", jobID, "err", err)
|
||||
}
|
||||
if err := store.UpdateAIJob(context.Background(), jobID, map[string]any{
|
||||
"payload": string(resultJSON),
|
||||
}); err != nil {
|
||||
logger.Error("admin: image-gen failed to write job payload", "job_id", jobID, "err", err)
|
||||
}
|
||||
|
||||
logger.Info("admin: image-gen async done",
|
||||
"job_id", jobID, "slug", capturedReq.Slug,
|
||||
|
||||
@@ -516,6 +516,11 @@ func (s *Server) handleAdminTextGenChapterNamesAsync(w http.ResponseWriter, r *h
|
||||
go func() {
|
||||
defer deregisterCancelJob(jobID)
|
||||
defer jobCancel()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
logger.Error("admin: text-gen chapter-names goroutine panic", "job_id", jobID, "recover", r)
|
||||
}
|
||||
}()
|
||||
|
||||
var allResults []proposedChapterTitle
|
||||
chaptersDone := 0
|
||||
@@ -574,12 +579,18 @@ func (s *Server) handleAdminTextGenChapterNamesAsync(w http.ResponseWriter, r *h
|
||||
if jobCtx.Err() != nil {
|
||||
status = domain.TaskStatusCancelled
|
||||
}
|
||||
_ = store.UpdateAIJob(context.Background(), jobID, map[string]any{
|
||||
if err := store.UpdateAIJob(context.Background(), jobID, map[string]any{
|
||||
"status": string(status),
|
||||
"items_done": chaptersDone,
|
||||
"finished": time.Now().Format(time.RFC3339),
|
||||
}); err != nil {
|
||||
logger.Error("admin: text-gen chapter-names failed to mark job done", "job_id", jobID, "err", err)
|
||||
}
|
||||
if err := store.UpdateAIJob(context.Background(), jobID, map[string]any{
|
||||
"payload": finalPayload,
|
||||
})
|
||||
}); err != nil {
|
||||
logger.Error("admin: text-gen chapter-names failed to write job payload", "job_id", jobID, "err", err)
|
||||
}
|
||||
logger.Info("admin: text-gen chapter-names async done",
|
||||
"job_id", jobID, "slug", capturedSlug,
|
||||
"results", len(allResults), "status", string(status))
|
||||
@@ -902,6 +913,11 @@ func (s *Server) handleAdminTextGenDescriptionAsync(w http.ResponseWriter, r *ht
|
||||
go func() {
|
||||
defer deregisterCancelJob(jobID)
|
||||
defer jobCancel()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
logger.Error("admin: text-gen description goroutine panic", "job_id", jobID, "recover", r)
|
||||
}
|
||||
}()
|
||||
|
||||
if jobCtx.Err() != nil {
|
||||
_ = store.UpdateAIJob(context.Background(), jobID, map[string]any{
|
||||
@@ -955,13 +971,19 @@ func (s *Server) handleAdminTextGenDescriptionAsync(w http.ResponseWriter, r *ht
|
||||
NewDescription: strings.TrimSpace(newDesc),
|
||||
})
|
||||
|
||||
_ = store.UpdateAIJob(context.Background(), jobID, map[string]any{
|
||||
if err := store.UpdateAIJob(context.Background(), jobID, map[string]any{
|
||||
"status": string(domain.TaskStatusDone),
|
||||
"items_done": 1,
|
||||
"items_total": 1,
|
||||
"payload": string(resultJSON),
|
||||
"finished": time.Now().Format(time.RFC3339),
|
||||
})
|
||||
}); err != nil {
|
||||
logger.Error("admin: text-gen description failed to mark job done", "job_id", jobID, "err", err)
|
||||
}
|
||||
if err := store.UpdateAIJob(context.Background(), jobID, map[string]any{
|
||||
"payload": string(resultJSON),
|
||||
}); err != nil {
|
||||
logger.Error("admin: text-gen description failed to write job payload", "job_id", jobID, "err", err)
|
||||
}
|
||||
logger.Info("admin: text-gen description async done", "job_id", jobID, "slug", capturedMeta.Slug)
|
||||
}()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user