Billing implements reserve -> commit -> refund against bl_quota and bl_ledger with row-level locking and idempotency keys; the refund commits on its own transaction so a failed request cannot silently keep a user's quota. Task implements the unified task centre over the state machine. Identity issues and resolves users. Remaining domains are placeholders whose READMEs state what belongs there and what must not.
packages/task/ — 统一任务中心
全系统唯一的长耗时任务视图(架构 §6.2、ADR-14)。报告、换装、发型、抠图、
渲染全部走这里,前端任务中心直接读 tk_task。
铁律
不要在业务域里自建任务状态字段。 每个功能各自实现一遍任务状态、进度、 幂等、重试,集成时会全部返工 —— 这正是 M1 存在的理由。
已实现
tk_task表与状态机(packages/domain/task/state.py,纯逻辑可单测)- 幂等提交(相同
idempotency_key返回同一任务,不重复扣点,FR-TASK-05) - 归属校验(架构 §11.1)
- Celery 四队列(gpu/cpu/io/beat)与一个贯通的
ping任务
待实现
| 需求 | 内容 |
|---|---|
| FR-TASK-02 | 进度与预估时间(阶段文案 + 排队位次 + 基于历史 p50 的预估) |
| FR-TASK-06 | 任务取消:排队中可取消并退点;执行中标记取消不再返回结果 |
| FR-TASK-07 | 死信队列与告警:连续失败进死信并告警,不静默丢弃 |
| — | beat 防重(单实例);自动重试与上限 |
状态机
pending → queued → running → succeeded
↓ ↓ ↓ ↘ failed → queued(重试)
failed failed canceled canceled
终态是 succeeded / failed / canceled;只有 failed 可以重新入队。
非成功终态必须触发配额退还(needs_refund())。
排队时间与执行时间必须分开统计
架构 §12.1:混在一起看会得出错误结论 —— 明明是 GPU 容量不足(该扩容), 却被误判为推理慢(去优化模型)。