fix(server): 修复蝦皮规格自动匹配固定首批扫描空跑,增加有界分页续扫 #359

Open
opened 2026-10-06 15:25:19 +08:00 by ila · 7 comments
Owner

基本信息

  • 类型:缺陷;所属 Epic / MVP:无,关联 #195(蝦皮规格自动匹配定时任务)、#283(匹配结果保存)。
  • 当前阶段(2026-10-08):已合并 main、执行线上追加迁移并发布重启,待业务验收。发布源码 0138da85602fb1baf5e208b4bc451f9357190e9d,线上 122.228.200.167;保持原定时任务配置,未手动触发真实 AI。管理员运行摘要字段认证回读、真实多轮续扫及匹配效果仍待验证。下文早期未授权/未发布描述为当时阶段记录,以最终发布回写为准。
  • 原始需求:2026-10-06 用户要求先查清定时匹配持续处理 0 件的原因,核验后确认按最小修复建议建工单。2026-10-07 用户进一步授权实施,未授权执行业务库迁移或发布。

基线、现象与根因

  • 核验日期:2026-10-06;线上源码 e76de6fc08f8b8f0a4bec6a51eb9193451aa784e,release 20261006-e76de6f-358;本地只读代码基线 e2a68b33caab3f4b4cf04733afe91c3a66d51504。
  • 最近 7 天运行记录汇总:168 次,全部 completed;每次 batch_limit=20、scanned_count=500、eligible_count=0、processed_count=0、failed_count=0。
  • 当前按相同排序核对:前 500 件蝦皮商品的 specs_json 全部为空数组,记录均早于统计窗口;PDD 端有颜色或尺码,蝦皮端无共同可用规格,因此资格判断全部跳过。
  • 按现有字段判定条件做只读统计,第一件符合匹配条件的商品位于第 1812 位,队列后方有 826 件符合条件。此为核验时快照,不作为固定线上验收数量;未调用 AI 或执行匹配。
  • 代码:server/app/goauto/shopeeproduct/auto_match_batch.go:124-134,queryLimit=batchLimit*25、最多1000,按 updated_at ASC,id ASC 只查询一次;153 行遇到不合格直接 continue,没有翻页或跨轮续扫。
  • 231 行无共同可用规格或不需匹配时返回不合格;所有跳过分支都不更新商品 updated_at,不仅是空规格,还包括已全部确认、未变 unmatched、达到重试上限和冷却中等,都会长期占据首段。单纯前置过滤或扩大扫描上限不能根治,必须跨轮持久化续扫。
  • 工作项表核验时为空,说明尚未进入工作项领取及 AI 调用阶段,不是 Provider 故障、重试次数耗尽或任务未启动。
  • completed 目前表示循环无错误,不代表有商品被匹配。只增加 batchLimit 不能修复:候选查询最多1000,仍可能到不了后续有效商品。
  • 工单仅记录脱敏汇总,不保存真实商品、订单、规格原文、凭据或完整生产响应。

依赖与并行

  • 依赖现有自动匹配批次、资格判断、工作项领取及原有匹配持久化逻辑;无需 ERPGo、Android 或 AI Provider 改动。
  • 不与同一文件、相同批次表/工作项表的修改并行。实施前核对最新 main 与现有工单完成状态。
  • v2 明确需要追加两个续扫/停止原因字段;已授权代码实施及内存测试;未授权执行业务库迁移、并发安全修复的正式运行、数据修复或发布。执行迁移前须独立取得用户授权。

子项目影响与范围

  • server:候选查询、分页续扫、有限扫描预算、运行统计及回归测试。
  • shared-docs:业务规则、架构/数据结构、Admin运行记录响应契约、运维排障。
  • 不修改 Web/Android、页面布局、Agent API、权限、AI 提示词、阈值及规格匹配算法;不改采购或支付流程。
  • 不回填历史匹配、不批量重置工作项、不删除空规格商品、不为了绕过排序而修改商品 updated_at。
  • 不建设全量 AI 成功率看板或通用任务框架。统计仅服务本批次扫描诊断。

最小方案(v2,整合 Claude #55/#56)

1. 候选筛选与处理边界

  • 保留PDD active、关联关系及现有软删除条件。SQL仅做简单、经MySQL和SQLite验证一致的空规格粗过滤;空串、空数组、JSON null是需排除的语义,不把示意 NOT IN 表达式未经验证直接用于JSON列。
  • 精确判断放在Go的autoMatchEligibility:先解析蝦皮规格,确认color或size中存在非空规格值,再读取PDD;空values、只有other维度跳过,只有颜色或只有尺码的合法商品保留。
  • 不修改AI匹配算法、阈值、指纹构成、未变输入去重、重试/冷却及人工/正确映射保护。
  • 默认每批实际领取/处理最多20件,沿用现有batchLimit校验;不能把扫描上限当成AI处理数量。
  • 每页最多200件,每轮最多实际检查2000件;整轮总时间预算10分钟,覆盖数据库查询及AI调用,用剩余预算限制新操作,取消后不再启动新领取/调用。原运行租约保留30分钟,不新增并行worker。

2. 稳定键集轮转和持久化(审核阻塞项B2)

  • 固定按shopee_product.id键集分页:id > cursor,ORDER BY id ASC,LIMIT min(200,剩余扫描预算),不再按updated_at排序,不用OFFSET。
  • 迁移只向shopee_spec_auto_match_run追加两个字段,不新建表:
    • resume_after_id:可空BIGINT,非负商品ID;NULL表示本轮没有提交有效续扫点,0表示下一轮从头开始。
    • stop_reason:VARCHAR(24) NOT NULL DEFAULT '',枚举batch_limit / scan_budget / time_budget / end_of_scan / lease_lost / error。
  • 新轮启动读取最近一条已终结且resume_after_id非空的运行记录,按运行ID倒序选取;0也属于有效值,不能略过它回退到更旧的非零游标。没有记录则从0开始。
  • 只推进到已实际检查并确定处理/跳过的最后一个商品。页中达到batchLimit、扫描预算或时间预算,只保留最后实际检查位置,不跳到预取页末尾。
  • 只有本页全部候选已检查,且查询确实到末尾时,才能写resume_after_id=0、stop_reason=end_of_scan。不能只凭“返回页不满”就回绕,避免页中提前退出造成漏扫。
  • 正常完成或预算退出时,在finishAutoMatchRun同一条带运行所有权守卫的UPDATE里保存计数、停止原因及游标。没有完成判定的当前记录不能越过。
  • 中途崩溃、失去租约或基础设施错误不提交新游标,下一轮沿用上次已提交位置复查,依赖现有幂等/指纹/租约避免重复写入。
  • ID顺序轮转的取舍:较小ID的商品后续发生变化,需等回绕才能重检。不是“最多固定3小时”的保证,实际时延取决于候选规模、每批20件处理上限、扫描预算和运行频率;有限稳定候选集应最终可达。

3. 分页期间的单运行与租约保护(审核阻塞项B1)

  • 当前renewAutoMatchRun仅在处理商品时调用,忽略错误及RowsAffected;claimAutoMatchWork也未校验本轮仍拥有运行槽。增加分页后不能沿用这种无反馈续期。
  • 每页读取前续期,领取商品/启动AI前检查剩余预算与所有权。续期必须检查错误及影响行数;正常要求RowsAffected=1。MySQL默认报告实际变更行数,同毫秒续期可能返回0:仅该续租零行分支在原事务行锁内再次校验运行ID、owner、running、active_slot和实时有效租约;仍属当前运行才视为有效。数据库错误或其他行数均失败,完成/工作项更新仍严格要求一行。
  • 续期与完成更新守卫包含运行ID、running、active_slot=1、lease_owner和租约尚未到期,不能续活已经过期的旧运行;数据库错误也应停止,不继续领取。
  • claim事务内校验并锁定本轮运行记录,确认状态、槽位、owner和有效租约后才进入工作项领取,防止失租旧运行继续启动新AI操作。保持原有工作项指纹、有限重试及冷却逻辑。
  • 失租立即取消本轮上下文,不再领取、调用或写入续扫游标;不能覆盖新owner的运行状态。
  • lease_lost用于旧运行的脱敏诊断;旧进程失租后不得为了写stop_reason强行UPDATE。由合法过期回收路径标记旧运行为failed/lease_lost且不推进游标;无法安全落库时仅记录日志。
  • 新增回归验证:租约过期或owner被替换后,旧运行不能领取、续期或完成覆盖;续期/claim错误安全退出。

4. 计数与诊断

  • scanned_count改为实际检查的候选数,不是len(预取结果),也不等于SQL粗过滤前的全表数量;文档明确口径变化。
  • eligible_count仍为Go资格检查通过的商品数;processed_count仍为实际领取并进入处理的商品数,不等于成功数;confirmed/unmatched为规格项数,failed沿用现有错误计数含义,不能混算成功率。
  • 跳过原因按类别写一条脱敏批次结构化日志(如无共同可选规格/已确认/指纹未变/重试上限/冷却/占用),不为每个原因加表字段,不保存逐商品业务样本。
  • stop_reason及resume_after_id使用明确JSON字段名stopReason/resumeAfterId;现有Admin运行记录接口以追加可选信息返回,保持旧字段和状态兼容,补齐对应契约,不改Web页面。
  • completed保留“正常执行完成”的语义,处理0件可由计数和stop_reason解释,不把空跑当匹配成功,也不把合法无候选标成失败。

5. 数据库兼容与范围

  • 迁移必须幂等,旧记录resume_after_id=NULL、stop_reason='';不修改商品数据,不重置工作项。
  • 旧二进制忽略追加字段;代码回退保留新字段,不自动回滚已保存映射。实施迁移和发布各自需要用户授权,不通过启动自动执行未授权迁移。
  • Claude提出每轮缓存AI设置updated_at的优化属于非阻塞建议,本单默认不做,避免设置运行中变更时改变输入指纹语义;确需纳入先说明一致性方案。
  • 不做通用任务框架、不扩大到#360规格键规范化、不建设AI成功率看板。

实际涉及:auto_match_batch.go、批次/扫描/MySQL只读测试、models/shopee_spec_auto_match.go及追加迁移/测试;为保证每次Provider调用及映射落库都有批次守卫,局部修改ai_suggest.go和auto_match.go;aimatching/service.go仅纠正配置读取数据库错误被disabled判断遮蔽的问题。非批次Provider重试、算法和阈值不变。

设计证据与确认

  • 非UI、恢复定时匹配可达性的缺陷;无需QuantUX/UI原型,无HTML导出。
  • v2流程:读取最近已提交游标 → 检查/续期运行租约 → ID键集分页 → Go资格判断/跳过推进 → 守卫领取并复用匹配 → 预算/末尾退出 → 守卫提交计数及游标。
  • 审核来源:Claude消息#55、#56(回复#53);审核代码基线origin/main 64f0e49,审核者确认auto_match_batch.go与e2a68b3相同。
  • 2026-10-06用户授权把审核建议整合进正文。此为当时设计确认;2026-10-07已另获代码实施授权,数据库迁移/线上发布仍未授权。
  • B1租约、B2游标设计已纳入;额外明确不满页提前退出不得回绕、失租不得强行回写,以及轮转时延不能按固定小时承诺。

验收标准

  • 前500/1000件为空规格,后方存在合法待匹配商品时,后方商品能被处理;覆盖首个有效商品在1812位附近的合成回归,不使用生产样本。

  • 只有颜色、只有尺码的合法商品不会被前置筛选误排除;空规格、空 values、仅 other 维度正确跳过。

  • 首段全部已确认、未变 unmatched、达到重试上限、冷却/租约中时,仍继续扫描后续商品,不反复停在首段。

  • 每轮实际处理不超过 batchLimit;扫描预算触顶可安全退出,下一轮及进程重启后继续扫描。

  • 页中达到处理上限时,不漏掉页内尚未检查记录;跨页不因自身更新 updated_at 而漏扫;末尾回绕后能重新发现条件已变化商品。

  • 保留全局单运行、指纹去重、原重试/租约、人工/正确映射保护及事务保存;不新增并行 AI 调用或全量重试。

  • 统计计数与实际分支一致,可解释处理0件;失败、正常无候选、预算退出能够区分,不暴露业务样本或凭据。

  • 授权后的线上验收证明不再重复扫描同一批空档案,出现真实候选/处理;允许合法无候选时仍为0,不强制所有826件成功。

  • 必要测试、文档影响、提交、未验证项和部署/迁移授权边界回写工单,待用户验收,不自行关闭。

  • 租约过期、owner变化、续期零行且再次核验不再拥有有效租约或数据库错误时,旧运行不再领取/调用、不回写游标、不覆盖新owner。

  • 租约回收记录lease_lost;预算退出记录scan_budget/time_budget;正常末尾、空候选记录end_of_scan;计数与停止原因一致。

  • 不满页但只处理一部分时不回绕;整页边界、预算恰好触顶、最近游标为0或NULL均有回归。

  • 10分钟总预算实际传播至数据库与模拟Provider;超时不再领取,原30分钟租约保护不中断。

  • 追加迁移重复执行安全,旧记录默认值正确、旧代码读取不受影响;Admin响应新增字段不改变原字段和状态语义。

验证方式

  • 默认单元测试:在server执行go test ./app/goauto/shopeeproduct,该包使用SQLite内存库,不会连接本机MySQL。迁移执行对应包的定向测试。
  • 推荐实现保持Go精确判断+可移植SQL粗过滤,覆盖空数组/null/空values/only-other/单颜色/单尺码、分页和租约。
  • 本机另有MySQL 8环境,不可据此宣称默认Go单元测试覆盖了MySQL。迁移和JSON列粗过滤应做MySQL兼容验证;若改用MySQL JSON函数实现精确筛选,必须新增GOAUTO_IT_MYSQL_DSN集成测试,参考sybproductfilter/recompute_mysql_integration_test.go,在隔离临时测试库覆盖上述规格形态。
  • 数据库连接参数仅从本机私有配置/环境读取,工单和代码不记录凭据;创建/删除测试库和业务库迁移按授权边界执行。未运行的MySQL验证必须明确列为未验证。
  • 用合成数据和模拟 AI Provider 验证跨页、跨轮、重启/回绕、正常匹配保存及预算限制,不以真实 AI 消耗或真实采购作为单元验证。
  • 测试前核对现有失败基线,不混入无关修复。
  • 线上只读复核统计;真实触发匹配、迁移及发布前再次确认授权。当前没有执行这些动作。

风险和回退

  • 原先被饿死的商品变为可处理后,会产生原本预期的 AI 调用与映射写入;保留每批20件、串行及调用时限,避免突然全量处理。
  • 游标推进/回绕错误可能漏扫或重复扫描,需要专项回归。重启不能丢失长期进度。
  • v2需要上述两个字段的追加迁移,保持向后兼容、不删改已有业务数据;回退旧二进制不自动撤销已确认映射,数据恢复必须独立授权。

文档影响、任务记录

  • 更新 Business-Rules-and-Glossary:扫描与跳过、批次处理边界;追加字段及游标生命周期更新 Architecture-and-Code-Map;更新 Deployment-and-Operations 中的空跑排障/迁移说明。
  • 不改变共享 Agent API;Admin运行统计响应新增stopReason/resumeAfterId,同步已有对应契约,不新增UI。
  • 长期事实落地后在线更新Wiki并回读revision,再执行一次 sync 与 sync --check;本轮已更新线上Wiki并回读,镜像同步和验证见交付记录。
  • Gitea工单为任务唯一事实来源,默认不建任务快照、不导出生产数据。
  • 交付文档:沿用上述现有运维/业务文档,不新增独立交付物。
  • Gitea交互:建单时曾因无MCP回退REST API;本轮工单/Wiki读取及更新均使用Gitea MCP。Wiki镜像同步按仓库harness命令使用私有环境凭据,不输出凭据。

需求变化记录

  • 2026-10-06 v1:按用户确认的最小修复方案建单;最后指令只要求建单,停在待实施。
  • 2026-10-06 v2:按用户授权整合Claude消息#55/#56到正文:纳入B1租约保护、B2 ID持久化游标及两个追加字段;明确200件/页、2000件扫描上限、10分钟预算、单轮20件默认处理上限;补齐MySQL/SQLite测试边界、统计口径和失租/末页回绕验收。仅更新工单,仍待实施及迁移/发布授权。
  • 2026-10-07 实施:按用户授权完成有界续扫及回归;评审补充MySQL同值续租零行语义的受锁核验,不放宽真正失租保护;实测本机3308 MySQL8.4.3合成只读JSON过滤通过。业务库迁移、MySQL DDL/锁竞争、真实AI批次与线上验收未执行。
## 基本信息 - 类型:缺陷;所属 Epic / MVP:无,关联 #195(蝦皮规格自动匹配定时任务)、#283(匹配结果保存)。 - 当前阶段(2026-10-08):**已合并 main、执行线上追加迁移并发布重启,待业务验收**。发布源码 `0138da85602fb1baf5e208b4bc451f9357190e9d`,线上 `122.228.200.167`;保持原定时任务配置,未手动触发真实 AI。管理员运行摘要字段认证回读、真实多轮续扫及匹配效果仍待验证。下文早期未授权/未发布描述为当时阶段记录,以最终发布回写为准。 - 原始需求:2026-10-06 用户要求先查清定时匹配持续处理 0 件的原因,核验后确认按最小修复建议建工单。2026-10-07 用户进一步授权实施,未授权执行业务库迁移或发布。 ## 基线、现象与根因 - 核验日期:2026-10-06;线上源码 e76de6fc08f8b8f0a4bec6a51eb9193451aa784e,release 20261006-e76de6f-358;本地只读代码基线 e2a68b33caab3f4b4cf04733afe91c3a66d51504。 - 最近 7 天运行记录汇总:168 次,全部 completed;每次 batch_limit=20、scanned_count=500、eligible_count=0、processed_count=0、failed_count=0。 - 当前按相同排序核对:前 500 件蝦皮商品的 specs_json 全部为空数组,记录均早于统计窗口;PDD 端有颜色或尺码,蝦皮端无共同可用规格,因此资格判断全部跳过。 - 按现有字段判定条件做只读统计,第一件符合匹配条件的商品位于第 1812 位,队列后方有 826 件符合条件。此为核验时快照,不作为固定线上验收数量;未调用 AI 或执行匹配。 - 代码:server/app/goauto/shopeeproduct/auto_match_batch.go:124-134,queryLimit=batchLimit*25、最多1000,按 updated_at ASC,id ASC 只查询一次;153 行遇到不合格直接 continue,没有翻页或跨轮续扫。 - 231 行无共同可用规格或不需匹配时返回不合格;所有跳过分支都不更新商品 updated_at,不仅是空规格,还包括已全部确认、未变 unmatched、达到重试上限和冷却中等,都会长期占据首段。单纯前置过滤或扩大扫描上限不能根治,必须跨轮持久化续扫。 - 工作项表核验时为空,说明尚未进入工作项领取及 AI 调用阶段,不是 Provider 故障、重试次数耗尽或任务未启动。 - completed 目前表示循环无错误,不代表有商品被匹配。只增加 batchLimit 不能修复:候选查询最多1000,仍可能到不了后续有效商品。 - 工单仅记录脱敏汇总,不保存真实商品、订单、规格原文、凭据或完整生产响应。 ## 依赖与并行 - 依赖现有自动匹配批次、资格判断、工作项领取及原有匹配持久化逻辑;无需 ERPGo、Android 或 AI Provider 改动。 - 不与同一文件、相同批次表/工作项表的修改并行。实施前核对最新 main 与现有工单完成状态。 - v2 明确需要追加两个续扫/停止原因字段;已授权代码实施及内存测试;未授权执行业务库迁移、并发安全修复的正式运行、数据修复或发布。执行迁移前须独立取得用户授权。 ## 子项目影响与范围 - server:候选查询、分页续扫、有限扫描预算、运行统计及回归测试。 - shared-docs:业务规则、架构/数据结构、Admin运行记录响应契约、运维排障。 - 不修改 Web/Android、页面布局、Agent API、权限、AI 提示词、阈值及规格匹配算法;不改采购或支付流程。 - 不回填历史匹配、不批量重置工作项、不删除空规格商品、不为了绕过排序而修改商品 updated_at。 - 不建设全量 AI 成功率看板或通用任务框架。统计仅服务本批次扫描诊断。 ## 最小方案(v2,整合 Claude #55/#56) ### 1. 候选筛选与处理边界 - 保留PDD active、关联关系及现有软删除条件。SQL仅做简单、经MySQL和SQLite验证一致的空规格粗过滤;空串、空数组、JSON null是需排除的语义,不把示意 NOT IN 表达式未经验证直接用于JSON列。 - 精确判断放在Go的autoMatchEligibility:先解析蝦皮规格,确认color或size中存在非空规格值,再读取PDD;空values、只有other维度跳过,只有颜色或只有尺码的合法商品保留。 - 不修改AI匹配算法、阈值、指纹构成、未变输入去重、重试/冷却及人工/正确映射保护。 - 默认每批实际领取/处理最多20件,沿用现有batchLimit校验;不能把扫描上限当成AI处理数量。 - 每页最多200件,每轮最多实际检查2000件;整轮总时间预算10分钟,覆盖数据库查询及AI调用,用剩余预算限制新操作,取消后不再启动新领取/调用。原运行租约保留30分钟,不新增并行worker。 ### 2. 稳定键集轮转和持久化(审核阻塞项B2) - 固定按shopee_product.id键集分页:id > cursor,ORDER BY id ASC,LIMIT min(200,剩余扫描预算),不再按updated_at排序,不用OFFSET。 - 迁移只向shopee_spec_auto_match_run追加两个字段,不新建表: - resume_after_id:可空BIGINT,非负商品ID;NULL表示本轮没有提交有效续扫点,0表示下一轮从头开始。 - stop_reason:VARCHAR(24) NOT NULL DEFAULT '',枚举batch_limit / scan_budget / time_budget / end_of_scan / lease_lost / error。 - 新轮启动读取最近一条已终结且resume_after_id非空的运行记录,按运行ID倒序选取;0也属于有效值,不能略过它回退到更旧的非零游标。没有记录则从0开始。 - 只推进到已实际检查并确定处理/跳过的最后一个商品。页中达到batchLimit、扫描预算或时间预算,只保留最后实际检查位置,不跳到预取页末尾。 - 只有本页全部候选已检查,且查询确实到末尾时,才能写resume_after_id=0、stop_reason=end_of_scan。不能只凭“返回页不满”就回绕,避免页中提前退出造成漏扫。 - 正常完成或预算退出时,在finishAutoMatchRun同一条带运行所有权守卫的UPDATE里保存计数、停止原因及游标。没有完成判定的当前记录不能越过。 - 中途崩溃、失去租约或基础设施错误不提交新游标,下一轮沿用上次已提交位置复查,依赖现有幂等/指纹/租约避免重复写入。 - ID顺序轮转的取舍:较小ID的商品后续发生变化,需等回绕才能重检。不是“最多固定3小时”的保证,实际时延取决于候选规模、每批20件处理上限、扫描预算和运行频率;有限稳定候选集应最终可达。 ### 3. 分页期间的单运行与租约保护(审核阻塞项B1) - 当前renewAutoMatchRun仅在处理商品时调用,忽略错误及RowsAffected;claimAutoMatchWork也未校验本轮仍拥有运行槽。增加分页后不能沿用这种无反馈续期。 - 每页读取前续期,领取商品/启动AI前检查剩余预算与所有权。续期必须检查错误及影响行数;正常要求RowsAffected=1。MySQL默认报告实际变更行数,同毫秒续期可能返回0:仅该续租零行分支在原事务行锁内再次校验运行ID、owner、running、active_slot和实时有效租约;仍属当前运行才视为有效。数据库错误或其他行数均失败,完成/工作项更新仍严格要求一行。 - 续期与完成更新守卫包含运行ID、running、active_slot=1、lease_owner和租约尚未到期,不能续活已经过期的旧运行;数据库错误也应停止,不继续领取。 - claim事务内校验并锁定本轮运行记录,确认状态、槽位、owner和有效租约后才进入工作项领取,防止失租旧运行继续启动新AI操作。保持原有工作项指纹、有限重试及冷却逻辑。 - 失租立即取消本轮上下文,不再领取、调用或写入续扫游标;不能覆盖新owner的运行状态。 - lease_lost用于旧运行的脱敏诊断;旧进程失租后不得为了写stop_reason强行UPDATE。由合法过期回收路径标记旧运行为failed/lease_lost且不推进游标;无法安全落库时仅记录日志。 - 新增回归验证:租约过期或owner被替换后,旧运行不能领取、续期或完成覆盖;续期/claim错误安全退出。 ### 4. 计数与诊断 - scanned_count改为实际检查的候选数,不是len(预取结果),也不等于SQL粗过滤前的全表数量;文档明确口径变化。 - eligible_count仍为Go资格检查通过的商品数;processed_count仍为实际领取并进入处理的商品数,不等于成功数;confirmed/unmatched为规格项数,failed沿用现有错误计数含义,不能混算成功率。 - 跳过原因按类别写一条脱敏批次结构化日志(如无共同可选规格/已确认/指纹未变/重试上限/冷却/占用),不为每个原因加表字段,不保存逐商品业务样本。 - stop_reason及resume_after_id使用明确JSON字段名stopReason/resumeAfterId;现有Admin运行记录接口以追加可选信息返回,保持旧字段和状态兼容,补齐对应契约,不改Web页面。 - completed保留“正常执行完成”的语义,处理0件可由计数和stop_reason解释,不把空跑当匹配成功,也不把合法无候选标成失败。 ### 5. 数据库兼容与范围 - 迁移必须幂等,旧记录resume_after_id=NULL、stop_reason='';不修改商品数据,不重置工作项。 - 旧二进制忽略追加字段;代码回退保留新字段,不自动回滚已保存映射。实施迁移和发布各自需要用户授权,不通过启动自动执行未授权迁移。 - Claude提出每轮缓存AI设置updated_at的优化属于非阻塞建议,本单默认不做,避免设置运行中变更时改变输入指纹语义;确需纳入先说明一致性方案。 - 不做通用任务框架、不扩大到#360规格键规范化、不建设AI成功率看板。 实际涉及:auto_match_batch.go、批次/扫描/MySQL只读测试、models/shopee_spec_auto_match.go及追加迁移/测试;为保证每次Provider调用及映射落库都有批次守卫,局部修改ai_suggest.go和auto_match.go;aimatching/service.go仅纠正配置读取数据库错误被disabled判断遮蔽的问题。非批次Provider重试、算法和阈值不变。 ## 设计证据与确认 - 非UI、恢复定时匹配可达性的缺陷;无需QuantUX/UI原型,无HTML导出。 - v2流程:读取最近已提交游标 → 检查/续期运行租约 → ID键集分页 → Go资格判断/跳过推进 → 守卫领取并复用匹配 → 预算/末尾退出 → 守卫提交计数及游标。 - 审核来源:Claude消息#55、#56(回复#53);审核代码基线origin/main 64f0e49,审核者确认auto_match_batch.go与e2a68b3相同。 - 2026-10-06用户授权把审核建议整合进正文。此为当时设计确认;2026-10-07已另获代码实施授权,数据库迁移/线上发布仍未授权。 - B1租约、B2游标设计已纳入;额外明确不满页提前退出不得回绕、失租不得强行回写,以及轮转时延不能按固定小时承诺。 ## 验收标准 - [x] 前500/1000件为空规格,后方存在合法待匹配商品时,后方商品能被处理;覆盖首个有效商品在1812位附近的合成回归,不使用生产样本。 - [x] 只有颜色、只有尺码的合法商品不会被前置筛选误排除;空规格、空 values、仅 other 维度正确跳过。 - [x] 首段全部已确认、未变 unmatched、达到重试上限、冷却/租约中时,仍继续扫描后续商品,不反复停在首段。 - [x] 每轮实际处理不超过 batchLimit;扫描预算触顶可安全退出,下一轮及进程重启后继续扫描。 - [x] 页中达到处理上限时,不漏掉页内尚未检查记录;跨页不因自身更新 updated_at 而漏扫;末尾回绕后能重新发现条件已变化商品。 - [x] 保留全局单运行、指纹去重、原重试/租约、人工/正确映射保护及事务保存;不新增并行 AI 调用或全量重试。 - [x] 统计计数与实际分支一致,可解释处理0件;失败、正常无候选、预算退出能够区分,不暴露业务样本或凭据。 - [ ] 授权后的线上验收证明不再重复扫描同一批空档案,出现真实候选/处理;允许合法无候选时仍为0,不强制所有826件成功。 - [x] 必要测试、文档影响、提交、未验证项和部署/迁移授权边界回写工单,待用户验收,不自行关闭。 - [x] 租约过期、owner变化、续期零行且再次核验不再拥有有效租约或数据库错误时,旧运行不再领取/调用、不回写游标、不覆盖新owner。 - [x] 租约回收记录lease_lost;预算退出记录scan_budget/time_budget;正常末尾、空候选记录end_of_scan;计数与停止原因一致。 - [x] 不满页但只处理一部分时不回绕;整页边界、预算恰好触顶、最近游标为0或NULL均有回归。 - [x] 10分钟总预算实际传播至数据库与模拟Provider;超时不再领取,原30分钟租约保护不中断。 - [x] 追加迁移重复执行安全,旧记录默认值正确、旧代码读取不受影响;Admin响应新增字段不改变原字段和状态语义。 ## 验证方式 - 默认单元测试:在server执行go test ./app/goauto/shopeeproduct,该包使用SQLite内存库,不会连接本机MySQL。迁移执行对应包的定向测试。 - 推荐实现保持Go精确判断+可移植SQL粗过滤,覆盖空数组/null/空values/only-other/单颜色/单尺码、分页和租约。 - 本机另有MySQL 8环境,不可据此宣称默认Go单元测试覆盖了MySQL。迁移和JSON列粗过滤应做MySQL兼容验证;若改用MySQL JSON函数实现精确筛选,必须新增GOAUTO_IT_MYSQL_DSN集成测试,参考sybproductfilter/recompute_mysql_integration_test.go,在隔离临时测试库覆盖上述规格形态。 - 数据库连接参数仅从本机私有配置/环境读取,工单和代码不记录凭据;创建/删除测试库和业务库迁移按授权边界执行。未运行的MySQL验证必须明确列为未验证。 - 用合成数据和模拟 AI Provider 验证跨页、跨轮、重启/回绕、正常匹配保存及预算限制,不以真实 AI 消耗或真实采购作为单元验证。 - 测试前核对现有失败基线,不混入无关修复。 - 线上只读复核统计;真实触发匹配、迁移及发布前再次确认授权。当前没有执行这些动作。 ## 风险和回退 - 原先被饿死的商品变为可处理后,会产生原本预期的 AI 调用与映射写入;保留每批20件、串行及调用时限,避免突然全量处理。 - 游标推进/回绕错误可能漏扫或重复扫描,需要专项回归。重启不能丢失长期进度。 - v2需要上述两个字段的追加迁移,保持向后兼容、不删改已有业务数据;回退旧二进制不自动撤销已确认映射,数据恢复必须独立授权。 ## 文档影响、任务记录 - 更新 Business-Rules-and-Glossary:扫描与跳过、批次处理边界;追加字段及游标生命周期更新 Architecture-and-Code-Map;更新 Deployment-and-Operations 中的空跑排障/迁移说明。 - 不改变共享 Agent API;Admin运行统计响应新增stopReason/resumeAfterId,同步已有对应契约,不新增UI。 - 长期事实落地后在线更新Wiki并回读revision,再执行一次 sync 与 sync --check;本轮已更新线上Wiki并回读,镜像同步和验证见交付记录。 - Gitea工单为任务唯一事实来源,默认不建任务快照、不导出生产数据。 - 交付文档:沿用上述现有运维/业务文档,不新增独立交付物。 - Gitea交互:建单时曾因无MCP回退REST API;本轮工单/Wiki读取及更新均使用Gitea MCP。Wiki镜像同步按仓库harness命令使用私有环境凭据,不输出凭据。 ## 需求变化记录 - 2026-10-06 v1:按用户确认的最小修复方案建单;最后指令只要求建单,停在待实施。 - 2026-10-06 v2:按用户授权整合Claude消息#55/#56到正文:纳入B1租约保护、B2 ID持久化游标及两个追加字段;明确200件/页、2000件扫描上限、10分钟预算、单轮20件默认处理上限;补齐MySQL/SQLite测试边界、统计口径和失租/末页回绕验收。仅更新工单,仍待实施及迁移/发布授权。 - 2026-10-07 实施:按用户授权完成有界续扫及回归;评审补充MySQL同值续租零行语义的受锁核验,不放宽真正失租保护;实测本机3308 MySQL8.4.3合成只读JSON过滤通过。业务库迁移、MySQL DDL/锁竞争、真实AI批次与线上验收未执行。
Author
Owner

开始实施(2026-10-07)

用户授权「做#359」。基线 origin/main 6781b309d4cd0de226c038b9fd509cb68e021b51,独立 worktree D:/OPC/goauto-worktrees/issue-359,分支 fix/359-auto-match-resume。
按已确认 v2 串行执行:①复核 shopeeproduct 基线并增加失败回归;②追加字段/幂等迁移及测试,实施分页、持久游标、预算和租约守卫;③定向/整包回归与独立规格、质量评审;④Wiki-first 更新、同步检查、提交推送与证据回写。
仅编写迁移和测试,不执行本地/线上业务库迁移、不建删 MySQL 测试库、不发布、不触发真实 AI/匹配/采购。SQLite 内存测试可运行,MySQL 实测需要独立授权。无需 UI 原型,不涉及 #360 规格键规则。

## 开始实施(2026-10-07) 用户授权「做#359」。基线 origin/main `6781b309d4cd0de226c038b9fd509cb68e021b51`,独立 worktree `D:/OPC/goauto-worktrees/issue-359`,分支 `fix/359-auto-match-resume`。 按已确认 v2 串行执行:①复核 shopeeproduct 基线并增加失败回归;②追加字段/幂等迁移及测试,实施分页、持久游标、预算和租约守卫;③定向/整包回归与独立规格、质量评审;④Wiki-first 更新、同步检查、提交推送与证据回写。 仅编写迁移和测试,不执行本地/线上业务库迁移、不建删 MySQL 测试库、不发布、不触发真实 AI/匹配/采购。SQLite 内存测试可运行,MySQL 实测需要独立授权。无需 UI 原型,不涉及 #360 规格键规则。
Author
Owner

实施交付(2026-10-07,开发分支待验收)

实现范围

  • 分支 fix/359-auto-match-resume,基线 6781b309d4cd0de226c038b9fd509cb68e021b51。
  • ID键集分页200件/页、实际扫描2000件/轮、默认实际领取20件、整轮10分钟,持久游标续扫/回绕;Go先判断蝦皮规格再读PDD。
  • 追加两列及幂等迁移文件 1791300000000_shopee_spec_auto_match_resume.go,Admin运行摘要追加字段;只编写,未执行业务库迁移。
  • 所有权检查覆盖分页续租、领取、每次Provider调用及映射事务。错误/失租不提交新游标,预算结束仅用独立最多5秒上下文受守卫收尾。
  • 必需局部配套:AI配置数据库错误不再被“未启用”吞掉;非批次Provider重试、阈值、匹配算法、人工确认映射保护未改变。
  • 独立规格评审PASS;质量评审发现MySQL同毫秒续租无变更返回0的问题,已修复并复审PASS。只有续租零行时在当前事务锁内重新核验有效所有权,其余写入严格守卫保留。
  • 重复测试发现新测试夹具共享内存残留,已仅在#359测试内增加连接清理,未修改生产逻辑或公共旧夹具。

提交

  • 95847a3f2daccb07f65a2a8f62cfd7c6144328c3:有界续扫/守卫/迁移与回归。
  • 151c426e54751717c59859b23458ee2f60f20ced:新增测试重复运行隔离。
  • 9fcbc64117bcee0cbed25c3957a14a25d826f637:MySQL零变更续租兼容。
  • 文档镜像提交:a82a1469a64255ffa34a516d02e87656376ff22f(分支已推送远端)。

真实验证

使用已安装Go1.26.5(PATH默认Go版本较旧,不修改全局环境)。

  1. 三个相关包 go test ./app/goauto/shopeeproduct ./app/goauto/aimatching ./cmd/migrate/migration/version-local -count=1:PASS(8.587s / 3.036s / 2.548s)。
  2. 新增扫描、领取、续租、Provider、工作项、预算和资格回归 -count=3:PASS(10.270s)。
  3. Linux amd64 Server构建:PASS,CGO_ENABLED=0;产物仅在本机临时目录,未上传。
  4. 用户明确本机3308为MySQL8;实际版本8.4.3。独立可选测试 TestAutoMatchScanMySQLJSONCoarseFilter:7个合成SELECT用例PASS;不选择业务库、不建表/改表、不读写生产行。默认其他Go测试仍使用SQLite及模拟Provider。
  5. 续租零变更:先红(合法所有者误判失租)后绿;过期/换owner/多行更新仍失败。
  6. git diff --check PASS;Wiki一次sync及一次sync --check结果见下。
  7. harness.py check --strict仍有既有阻塞:docs/evidence/pdd-home-35727-summary.md被判为未登记Wiki镜像;该文件未由本单修改,不扩大范围处理。

长期文档

在线更新并回读一致,未直接修改镜像:
Business-Rules-and-Glossary: 2abd7a07ccf8a28308ce9c318250e2f8f957c137
Architecture-and-Code-Map: b8b969b0c20aca9af6798a5a0b8784aa735600d4
Deployment-and-Operations: cf7b9d1e8ca8f97933936e4ddfd9edc3fac43c98
Android-Agent-API-Contract: cf3788145daf3dfe9a4526fd231bc4b8d730f763
已执行一次 harness.py sync 成功;一次 sync --check,17页全部一致。

未执行/待授权

  • 未合并main、未执行业务库迁移、未发布/重启,未改变定时任务启停,未调用真实AI或写入真实匹配数据。
  • MySQL迁移DDL及锁竞争集成测试未执行,不以只读JSON测试替代。
  • 线上多轮推进、真实处理计数及末尾回绕仍须授权部署后验证,不能宣称当前线上已恢复。
  • 保持工单open待验收;未合并的worktree D:/OPC/goauto-worktrees/issue-359按规则保留。
## 实施交付(2026-10-07,开发分支待验收) ### 实现范围 - 分支 `fix/359-auto-match-resume`,基线 `6781b309d4cd0de226c038b9fd509cb68e021b51`。 - ID键集分页200件/页、实际扫描2000件/轮、默认实际领取20件、整轮10分钟,持久游标续扫/回绕;Go先判断蝦皮规格再读PDD。 - 追加两列及幂等迁移文件 `1791300000000_shopee_spec_auto_match_resume.go`,Admin运行摘要追加字段;只编写,未执行业务库迁移。 - 所有权检查覆盖分页续租、领取、每次Provider调用及映射事务。错误/失租不提交新游标,预算结束仅用独立最多5秒上下文受守卫收尾。 - 必需局部配套:AI配置数据库错误不再被“未启用”吞掉;非批次Provider重试、阈值、匹配算法、人工确认映射保护未改变。 - 独立规格评审PASS;质量评审发现MySQL同毫秒续租无变更返回0的问题,已修复并复审PASS。只有续租零行时在当前事务锁内重新核验有效所有权,其余写入严格守卫保留。 - 重复测试发现新测试夹具共享内存残留,已仅在#359测试内增加连接清理,未修改生产逻辑或公共旧夹具。 ### 提交 - `95847a3f2daccb07f65a2a8f62cfd7c6144328c3`:有界续扫/守卫/迁移与回归。 - `151c426e54751717c59859b23458ee2f60f20ced`:新增测试重复运行隔离。 - `9fcbc64117bcee0cbed25c3957a14a25d826f637`:MySQL零变更续租兼容。 - 文档镜像提交:`a82a1469a64255ffa34a516d02e87656376ff22f`(分支已推送远端)。 ### 真实验证 使用已安装Go1.26.5(PATH默认Go版本较旧,不修改全局环境)。 1. 三个相关包 `go test ./app/goauto/shopeeproduct ./app/goauto/aimatching ./cmd/migrate/migration/version-local -count=1`:PASS(8.587s / 3.036s / 2.548s)。 2. 新增扫描、领取、续租、Provider、工作项、预算和资格回归 `-count=3`:PASS(10.270s)。 3. Linux amd64 Server构建:PASS,CGO_ENABLED=0;产物仅在本机临时目录,未上传。 4. 用户明确本机3308为MySQL8;实际版本8.4.3。独立可选测试 `TestAutoMatchScanMySQLJSONCoarseFilter`:7个合成SELECT用例PASS;不选择业务库、不建表/改表、不读写生产行。默认其他Go测试仍使用SQLite及模拟Provider。 5. 续租零变更:先红(合法所有者误判失租)后绿;过期/换owner/多行更新仍失败。 6. `git diff --check` PASS;Wiki一次sync及一次sync --check结果见下。 7. `harness.py check --strict`仍有既有阻塞:`docs/evidence/pdd-home-35727-summary.md`被判为未登记Wiki镜像;该文件未由本单修改,不扩大范围处理。 ### 长期文档 在线更新并回读一致,未直接修改镜像: Business-Rules-and-Glossary: 2abd7a07ccf8a28308ce9c318250e2f8f957c137 Architecture-and-Code-Map: b8b969b0c20aca9af6798a5a0b8784aa735600d4 Deployment-and-Operations: cf7b9d1e8ca8f97933936e4ddfd9edc3fac43c98 Android-Agent-API-Contract: cf3788145daf3dfe9a4526fd231bc4b8d730f763 已执行一次 `harness.py sync` 成功;一次 `sync --check`,17页全部一致。 ### 未执行/待授权 - 未合并main、未执行业务库迁移、未发布/重启,未改变定时任务启停,未调用真实AI或写入真实匹配数据。 - MySQL迁移DDL及锁竞争集成测试未执行,不以只读JSON测试替代。 - 线上多轮推进、真实处理计数及末尾回绕仍须授权部署后验证,不能宣称当前线上已恢复。 - 保持工单open待验收;未合并的worktree `D:/OPC/goauto-worktrees/issue-359`按规则保留。
Author
Owner

合并完成,发布前迁移授权待补(2026-10-07)

用户授权「#359合并main,部署线上」。已在现有main发布工作区按常规no-ff合并,合并提交 0138da85602fb1baf5e208b4bc451f9357190e9d 已推送origin/main;保留工作区原有无关未跟踪产物,未修改主开发目录。
合并结果重新执行 shopeeproduct、aimatching、version-local 三包测试,全部PASS(7.062s/2.951s/1.587s)。
本单明确要求迁移单独授权,因此尚未执行业务库迁移、线上发布或重启。需确认允许在122.228.200.167执行追加迁移 1791300000000_shopee_spec_auto_match_resume.go:只增加 shopee_spec_auto_match_run.resume_after_id / stop_reason 和迁移登记,不改历史商品/映射,不改定时任务启停。获授权后再做线上运行任务检查、受限备份、迁移、发布与验证。
本轮只更新合并/授权状态,无新的运行契约变化,不重复Wiki同步;部署完成后统一更新发布事实。工单保持open。发布尚未完成,按规则保留issue-359 worktree,发布成功后再清理。

## 合并完成,发布前迁移授权待补(2026-10-07) 用户授权「#359合并main,部署线上」。已在现有main发布工作区按常规no-ff合并,合并提交 `0138da85602fb1baf5e208b4bc451f9357190e9d` 已推送origin/main;保留工作区原有无关未跟踪产物,未修改主开发目录。 合并结果重新执行 shopeeproduct、aimatching、version-local 三包测试,全部PASS(7.062s/2.951s/1.587s)。 本单明确要求迁移单独授权,因此尚未执行业务库迁移、线上发布或重启。需确认允许在122.228.200.167执行追加迁移 `1791300000000_shopee_spec_auto_match_resume.go`:只增加 `shopee_spec_auto_match_run.resume_after_id` / `stop_reason` 和迁移登记,不改历史商品/映射,不改定时任务启停。获授权后再做线上运行任务检查、受限备份、迁移、发布与验证。 本轮只更新合并/授权状态,无新的运行契约变化,不重复Wiki同步;部署完成后统一更新发布事实。工单保持open。发布尚未完成,按规则保留issue-359 worktree,发布成功后再清理。
Author
Owner

开始授权发布(2026-10-07)

用户明确授权在线执行 #359 追加迁移,随后发布并重启 GoAuto。合并main 0138da85602fb1baf5e208b4bc451f9357190e9d;Linux Server已重新构建,SHA256 4962738a7fe56244e13748d861f8e8214743ac22d8bf6440c6c8e27d381f88b6。
线上目标122.228.200.167,当前release 20261007-eb7cb6b-363,MySQL8.4.8。注册版本比对唯一缺失 1791300000000;Web与线上#363源码无差异,将完整复制已验证dist并核对全部文件哈希。保持config、环境、持久资源真实路径及sys_job启停/Cron/参数不变,不触发真实匹配或采购。
预检有1个采集任务运行,其余被检查运行项为0;暂不迁移或重启,先准备发布文件,等待空闲后执行受限数据库备份及迁移,切换前再核验。

## 开始授权发布(2026-10-07) 用户明确授权在线执行 #359 追加迁移,随后发布并重启 GoAuto。合并main `0138da85602fb1baf5e208b4bc451f9357190e9d`;Linux Server已重新构建,SHA256 `4962738a7fe56244e13748d861f8e8214743ac22d8bf6440c6c8e27d381f88b6`。 线上目标122.228.200.167,当前release `20261007-eb7cb6b-363`,MySQL8.4.8。注册版本比对唯一缺失 `1791300000000`;Web与线上#363源码无差异,将完整复制已验证dist并核对全部文件哈希。保持config、环境、持久资源真实路径及sys_job启停/Cron/参数不变,不触发真实匹配或采购。 预检有1个采集任务运行,其余被检查运行项为0;暂不迁移或重启,先准备发布文件,等待空闲后执行受限数据库备份及迁移,切换前再核验。
Author
Owner

按用户要求暂缓发布(2026-10-07)

用户回复「暂时不能暂停,稍后再发布」。已停止发布等待,不再继续自动迁移/重启。最后一次只读核验:current仍为 /home/goauto/releases/20261007-eb7cb6b-363;唯一未应用迁移仍为 1791300000000,两个新字段均未创建;sys_job状态/Cron/参数摘要未变。等待进程已结束,没有后台部署链继续执行;采购任务保持原样运行,未取消或重置。
已完成准备:

  • main合并 0138da85602fb1baf5e208b4bc451f9357190e9d;Server构建及上传哈希一致 4962738a7fe56244e13748d861f8e8214743ac22d8bf6440c6c8e27d381f88b6。
  • 未启用的新release /home/goauto/releases/20261007-0138da8-359,436个Web文件与#363逐一一致;沿用config与static/temp/var真实路径。
  • 服务器受限备份 /home/goauto/backups/20261007-359/database.sql,89,158,536字节;不下载生产数据。恢复发布时必须重新检查任务/迁移/版本,并生成新的当时备份,不把这份较早快照作为恢复覆盖后续业务的依据。
    未执行:追加迁移、current切换、GoAuto/Nginx重启、真实匹配。工单保持open待发布/验收,issue-359 worktree按尚未完成发布的规则保留。临时部署辅助文件仅保留于本机发布工作区verification-359,不含凭据或生产业务数据,不纳入源码提交。没有新的线上长期行为变化,本轮不更新Wiki。
## 按用户要求暂缓发布(2026-10-07) 用户回复「暂时不能暂停,稍后再发布」。已停止发布等待,不再继续自动迁移/重启。最后一次只读核验:current仍为 `/home/goauto/releases/20261007-eb7cb6b-363`;唯一未应用迁移仍为 `1791300000000`,两个新字段均未创建;sys_job状态/Cron/参数摘要未变。等待进程已结束,没有后台部署链继续执行;采购任务保持原样运行,未取消或重置。 已完成准备: - main合并 `0138da85602fb1baf5e208b4bc451f9357190e9d`;Server构建及上传哈希一致 `4962738a7fe56244e13748d861f8e8214743ac22d8bf6440c6c8e27d381f88b6`。 - 未启用的新release `/home/goauto/releases/20261007-0138da8-359`,436个Web文件与#363逐一一致;沿用config与static/temp/var真实路径。 - 服务器受限备份 `/home/goauto/backups/20261007-359/database.sql`,89,158,536字节;不下载生产数据。恢复发布时必须重新检查任务/迁移/版本,并生成新的当时备份,不把这份较早快照作为恢复覆盖后续业务的依据。 未执行:追加迁移、current切换、GoAuto/Nginx重启、真实匹配。工单保持open待发布/验收,issue-359 worktree按尚未完成发布的规则保留。临时部署辅助文件仅保留于本机发布工作区verification-359,不含凭据或生产业务数据,不纳入源码提交。没有新的线上长期行为变化,本轮不更新Wiki。
Author
Owner

恢复授权发布(2026-10-08)

用户明确授权「执行迁移和完成重启更新」,解除此前暂缓。已重新只读检查:采集/采购主任务及attempt、同步、AI匹配/解析、回填、入库码等执行中计数均为0;current仍为20261007-eb7cb6b-363,唯一缺失迁移1791300000000,两个新字段均未创建。
沿用已验证的#359发布包与哈希,重新生成服务器受限备份(不使用昨日快照覆盖新增业务);迁移与切换前再次检查空闲。保持定时任务启停、Cron、参数和Web资源不变,不主动触发真实匹配或采购。此次仅#359发布,不混入#364/#365。

## 恢复授权发布(2026-10-08) 用户明确授权「执行迁移和完成重启更新」,解除此前暂缓。已重新只读检查:采集/采购主任务及attempt、同步、AI匹配/解析、回填、入库码等执行中计数均为0;current仍为20261007-eb7cb6b-363,唯一缺失迁移1791300000000,两个新字段均未创建。 沿用已验证的#359发布包与哈希,重新生成服务器受限备份(不使用昨日快照覆盖新增业务);迁移与切换前再次检查空闲。保持定时任务启停、Cron、参数和Web资源不变,不主动触发真实匹配或采购。此次仅#359发布,不混入#364/#365。
Author
Owner

线上迁移与发布完成(2026-10-08,待业务验收)

用户重新授权执行迁移和完成重启更新。今日备份后,迁移前/切换前两次检查采集、采购及 attempt、同步、AI、回填、入库码批次和调度执行记录均为0;未取消或重置任务。

部署与迁移

  • 线上 122.228.200.167,源码 main 合并 0138da85602fb1baf5e208b4bc451f9357190e9d;current 切到 /home/goauto/releases/20261007-0138da8-359,goauto.service 已重启且 active。
  • 运行进程与发布包 SHA256 一致:4962738a7fe56244e13748d861f8e8214743ac22d8bf6440c6c8e27d381f88b6。
  • 新受限备份 /home/goauto/backups/20261008-359/database.sql,90,758,085 字节,目录0700/文件0600;未下载生产数据。
  • 唯一待执行版本1791300000000已迁移;resume_after_id/stop_reason两列、默认值、非负CHECK约束和迁移登记回读正确,剩余缺失迁移0。旧运行保留NULL/空字符串,不改历史商品或映射。
  • Web完整沿用#363的dist,config/环境/static/temp/var真实路径不变;sys_job启停/Cron/参数摘要前后一致。没有主动执行真实AI、同步、采购或回填;没有Android构建/安装。
  • Nginx配置检查通过,无配置变更,无需重启或reload。

故障与验证

  • 切换后外网根入口出现404,查明为新release根目录受umask=0077影响实际0700,Nginx无法进入。定向恢复与旧release一致的0755后恢复;dist文件从未删除,未修改代理路由。已写入运维说明:受限备份权限与release可遍历权限必须分开验证。
  • 公网 /、/index.html、/login、/syb-products/index 与已验证dist/index.html哈希一致;10项入口JS/CSS、健康、验证码接口通过。
  • 后端日志结构检查 panic/fatal/1146/1054 均0;最新复查服务active、current正确、待执行迁移0。
  • 修正仅本机未提交发布辅助检查:旧systemd不支持--value及ISO时间参数,改为兼容读取;health按代码契约仅返回HTTP200空正文,不强制解析JSON。未改产品代码。
  • 未认证管理员运行摘要返回401;本机admin_jwtoken.txt实际是purchaser凭据,访问该管理员接口403,未绕过或增权。有效管理员会话的新字段回读仍未验证,不能以数据库结构验收替代。
  • 真实多轮续扫、后方候选处理及末尾回绕仍待原计划自然运行验收;没有为了验收手动发起生产AI,不宣称业务成功率已验证。

文档与清理

  • 4个长期Wiki已在线更新并回读一致:
  • Business-Rules-and-Glossary: 233b72e9e2415a2456bb8dd27c770df881960db4
  • Architecture-and-Code-Map: b3d1c9b7ba1dd5820a20e59b0c21a971aaf1b8ee
  • Android-Agent-API-Contract: 640da0a86bf1057d418dbeb062c07a84cb5b1d8e
  • Deployment-and-Operations: db99427fa2460989d34d28ef864230a907fc5e6d
  • 一轮sync和一轮sync --check完成,17页全部一致;文档镜像提交 7622795 已推送main,不需要再部署二进制。
  • 已确认issue-359 HEAD为origin/main祖先、工作区干净、无外部链接/常驻进程或supervisor引用;仅有可再生Python缓存。已用git worktree remove移除 D:/OPC/goauto-worktrees/issue-359 并prune;保留分支与提交历史。release-316既有无关未跟踪内容未动。
  • 回滚release 20261007-eb7cb6b-363 和受限备份保留;回退代码仍须检查任务窗口,保留追加列及发布后的业务数据,不恢复旧库覆盖后续业务。

工单保持open待用户验收。

## 线上迁移与发布完成(2026-10-08,待业务验收) 用户重新授权执行迁移和完成重启更新。今日备份后,迁移前/切换前两次检查采集、采购及 attempt、同步、AI、回填、入库码批次和调度执行记录均为0;未取消或重置任务。 ### 部署与迁移 - 线上 122.228.200.167,源码 main 合并 `0138da85602fb1baf5e208b4bc451f9357190e9d`;current 切到 `/home/goauto/releases/20261007-0138da8-359`,goauto.service 已重启且 active。 - 运行进程与发布包 SHA256 一致:`4962738a7fe56244e13748d861f8e8214743ac22d8bf6440c6c8e27d381f88b6`。 - 新受限备份 `/home/goauto/backups/20261008-359/database.sql`,90,758,085 字节,目录0700/文件0600;未下载生产数据。 - 唯一待执行版本1791300000000已迁移;resume_after_id/stop_reason两列、默认值、非负CHECK约束和迁移登记回读正确,剩余缺失迁移0。旧运行保留NULL/空字符串,不改历史商品或映射。 - Web完整沿用#363的dist,config/环境/static/temp/var真实路径不变;sys_job启停/Cron/参数摘要前后一致。没有主动执行真实AI、同步、采购或回填;没有Android构建/安装。 - Nginx配置检查通过,无配置变更,无需重启或reload。 ### 故障与验证 - 切换后外网根入口出现404,查明为新release根目录受umask=0077影响实际0700,Nginx无法进入。定向恢复与旧release一致的0755后恢复;dist文件从未删除,未修改代理路由。已写入运维说明:受限备份权限与release可遍历权限必须分开验证。 - 公网 /、/index.html、/login、/syb-products/index 与已验证dist/index.html哈希一致;10项入口JS/CSS、健康、验证码接口通过。 - 后端日志结构检查 panic/fatal/1146/1054 均0;最新复查服务active、current正确、待执行迁移0。 - 修正仅本机未提交发布辅助检查:旧systemd不支持--value及ISO时间参数,改为兼容读取;health按代码契约仅返回HTTP200空正文,不强制解析JSON。未改产品代码。 - 未认证管理员运行摘要返回401;本机admin_jwtoken.txt实际是purchaser凭据,访问该管理员接口403,未绕过或增权。**有效管理员会话的新字段回读仍未验证**,不能以数据库结构验收替代。 - **真实多轮续扫、后方候选处理及末尾回绕仍待原计划自然运行验收**;没有为了验收手动发起生产AI,不宣称业务成功率已验证。 ### 文档与清理 - 4个长期Wiki已在线更新并回读一致: - Business-Rules-and-Glossary: `233b72e9e2415a2456bb8dd27c770df881960db4` - Architecture-and-Code-Map: `b3d1c9b7ba1dd5820a20e59b0c21a971aaf1b8ee` - Android-Agent-API-Contract: `640da0a86bf1057d418dbeb062c07a84cb5b1d8e` - Deployment-and-Operations: `db99427fa2460989d34d28ef864230a907fc5e6d` - 一轮sync和一轮sync --check完成,17页全部一致;文档镜像提交 `7622795` 已推送main,不需要再部署二进制。 - 已确认issue-359 HEAD为origin/main祖先、工作区干净、无外部链接/常驻进程或supervisor引用;仅有可再生Python缓存。已用git worktree remove移除 `D:/OPC/goauto-worktrees/issue-359` 并prune;保留分支与提交历史。release-316既有无关未跟踪内容未动。 - 回滚release `20261007-eb7cb6b-363` 和受限备份保留;回退代码仍须检查任务窗口,保留追加列及发布后的业务数据,不恢复旧库覆盖后续业务。 工单保持open待用户验收。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OPC/goauto#359