Skip to content

异步任务、版本、幂等与恢复 ​

1. 解决什么问题 ​

模型、图片和音频可能超时,worker 可能退出,用户也可能在素材制作中修改内容。可靠执行要处理“重复请求、执行结果不明、旧结果迟到”,不能只在异常后重新调用一次。

2. 原理与术语 ​

幂等键识别同一业务意图;租约限制 worker 持有任务的时间;心跳延长租约;fencing 令牌阻止旧执行者提交任务状态。业务版本决定哪些结果可交付,文件 receipt 则帮助恢复已经落盘但未完成数据库记录的素材。

3. 输入输出与执行 ​

claim 用 FOR UPDATE SKIP LOCKED 领取可运行且依赖已完成的任务,增加 attempts 并生成 lease_token。执行发生在短事务之外,完成时只有仍持有令牌的 worker 能提交。状态包括 ready、running、retry、unknown、failed、succeeded、superseded。

4. 容易混淆 ​

超时不等于外部服务没执行;租约过期也不能撤销已经发出的请求。任务去重不保证供应商只收费一次。Checkpointer 管流程,任务表管调度,教材版本管发布事实,三者不能相互替代。

5. 最小示例 ​

python
from app.db import digest
assert digest({"kind":"audio","text":"你好"}) == digest({"text":"你好","kind":"audio"})
assert digest({"version":1}) != digest({"version":2})

稳定摘要只是识别输入的基础,真正并发去重依赖数据库唯一约束,不能用一次字典查询替代。

6. 实际实现 ​

自动重试受 MAX_ATTEMPTS 限制,退避为指数增长并封顶 30 秒,当前没有随机抖动。真实图片或 TTS 的超时、网络错误和部分服务错误进入 unknown。恢复先检查本地持久 receipt;当前适配器没有供应商任务查询能力,缺证据时不能自动重发。

7. 源码与数据结构 ​

阅读 system/app/worker.py::claim/heartbeat/recover_expired/run_once、db.py::enqueue/save_version、media.py::reconcile 和 api.py::resolve。tasks 的 dedup_key、lease_token、available_at、version 分别承担不同责任。

8. 取舍与边界 ​

新内容版本将旧未完成素材标记 superseded;交付检查只接受当前批准版本的完整任务集合。素材文件按输入指纹存储,可复用相同输入。真实外部结果不明时要求用户明确接受重复风险再重试,承认边界比虚构恰好一次可靠。

9. 实验与验收 ​

演示模式创建故障场景并通过人工审核:

bash
curl -s -H "X-API-Key: ${LAB_API_KEY:-}" -H 'Content-Type: application/json' \
  -d '{"theme":"校园生活","scenario":"media_timeout"}' http://127.0.0.1:8000/api/jobs

检查图片首次安全注入失败、attempts 增加、随后成功。再编辑一个课文块并重新审核,比较新旧任务版本与复用事件。该超时发生在演示提交前,不能用它证明真实服务超时后自动重试安全。

10. 故障排查 ​

任务不领取先查依赖、available_at 和 attempts;running 长期不结束查心跳;unknown 查 receipt;旧结果问题查 current_version 和 lease_token。人工重试会重新开放尝试预算,但操作应有记录,不应把反复点击当成自动恢复策略。

11. 面试题与追问 ​

问:如何防止旧结果覆盖新版本? 旧任务失效、提交令牌检查、交付版本门同时约束。追问:外部已成功但程序没收到呢? 核对持久结果,无法确认则保留 unknown。再追问:为什么不承诺 exactly-once? 数据库事务无法原子覆盖第三方 API;没有对方幂等或查询契约时存在不可消除的不确定窗口。

STAR 应用:假设实验场景,R 为应核对的证据
对应S:情境T:目标A:行动R:验收证据
主问旧worker完成过期任务阻止旧状态覆盖核对版本与租约令牌旧任务不能使当前版本交付成功
追问一供应商成功但响应丢失避免盲目重复付费核对receipt;缺证据保留unknown明确结果不明而非静默重发
追问二被要求承诺恰好一次说明外部事务边界区分本地去重与供应商契约列出仍需人工核对的失败窗口

这些是设计讨论的参考表达,实际执行前不能改写为已取得的历史成果。

12. 官方资料与版本 ​

PostgreSQL 16 SELECT、显式锁、AWS 幂等重试。核验日期 2026-11-03;当前实现是数据库任务队列,不声称使用 Celery 或外部消息中间件。

学习复现系统 · 事实、实验与假设分开记录