fix(server): 图搜后的规格匹配挂在 Agent 请求 ctx 上,超时断开即中断 #300

Open
opened 2026-09-16 17:18:05 +08:00 by ila · 0 comments
Owner

来源:2026-09-16 线上实测。用户原话:「线上服务syb订单2609142G6875RU蝦皮商品42870755023,图搜采集后没有匹配颜色尺码,我手动一键匹配又能成功」。

问题

图搜采集成功并自动关联后的规格匹配,挂在 Agent 提交采集结果那个 HTTP 请求的 context 上。AI 匹配耗时几十秒到几分钟,Agent 先超时断开,请求 ctx 被取消,匹配当场中断。

采购员手动点「一键匹配」能成功,因为那是另一个请求的 ctx。

证据

result_service.go:130:

linked, err := service.autoLinkImageSearch(ctx, taskID)
...
service.matchSpecsAfterImageSearch(ctx, linked)

ctx 来自 SubmitResult(ctx context.Context, ...),即 Agent 提交结果的请求上下文。

线上日志(#294 上线后第一次派上用场,2026-09-16 17:07~17:14):

shopee 28111: image search spec match failed=1; syb 15806 failed: AI 匹配服务暂时不可用
shopee 28111: archive spec match failed: context canceled
shopee  8544: archive spec match failed: context canceled
shopee  5250: archive spec match failed: context canceled
shopee  5259: archive spec match failed: context canceled
shopee  9214: archive spec match confirmed=5 skipped=2 no_match=1   ← 请求活得够久
shopee 26680: archive spec match confirmed=1 no_match=1 unavailable=7

六个商品中四个被 ctx 取消打断。成功的两个只是 Agent 尚未超时。本地时好时坏同样由此解释:本地网络与 AI 响应快,常能赶在超时前做完。

次生问题

ctx 取消导致的 AI 调用失败被 classifySpecMatchFailure 归入 specMatchUnavailable(「AI 匹配服务暂时不可用」),而 AI 服务本身正常。#295 的重试对它无效——重试用的是同一个已死的 ctx。日志里 26680 的 unavailable=7 大概率也是这个原因,不是 Provider 故障。这会持续误导排查。

方案(A:脱钩 context,仍同步)

  1. matchSpecsAfterImageSearch 不再直接使用入站请求 ctx。改为从中派生一个不随请求取消的 context(context.WithoutCancel),并加上自己的超时上限,避免无限期挂起。
  2. [必须] 区分「ctx 被取消/超时」与「AI 服务不可用」。前者是本端调度问题,重试无意义;后者才是 Provider 故障。日志与计数必须分得开,否则会一直把自己的调度缺陷读成外部故障。

非目标

  • 不改为异步执行(方案 B)。异步是更正确的终态,但牵涉并发、失败可见性与服务重启丢任务,需单独评估。本单只止血。
  • 不改任何匹配判据、候选校验、可售 SKU 校验与置信度门槛。
  • 不改 SubmitResult 的返回内容与 Agent 契约。
  • 不自动创建采购。
  • 不动 app/goauto/sybimport 的 12 个既有失败用例(#285)。

已知影响

Agent 的提交请求仍会等待匹配完成,超时断开后服务端继续做完,结果正确但 Agent 侧会看到一次超时。这是 A 方案的已知代价,由方案 B 解决。

验收

  • Agent 提交请求断开后,规格同步与匹配仍然完整执行。
  • 线上日志不再出现 archive spec match failed: ... context canceled。
  • 超时上限生效,不会无限期挂起。
  • ctx 取消/超时与 AI 服务不可用在日志中可区分。
  • 匹配判据与结果不变。

验证

go test ./app/goauto/task/... ./app/goauto/purchase/...;线上发布后观察一次真实图搜采集的日志。

文档影响

匹配执行的生命周期变化,需更新对应 Wiki 页面说明其不再受 Agent 请求生命周期约束。

> 来源:2026-09-16 线上实测。用户原话:「线上服务syb订单2609142G6875RU蝦皮商品42870755023,图搜采集后没有匹配颜色尺码,我手动一键匹配又能成功」。 ## 问题 图搜采集成功并自动关联后的规格匹配,挂在 **Agent 提交采集结果那个 HTTP 请求的 context** 上。AI 匹配耗时几十秒到几分钟,Agent 先超时断开,请求 ctx 被取消,匹配当场中断。 采购员手动点「一键匹配」能成功,因为那是另一个请求的 ctx。 ## 证据 `result_service.go:130`: ```go linked, err := service.autoLinkImageSearch(ctx, taskID) ... service.matchSpecsAfterImageSearch(ctx, linked) ``` `ctx` 来自 `SubmitResult(ctx context.Context, ...)`,即 Agent 提交结果的请求上下文。 线上日志(#294 上线后第一次派上用场,2026-09-16 17:07~17:14): ``` shopee 28111: image search spec match failed=1; syb 15806 failed: AI 匹配服务暂时不可用 shopee 28111: archive spec match failed: context canceled shopee 8544: archive spec match failed: context canceled shopee 5250: archive spec match failed: context canceled shopee 5259: archive spec match failed: context canceled shopee 9214: archive spec match confirmed=5 skipped=2 no_match=1 ← 请求活得够久 shopee 26680: archive spec match confirmed=1 no_match=1 unavailable=7 ``` **六个商品中四个被 ctx 取消打断**。成功的两个只是 Agent 尚未超时。本地时好时坏同样由此解释:本地网络与 AI 响应快,常能赶在超时前做完。 ## 次生问题 ctx 取消导致的 AI 调用失败被 `classifySpecMatchFailure` 归入 `specMatchUnavailable`(「AI 匹配服务暂时不可用」),而 AI 服务本身正常。#295 的重试对它无效——重试用的是同一个已死的 ctx。日志里 26680 的 `unavailable=7` 大概率也是这个原因,不是 Provider 故障。这会持续误导排查。 ## 方案(A:脱钩 context,仍同步) 1. `matchSpecsAfterImageSearch` 不再直接使用入站请求 ctx。改为从中派生一个**不随请求取消**的 context(`context.WithoutCancel`),并加上自己的超时上限,避免无限期挂起。 2. `[必须]` 区分「ctx 被取消/超时」与「AI 服务不可用」。前者是本端调度问题,重试无意义;后者才是 Provider 故障。日志与计数必须分得开,否则会一直把自己的调度缺陷读成外部故障。 ## 非目标 - 不改为异步执行(方案 B)。异步是更正确的终态,但牵涉并发、失败可见性与服务重启丢任务,需单独评估。本单只止血。 - 不改任何匹配判据、候选校验、可售 SKU 校验与置信度门槛。 - 不改 `SubmitResult` 的返回内容与 Agent 契约。 - 不自动创建采购。 - 不动 `app/goauto/sybimport` 的 12 个既有失败用例(#285)。 ## 已知影响 Agent 的提交请求仍会等待匹配完成,超时断开后服务端继续做完,结果正确但 Agent 侧会看到一次超时。这是 A 方案的已知代价,由方案 B 解决。 ## 验收 - [ ] Agent 提交请求断开后,规格同步与匹配仍然完整执行。 - [ ] 线上日志不再出现 `archive spec match failed: ... context canceled`。 - [ ] 超时上限生效,不会无限期挂起。 - [ ] ctx 取消/超时与 AI 服务不可用在日志中可区分。 - [ ] 匹配判据与结果不变。 ## 验证 `go test ./app/goauto/task/... ./app/goauto/purchase/...`;线上发布后观察一次真实图搜采集的日志。 ## 文档影响 匹配执行的生命周期变化,需更新对应 Wiki 页面说明其不再受 Agent 请求生命周期约束。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/goauto#300