跨设备菜品学习记录同步识别回归修复

变更目标

修复设备 A 学习菜品后,设备 B 同步学习图片成功但无法识别的问题,同时保证同步失败、SDK 校正失败或进程中断时,设备 B 仍可回退到上一份可用学习数据。

根因

2026-07-22 引入 staging 事务目录后,同步流程把下载图片保存在临时目录,并在 learnDateRivise() 返回成功后立即替换正式目录。SDK 的即时返回仅表示请求已受理,真正的学习特征重建通过异步进度回调完成;原流程没有等待进度到 100,且校正时使用的目录随后被重命名,导致 SDK 后台读取路径不稳定,从而出现跨设备同步后无法识别。

本次未变更 SDK AAR,修复位于应用侧的同步事务和 SDK 异步完成判定。

实现内容

  1. 新增 DishLearningRevisionRunner,将 SDK 即时受理结果与异步最终结果分离:即时响应确认成功前只缓冲进度,仅进度 100 视为成功,-1、中断和请求拒绝均视为失败。
  2. 将完整同步拆分为准备、激活、提交和恢复四个阶段:staging 目录只负责下载和校验;调用 SDK 前先把 staging 切换到固定正式目录;旧正式目录保留为 backup;SDK 成功后才删除 backup,失败时恢复 backup。
  3. 新增进程级 DishLearningOperationCoordinator,将完整同步、菜品新增学习、删除学习图片和识别页替换学习统一串行化,避免它们同时改写正式目录或消费同一组全局 SDK 回调。
  4. 激活新 root 前创建独立的 .sync_recovery_required 持久标记;SDK 进度到 100 时再写 confirmed 标记并清除恢复标记,最后提交 backup。即使恢复 backup 后、旧特征重建完成前再次崩溃,下次启动仍会继续阻断识别并重建特征。
  5. 恢复旧目录后,对旧目录再次执行 SDK 校正,避免磁盘数据已回退但内存特征仍处于失败同步状态;恢复阶段的未激活状态也进入统一激活处理。
  6. 全量分页在服务端声明仍有数据却返回空页、缺项或不前进时整次失败,禁止用不完整集合覆盖正式目录。
  7. SDK 五分钟内未给出终态进度时进入故障隔离:显式调用 SDK 远程 release() 路径、保留 root 与 backup 事务现场、唤醒并拒绝已排队的学习写、暂停菜品识别与学习预览,并提示重启。新进程首次使用协调器时会检查未确认 backup,在菜品管理完成旧目录与旧特征恢复前继续阻止识别和所有学习写。
  8. 新增事务目录、异步进度、共享协调器和分页决策单元测试,覆盖成功、失败、超时隔离、请求拒绝、拒绝前旧进度、激活提交、失败恢复、崩溃窗口和不完整分页。

变更文件

验证记录

实机验收建议

  1. 设备 A 学习一个新菜品并确认本机可识别。
  2. 设备 B 进入菜品管理触发同步,等待“学习数据校正成功”。
  3. 在设备 B 连续识别该菜品,确认结果稳定。
  4. 同步过程中断网或制造 SDK 校正失败,确认设备 B 仍能识别同步前的旧菜品。
  5. 杀进程后重新进入菜品管理,确认遗留 backup 能自动恢复,再次同步可成功。

Git 操作

本次仅修改和验证工作区文件,未主动执行暂存、提交、推送、切换分支、合并或变基。任务结束检查时发现索引中已有部分阶段性改动,同时工作区还有后续修复和未跟踪新文件;提交前必须以当前工作树重新核对并完整暂存,不能直接提交现有索引快照。