docs: import wiki at afc651f75a3a
+89
@@ -0,0 +1,89 @@
|
|||||||
|
<!-- docs-wiki-sync:docs/tasks/T-275.md@afc651f75a3abc2676bb13aa8a80f6aa6a25a72e -->
|
||||||
|
> 同步来源:[`docs/tasks/T-275.md`](/chengma/mroubao/src/commit/afc651f75a3abc2676bb13aa8a80f6aa6a25a72e/docs/tasks/T-275.md) · commit `afc651f75a3a`
|
||||||
|
|
||||||
|
---
|
||||||
|
id: T-275
|
||||||
|
title: 修复超长执行事件阻塞任务同步
|
||||||
|
phase: 2
|
||||||
|
deps:
|
||||||
|
- T-207
|
||||||
|
- T-274
|
||||||
|
status: DONE
|
||||||
|
created: 2026-08-01
|
||||||
|
context_ref: f3f59fb
|
||||||
|
work_branch: null
|
||||||
|
write_paths:
|
||||||
|
- docs/tasks/T-275.md
|
||||||
|
- docs/current-state.md
|
||||||
|
- docs/04-architecture.md
|
||||||
|
- docs/05-coding-rules.md
|
||||||
|
- android-buyer/app/src/main/**
|
||||||
|
- android-buyer/app/src/test/**
|
||||||
|
---
|
||||||
|
|
||||||
|
## 问题 / 背景
|
||||||
|
|
||||||
|
安装 T-274 后,Roubao 任务模块持续提示“后台暂时离线,将在授权截止前重试”,但真机
|
||||||
|
日志证明手机已连接后台,上传 execution outbox 时收到不可重试的 HTTP 422
|
||||||
|
`EXECUTION_RESULT_INVALID`。候选搜索事件原长约 889 字节;T-274 追加六个 locator
|
||||||
|
诊断键后达到 1014 字节,超过后台单条事件 `message` 的 1000 字节契约。
|
||||||
|
|
||||||
|
当前同步循环还把所有非本地异常统一标记为离线,并将不可重试的 4xx 项永久保留在
|
||||||
|
outbox 队首,导致后续事件和 heartbeat 均无法执行。
|
||||||
|
|
||||||
|
## 行为契约
|
||||||
|
|
||||||
|
1. 候选搜索的状态事件与聚合诊断事件分开发送;每条 `message` 的 UTF-8 长度必须在
|
||||||
|
后台 1000 字节上限内,核心状态、轮次、失败码和全部聚合计数均保留。
|
||||||
|
2. T-274 已持久化但尚未被后台接受的超长候选事件,在上传前按稳定分隔点确定性拆成
|
||||||
|
两条合法事件;保持原事件 ID,派生诊断事件 ID 必须稳定,网络重试不能产生新事件。
|
||||||
|
3. 迁移只处理可确认来源的 `CANDIDATE_SEARCH`/`CANDIDATE_SEARCH_*` 超长事件;其它
|
||||||
|
非法 payload 不得截断、丢弃或伪装成功。
|
||||||
|
4. App 解析后台结构化错误中的非敏感字段校验详情。HTTP 已收到响应时后台状态保持在线;
|
||||||
|
仅连接、TLS、DNS、超时等 I/O 错误和可重试 5xx 显示后台暂时不可用。
|
||||||
|
5. `retryable=false` 的 outbox 上传失败进入持久化阻塞状态,不再自动重试同一项,也不越过
|
||||||
|
该项继续 heartbeat 或自动化;UI 显示稳定错误码和安全字段,不显示响应正文、凭证、
|
||||||
|
商品信息或服务端内部信息。
|
||||||
|
6. 更新后必须能自动修复当前手机里由 T-274 产生的 1014 字节候选事件并恢复队列同步,
|
||||||
|
不要求清除 App 数据、重新登录或丢弃任务。
|
||||||
|
|
||||||
|
## 方案
|
||||||
|
|
||||||
|
1. 将候选尝试核心消息与 `CandidateSearchDiagnostics` 消息组装为同一 EVENTS payload 中
|
||||||
|
的两条事件,并增加共享 UTF-8 长度校验常量和单测。
|
||||||
|
2. 在 outbox 上传边界增加窄范围 legacy payload 规范化器:识别单条超限候选事件,按
|
||||||
|
` cards=` 分隔,使用原 event ID 派生稳定 UUID 后形成两条事件。
|
||||||
|
3. 扩展 `ProcurementApiException` 保存经过白名单裁剪的 `details.fields`;同步状态按是否
|
||||||
|
收到 HTTP 响应和 `retryable` 分类。
|
||||||
|
4. 为 outbox 项增加可持久化 rejection 元数据。不可重试响应只记录一次并安全停止同步;
|
||||||
|
legacy 修复在发请求前完成,因此当前已知超长项不会进入 rejection 状态。
|
||||||
|
|
||||||
|
## 验收要点
|
||||||
|
|
||||||
|
- [x] 新候选搜索状态和诊断事件分别小于等于 1000 UTF-8 字节,聚合字段完整。
|
||||||
|
- [x] T-274 的 1014 字节 legacy payload 被稳定拆分并成功上传,重复迁移结果相同。
|
||||||
|
- [x] HTTP 422 显示“后台拒绝执行结果”及安全字段,`backendOnline=true`,且不再重试。
|
||||||
|
- [x] I/O/超时和可重试 5xx 仍保留 outbox 并按既有授权边界重试。
|
||||||
|
- [x] 不可重试阻塞跨进程重启保持,不继续 heartbeat、拼多多动作或越过队首结果。
|
||||||
|
- [x] Android 单测、lint、Debug/Release APK 构建通过,Debug APK 覆盖安装到 PKG110。
|
||||||
|
|
||||||
|
## 边界
|
||||||
|
|
||||||
|
- 不提高后台 1000 字节限制,不放宽敏感内容检查。
|
||||||
|
- 不丢弃不可重试结果,不自动取消任务,不清除登录、claim、候选或下单状态。
|
||||||
|
- 不修改三轮搜索、SKU/价格匹配、候选数量、VLM、支付边界或订单提交授权。
|
||||||
|
|
||||||
|
## 执行记录
|
||||||
|
|
||||||
|
- 2026-08-01:根据真机 HTTP 422 日志和 T-274 消息长度复现创建任务,状态 `TODO`。
|
||||||
|
已确认网络、TLS 和 Bearer 鉴权不是本次错误;直接失败字段为 execution event
|
||||||
|
`message` 超过 1000 UTF-8 字节。
|
||||||
|
- 2026-08-01:候选状态和诊断改为同一 EVENTS payload 内两条有界事件;上传边界只对
|
||||||
|
T-274 单条超长候选格式执行确定性拆分,原 event ID 保留并稳定派生诊断 ID。App 只从
|
||||||
|
`EXECUTION_RESULT_INVALID` 的显式字段白名单读取字段名,不读取字段值或响应正文。
|
||||||
|
不可重试 outbox 拒绝会加密持久化错误码、HTTP 状态和字段名,停止同步、候选采集、
|
||||||
|
dry-run 和提交;I/O/可重试 5xx 仍保持原重试语义。
|
||||||
|
- 2026-08-01:Debug/Release 各 462 项单测、`lintDebug`、`assembleDebug`、
|
||||||
|
`assembleRelease` 全部通过。Debug APK 以保留数据方式覆盖安装到 PKG110;安装后原持续
|
||||||
|
422 的任务恢复为等待后台确认商品。最终 APK 再覆盖安装并运行一个同步周期,logcat
|
||||||
|
未出现 `EXECUTION_RESULT_INVALID`、同步异常或崩溃,状态改为 `DONE`。
|
||||||
Reference in New Issue
Block a user