2026-07-13 取餐记录定时补传实现

背景

原取餐记录在取餐结束后实时上传,失败时只在当前流程内重试,最终进入 FAILED 后没有后台消费者继续补传。网络中断、App 重启或请求临时异常时,记录可能长期留在本地。

本次按照已确认方案,仅修改 Android 端,不修改 /p/api/zhctPushMeal 接口字段和服务端逻辑。

实现内容

固定周期与单批上限

状态与重试规则

新增并统一使用以下状态:

实时上传继续最多尝试 3 次,失败次数计入同一个 retry_count;周期补传中每条记录每轮只请求一次,单条失败但网络仍可用时继续处理下一条。

数据库升级

CustomDBHelper 数据库版本从 2 升至 3。

取餐记录表新增:

新增 pick_record_upload_log 追加日志表,记录批次 ID、触发来源、前后状态、尝试次数、请求起止时间、结果码、错误分类和错误摘要。

增加以下保护:

上传链路统一

主要代码文件

测试

新增 JUnit 测试:

验证记录

基线验证:

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

结果:修改前 BUILD SUCCESSFUL in 22s

TDD RED:新增测试后,生产策略类尚未实现,:app:compileDebugUnitTestJavaWithJavac 按预期失败,错误为找不到 PickMealUploadPolicyPickMealRetryProcessorPickMealUploadResult

TDD GREEN:

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

结果:BUILD SUCCESSFUL in 19s

Java 编译:

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

结果:BUILD SUCCESSFUL in 19s

数据库迁移 SQL 使用内存 SQLite 验证,v3 主表为 17 列,上传日志表为 13 列,索引创建成功。

APK 构建:

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

结果:BUILD SUCCESSFUL in 59s,输出 app/build/outputs/apk/debug/app-debug.apk

最终验证门:

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

结果:命令退出码为 0;JUnit 共 10 项测试,failures=0errors=0;debug APK 大小约 59MB;git diff --check 无输出。

风险与设备验收

设备验收建议:

  1. 准备 21 条 FAILED,确认第一轮最多 20 条、下一轮 1 条。
  2. 补传过程中断网,确认未处理记录保持原状态。
  3. 将一条记录置为超时 UPLOADING,确认恢复为 FAILED
  4. 核对 pick_record_upload_log 中每次占用和结果状态成对出现。
  5. 确认历史 UPLOADED 记录不进入补传队列。