取餐记录定时补传实现计划

执行方式:loop_upload_pick 分支按测试驱动方式逐项实现;所有步骤完成后执行 JDK 8 单元测试、Java 编译和 APK 构建验证。

目标: 仅修改 Android 端,为取餐记录增加固定 3 分钟、每轮最多 20 条、严格串行且全状态留痕的自动补传能力。

架构: 使用 AlarmManager 固定触发一次性唯一 WorkManager;纯 Java 处理器决定批次上限、串行顺序和断网停止;协调器统一实时上传与周期上传;SQLite 主表保存当前状态,追加日志表保存完整迁移轨迹。

技术栈: Java 8、SQLiteOpenHelper、WorkManager 2.5、AlarmManager、Retrofit、JUnit 4。


任务 1:建立可测试的补传策略

文件:

步骤:

  1. 先编写失败测试,覆盖 20 条上限、ID 顺序、同步逐条处理、单条失败继续、中途断网停止、无网络不处理、5g 阈值、服务端成功/拒绝/失败分类和失败 10 次封顶。
  2. 运行 :app:testDebugUnitTest,确认测试因生产类不存在而失败。
  3. 实现最小纯 Java 策略和处理器。
  4. 再次运行单元测试,确认全部通过。

任务 2:升级数据库和状态日志

文件:

步骤:

  1. 数据库版本从 2 升至 3。
  2. 主表增加 retry_countlast_attempt_timelast_error_codelast_error_messageupload_updated_at
  3. 新建 pick_record_upload_log 追加日志表和查询索引。
  4. 增加最早优先且最多 20 条的查询、PENDING/FAILED -> UPLOADING 原子占用、结果落库、IGNORED/REJECTED/FAILED_FINAL 终态和 10 分钟占用恢复。
  5. 编译验证所有字段映射和接口签名。

任务 3:统一实时上传与周期补传

文件:

步骤:

  1. 协调器复用现有 uploadPickMealInfo 同步请求,不修改接口字段。
  2. 实时上传继续最多尝试 3 次,但每次失败都计入总失败次数 10 次上限。
  3. 周期补传每条只请求一次,失败后继续下一条。
  4. 小于 5g 或关键数据无效的记录标记为 IGNORED
  5. code=0 标记 UPLOADEDcode=1 标记 REJECTED,其余错误标记 FAILED/FAILED_FINAL
  6. Activity 保留原成功、拒绝和失败提示/日志入口。

任务 4:接入 3 分钟唯一后台任务

文件:

步骤:

  1. App 初始化后安排第一次 3 分钟闹钟。
  2. 闹钟触发后立即续订下一次,并在有网络时提交唯一 Worker。
  3. Worker 开始时再次检查网络、恢复超时占用、执行最多 20 条的串行批次。
  4. 使用 ExistingWorkPolicy.KEEP 和数据库原子占用避免任务重叠。
  5. 无网络时不选取记录、不修改状态和重试次数。

任务 5:验证和交付记录

文件:

验证命令:

JAVA_HOME=$(/usr/libexec/java_home -v 1.8) bash ./gradlew :app:testDebugUnitTest --no-daemon
JAVA_HOME=$(/usr/libexec/java_home -v 1.8) bash ./gradlew :app:compileDebugJavaWithJavac --no-daemon
JAVA_HOME=$(/usr/libexec/java_home -v 1.8) bash ./gradlew :app:assembleDebug --no-daemon
git diff --check

完成标准: