fix(tenant): finalize definitive/manual-retry publish tasks as failed
Desktop Client Build / Resolve Build Metadata (push) Successful in 58s
Backend CI / Backend (push) Failing after 12m16s
Frontend CI / Frontend (push) Successful in 5m5s
Desktop Client Build / Build Desktop Client (push) Successful in 23m55s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 41s

Add normalizeDesktopTaskCompletionStatusForTask so an "unknown" publish
completion is downgraded to "failed" when the payload is a manual retry or
the error matches a definitive publish failure, instead of leaving it
stuck as unknown.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-08 22:32:15 +08:00
parent aecdb87fa3
commit f1334aac80
2 changed files with 53 additions and 1 deletions
@@ -1217,7 +1217,7 @@ func (s *DesktopTaskService) Complete(ctx context.Context, client *repository.De
previousTask, _ := taskRepo.GetByDesktopID(ctx, desktopID, client.WorkspaceID)
previousAttemptID := activeAttemptID(previousTask)
if previousTask != nil {
finalStatus = normalizeDesktopTaskCompletionStatusForKind(previousTask.Kind, finalStatus)
finalStatus = normalizeDesktopTaskCompletionStatusForTask(previousTask.Kind, finalStatus, previousTask.Payload, errorJSON)
}
task, err := taskRepo.Complete(ctx, desktopID, HashDesktopClientToken(strings.TrimSpace(req.LeaseToken)), finalStatus, resultJSON, errorJSON)
@@ -1937,6 +1937,24 @@ func normalizeDesktopTaskCompletionStatusForKind(kind string, status string) str
return strings.TrimSpace(status)
}
func normalizeDesktopTaskCompletionStatusForTask(kind string, status string, payloadJSON []byte, errorJSON []byte) string {
normalizedStatus := normalizeDesktopTaskCompletionStatusForKind(kind, status)
if strings.TrimSpace(kind) != "publish" || normalizedStatus != "unknown" {
return normalizedStatus
}
if boolValueFromMap(unmarshalJSONObject(payloadJSON), "manual_retry") {
return "failed"
}
if publishUnknownTaskHasDefinitiveFailure(&repository.DesktopTask{
Kind: "publish",
Status: "unknown",
Error: errorJSON,
}) {
return "failed"
}
return normalizedStatus
}
func normalizeDesktopTaskViewStatus(kind string, status string) string {
switch strings.TrimSpace(kind) {
case "monitor":
@@ -204,6 +204,40 @@ func TestNormalizeDesktopTaskCompletionStatusForKindFailsMonitorUnknown(t *testi
}
}
func TestNormalizeDesktopTaskCompletionStatusForTaskFailsDefinitivePublishUnknown(t *testing.T) {
t.Parallel()
got := normalizeDesktopTaskCompletionStatusForTask(
"publish",
"unknown",
nil,
[]byte(`{"publish_submit_uncertain":true,"code":"toutiaohao_publish_failed","message":"标题长度应该在2-30字之间"}`),
)
if got != "failed" {
t.Fatalf("publish title validation completion status = %q, want failed", got)
}
got = normalizeDesktopTaskCompletionStatusForTask(
"publish",
"unknown",
nil,
[]byte(`{"publish_submit_uncertain":true,"message":"network interrupted after submit"}`),
)
if got != "unknown" {
t.Fatalf("ambiguous publish completion status = %q, want unknown", got)
}
got = normalizeDesktopTaskCompletionStatusForTask(
"publish",
"unknown",
[]byte(`{"manual_retry":true}`),
[]byte(`{"publish_submit_uncertain":true,"message":"network interrupted after submit"}`),
)
if got != "failed" {
t.Fatalf("manual retry publish completion status = %q, want failed", got)
}
}
func TestExpiredMonitorDesktopTasksCandidateSQLSelectsOnlyExpiredInProgressMonitorTasks(t *testing.T) {
t.Parallel()