feat: add durable relative task delays and outage recovery regression

This commit is contained in:
2026-09-17 23:43:57 +08:00
parent 522fe2ef3e
commit a664ec9370
34 changed files with 811 additions and 28 deletions

View File

@@ -20,6 +20,7 @@
| 任务 `priority` 与节点领取池 | P3 已实现有界优先级加速、应用/队列轮转 | [优先级与公平派发](priority-and-fairness.md) |
| 凭据校验与初始化 CLI | P1 已实现 | [鉴权](authentication.md) |
| `/v1/worker/connect` | P2 已实现并通过阶段验收 | [Worker 契约](worker.md)、[Schema](worker-schema.md) |
| 任务相对延迟 `delay_ms` | 已实现数据库计时、原键恢复与实际执行例子 | [任务接口](tasks.md)、[延迟示例](../examples/delayed-task.md) |
| 任务冻结策略与 Worker `retryable` | P3 安全重试已实现 | [安全重试](retries.md) |
| `/v1/tasks/{task_id}:cancel` 与 `task.cancel` 通知 | P3 运行中取消已实现 | [取消及 SDK 场景](cancellation.md) |
| `/v1/schedules`、不可变版本、暂停/恢复及触发查询 | P3 已实现 | [计划接口与 SDK 场景](schedules.md) |

View File

@@ -52,7 +52,9 @@ available_at = 本次结束事务中的数据库时间 + delay_ms
- 等待重试期间不占执行许可,任务不带 result/completed_at;上一尝试的错误和结果保留在 [执行历史](execution-history.md)。NEEDS_REVIEW 也没有 completed_at。
- 重启后以数据库 available_at 继续领取,不依赖某一节点内存中的定时器。
`task.requeued` 等持久化事件记录 decision、delay_ms、next_available_at、attempt_count、max_attempts、effect_uncertain。decision 包括 RETRYABLE_FAILURE、IDEMPOTENT_UNKNOWN、UNSTARTED_LEASE_EXPIRED、ATTEMPT_LIMIT、DEADLINE_EXCEEDED、RECONCILIATION_REQUIRED 等。当前可靠事件订阅尚未开放。
`task.requeued` 等内部持久化事件记录 decision、delay_ms、next_available_at、attempt_count、max_attempts、effect_uncertain。decision 包括 RETRYABLE_FAILURE、IDEMPOTENT_UNKNOWN、UNSTARTED_LEASE_EXPIRED、ATTEMPT_LIMIT、DEADLINE_EXCEEDED、RECONCILIATION_REQUIRED 等。[可靠结果订阅](subscriptions.md)已开放规定的结果类型;内部重排事件不自动成为外部可订阅类型。
提交参数`delay_ms`只控制首次受理的最早执行时间;它与这里按每次失败计算的退避分别定义。真实进程回归已覆盖退避期间唯一节点退出、两个新节点竞争恢复,以及停机期间总时限耗尽;冻结策略、已用次数和未知效果均保留,见[验证记录](../reports/phase-3-delay-recovery.md)。
取消接口支持独立任务和计划任务的 WAITING、LEASED、RUNNING 与 NEEDS_REVIEW。取消意图阻止后续尝试;运行中继续收集结果,普通取消错误或失联保持 UNKNOWN,不因 IDEMPOTENT 声明再次执行。此前未核实的效果不会被本次确认取消清除,详见 [取消状态与结果表](cancellation.md)。

View File

@@ -54,7 +54,7 @@ Cron 段顺序为分钟、小时、月日、月、星期;支持 `*`、列表
| catchup_window_ms | 必填 1000–2592000000,未处理触发点最多保留的时间窗口 |
| grace_ms | 必填 1000–60000,正常派发允许延迟;不能超过 catchup_window_ms |
所有任务策略在 task 内冻结,字段同 SubmitTaskRequest;payload 最大 256 KiB,数字文本保持精确。task 中禁止绝对 available_at / start_deadline_at,每次生成时立即可受理,task_timeout_ms 从本次实际创建时间计算。计划结束不取消已经生成的任务,也不缩短其任务时限。
所有任务策略在 task 内冻结,字段同 SubmitTaskRequest;payload 最大 256 KiB,数字文本保持精确。task 中禁止绝对 available_at / start_deadline_at 和非零 delay_ms,时间由计划规则定义,不静默忽略这些字段。每次生成时立即可受理,task_timeout_ms 从本次实际创建时间计算。计划结束不取消已经生成的任务,也不缩短其任务时限。
生成任务受 [队列积压上限](queues.md) 约束。满额时保留未受理触发点,本批较早已生成部分仍提交;释放空间后按冻结的漏跑策略接续,超过补偿窗口的点仍按策略跳过。队列 paused 仅停止领取/开始,停止计划生成需使用计划暂停接口。

View File

@@ -26,6 +26,7 @@ P2 进展:服务端执行内核、WSS 与独立自动 Worker SDK 已可产生
| business_key | string | 可选 | 最多 191 个 Unicode 字符,无 NUL/换行;用于关联,不提供业务幂等 |
| concurrency_key | string | 可选,空为关闭 | 1–191 个 Unicode 字符,无控制字符和首尾空白;显式资源互斥键,同命名空间跨队列共享,见 [资源键契约](keyed-concurrency.md) |
| priority | 整数 | 可选,默认 0 | 0–9,冻结优先级,每级30秒排序优势;不提前延时任务,见 [优先级与公平派发](priority-and-fairness.md) |
| delay_ms | uint64 | 可选,默认 0 | 相对首次受理事务数据库时间的等待毫秒数,必须小于 task_timeout_ms;非零不能与 available_at 同用 |
| available_at | time / null | 受理时数据库时间 | 最早可执行时间;必须早于总截止时间,仅允许最多 1 秒的过去时间容差 |
| start_deadline_at | time / null | 无独立限制 | 必须晚于当前时间,不早于 available_at,不晚于总截止时间 |
| task_timeout_ms | uint64 | 0 或省略为 86400000 | 从受理时计算的总时限,最大 30 天(2592000000 毫秒) |
@@ -34,6 +35,10 @@ P2 进展:服务端执行内核、WSS 与独立自动 Worker SDK 已可产生
处理器及版本名称以 ASCII 字母或数字开头,后续只能包含字母、数字、`_ . : -`。时间年份为 2000–9998。
相对延迟通过`delay_ms`提交:首次受理时保存`available_at = created_at + delay_ms`,同键重报返回原受理回执,不能重新计时。`delay_ms`省略或0保留原有立即/绝对时间语义;负数、小数、字符串、null和溢出值均拒绝。总时限包含等待,最晚开始时间仍须满足上表。任务响应不新增delay_ms;当前available_at可能在安全重试后变为下一次退避时间,首次时间以原提交回执为准。见[完整SDK示例](../examples/delayed-task.md)。
批量每项支持相同字段,各项使用自己的首次受理数据库时间。相对时长和绝对时刻属于不同请求语义,即使碰巧对应相同时间,也不能在原幂等键下互换。启用delay_ms前先更新服务端;旧服务会拒绝未知字段,省略/零值不改变已有请求摘要。
| retry 字段 | 默认与限制 |
| --- | --- |
| max_attempts | 0 或省略为 1;范围 1–100,包含首次尝试 |