From 3d15cdb4934f96cf5bb6984501aa5c2dcd566e24 Mon Sep 17 00:00:00 2001 From: Blizzard Date: Sat, 18 Jul 2026 11:45:08 +0800 Subject: [PATCH] =?UTF-8?q?fix(gateway):=20=E4=BB=BB=E5=8A=A1=E8=90=BD?= =?UTF-8?q?=E5=BA=93=E5=A4=B1=E8=B4=A5=E4=B8=8D=E5=86=8D=E5=90=9E=20?= =?UTF-8?q?=E2=80=94=E2=80=94=20=E5=85=B3=E9=94=AE=E5=86=99=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E4=B8=8A=E6=B5=AE=205xx=20(P0-2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DEPTH_ROADMAP:225 未完项 + 完成度审计 P0-2:launch() 里 SaveTask 是 best-effort, DB 写失败只 log 却照样 PublishTask + 返 202。结果任务发出去在后端跑了,却不进 运行历史、复盘不了、报告类的用户切页面回来彻底找不回——用户以为成功、实际没落库。 - SaveTask 对「DB 降级(nil)」返 nil、对「DB 活着写失败」返真 error,天然可区分: 前者静默跳过(开发态本就无库),后者上浮为提交失败。落库在 Publish 之前, 失败时还没发布,中止干净、不产生"看不见的执行"。 - 两个调用点(SubmitTask/GenerateReport)已把 launch 错误映射 5xx,无需再改。 范围克制:审计列的其它 best-effort 点保持不动——dispatcher 的异步回写 (UpdateTaskStatus/SaveTaskOutput/SaveTaskTrace)、审计日志、用量累计计数, 都不是"用户等着响应"的路径,没有请求可返 5xx,best-effort 是对的。 唯独 launch 这处是"用户以为提交成功实际没有",才该阻断。 live 验证:改名 task 表模拟 DB 写失败 → 提交返 502+明确文案(不再假 202); 表改回 → 立刻恢复 202。happy path 202+落库不变。go build/vet/test 全绿。 Co-Authored-By: Claude Opus 4.8 --- sundynix-gateway/internal/handler/task_handler.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sundynix-gateway/internal/handler/task_handler.go b/sundynix-gateway/internal/handler/task_handler.go index a295cab..3b09e02 100644 --- a/sundynix-gateway/internal/handler/task_handler.go +++ b/sundynix-gateway/internal/handler/task_handler.go @@ -4,6 +4,7 @@ package handler import ( "context" "encoding/json" + "fmt" "io" "log" "net/http" @@ -71,9 +72,14 @@ func (h *Handler) preflight(c *gin.Context) (string, bool) { // 报告生成此前只 PublishTask,这两样都没有,所以报告既进不了运行历史, // 切个页面回来也彻底找不回——它明明在后端好好地跑完了。 func (h *Handler) launch(c *gin.Context, task *contract.Task) error { - // 持久化任务提交(best-effort:降级模式下静默跳过,不阻断发布)。 + // 持久化任务提交。DB 降级(nil)时 SaveTask 返 nil 静默跳过(开发态本就无库,不阻断); + // 但 DB 活着却写失败 → 真故障,绝不能吞:一旦 PublishTask 发出去,任务就在后端跑了, + // 却不进运行历史、复盘不了、报告类的会彻底"丢"(用户切页面回来找不回)。 + // 宁可这里失败上浮 5xx 让用户重试,也不发一个"看不见的执行"。落库在 Publish 之前, + // 失败时还没发布,中止是干净的。 if err := h.db.SaveTask(c.Request.Context(), userID(c), task.ID, string(task.Graph)); err != nil { log.Printf("[gateway] save task %s failed: %v", task.ID, err) + return fmt.Errorf("任务落库失败,请重试: %w", err) } if err := h.bus.PublishTask(c.Request.Context(), task); err != nil { return err