Files

5.8 KiB
Raw Permalink Blame History

第三方任务发现事件游标分页 v0.3(项目内提案)

仅替换 v0.2 §2.5 的任务发现目标;其他 SaaS 项目内业务接口仍按 v0.1。设计依据为 plan-0926.md。本文件、Schema 和 Mock 未经 SaaS/业务签收,不是现网接口或生产合同;当前本地仅运行 v0.3;v0.2 仅作历史,真实 SaaS 尚未切换。

2.5 唯一任务发现路径

GET /internal/v1/dispatcher/tasks?after=<cursor> 由指定 Dispatcher 使用既有 X-DISPATCHER-id / X-DISPATCHER-SECRET-KEY 读取自己的任务。首次无本协议游标时发送 after=0;之后只发送已和任务状态一起持久化的 next_cursor。after 是该 D 范围内单调、不可复用的事件 ID,不是任务 ID、页号或任务配置版本。规范形式是无前导零的十进制 uint64 字符串;只允许起点为 0。D 身份不可更换来绕过游标。

所有 HTTP 200 均采用同一形状:schema_version=task-discovery.v0.3-proposal、dispatcher_id、tasks[] 和 next_cursor。tasks[] 中每项为 task_id、tenant_id、原值 tenant_key、status、task_revision;没有 changes、operation、snapshot、mode、单项 event_id、SaaS 队列名或任务页 token。同一任务有更晚的事件时可再次出现。SaaS 对每个任务只需返回最新状态,不要求回放所有中间状态;已有任务的 status 变化更新 SaaS 状态;新 paused、stopped、finished、removed 可关闭或保持准入。**后续 running(即使更新且已持久化)只更新 SaaS 状态与游标,不直接解除已持久的 paused;必须收到 MQ resume 并由任务只读接口新鲜确认 running 才能重开原队列。**其他字段仍须校验身份、版本及归属。任务具体执行配置仍由独立只读接口取得,不由发现列表取代。

SaaS 在响应中按其事件序号升序选取尚未返回的最新任务记录。每页至多 256 项,活动任务总量仍受单 D 256 上限约束;撤销墓碑的累计数量不在这个活动上限之内。非空页的 next_cursor 必须是最后一个实际返回任务的事件 ID,并严格大于请求的 after,绝不能前进到尚未返回的更新之后。空页表示本轮追平,tasks=[] 且 next_cursor=after;D 可在首次追平后开放经核验的新执行,其后约 30 秒再次查询。不得依靠“不足 256 项”断定追平:无论每页实际数量,D 都必须继续读取直到空页。若页内同一任务重复出现、任务身份发生冲突或游标不前进,D 拒绝整页而不是挑一条使用。

信任边界:用户确认仅返回响应级 next_cursor,不返回每项 event_id。D 可以验证游标形式、单调前进、响应身份和任务数据,但不能独立证明 SaaS 的页内顺序及没有漏项;SaaS 必须保证选择完整、有序、无跳跃,真实 SaaS 签收及并发分页故障测试属于外部门禁。Mock 正例不代签这一保证。

状态和撤销

status 只允许 running、paused、stopped、finished、removed。removed 是该 D 归属撤销的任务墓碑,必须保留原任务/租户身份;某任务没有出现在本页不表示撤销。SaaS 先持久化 stop/撤销及其必要回执、协调自己拥有的任务队列退役,再发出墓碑;D 收到后停止新接纳,不清理执行恢复、已入队结果、幂等或未知占用,也不自动强挂在途通话。paused 保留原积压;MQ 控制即时执行,不等轮询。发现页无论新旧 running 均不解除已持久的 paused/stopped 屏障;stopped 同任务不可逆,removed 不撤销旧执行事实。

一致性、错误和恢复

  • 任务页与游标同一 SQLite 事务提交;页提交失败不能推进游标。首次启动/恢复在读到空页并完成授权、归属和 SaaS 预建队列核验前不消费执行消息。中途失败、响应无效或网络不可用时保留本地任务、控制、执行事实与错误记录,拒绝新执行;MQ 即时控制仍继续。不能拿空列表推断未返回任务已经 removed。
  • 游标永不过期:不提供 410 或 cursor_expired,也不因时间推移要求 D 自动从零重建。SaaS 必须长期维护每个任务可追溯的最新事件位置和撤销墓碑;对任意曾提交的 D 游标,不能返回遗漏后续状态的伪造空页。after=0 的首次分页同样有界而不一次返回全部。序号回退、持久记录丢失或无法证明连续时返回明确错误,D fail-closed 并等待处理,不暗中重置。
  • HTTP 错误:400 invalid_cursor、401 unauthorized、403 dispatcher_not_authorized、503 service_unavailable;成功只允许 200。返回体按本版本严格 Schema,错误正文不含任务或凭据。具体身份、响应大小与实际 SaaS 系统行为仍待签收。
  • 当前 v0.2 游标不能重解释为事件 ID;切换前必须核验旧任务、积压与在途执行安全收口。新版只运行一个任务发现消费者,不保留旧 changes/410/分页 token 兼容路径或 HTTP→MQ 回退。SaaS 独占建队、绑定和退役,D 只消费预建队列。

验收及容量阻断

本地 Mock 要覆盖初始多页、空页、同一任务再出现、撤销、跨页并发更新、重启原游标续读、重复页、事务回滚、发现页 paused→running 后准入仍暂停直到 MQ resume+新鲜任务核验、暂停/停止竞态和 queue-only 消费;所有关键边界 fail-closed,不重拨。实时控制与最终结果的其他 v0.1 业务合同不变。活动任务 256 上限不约束永久墓碑;历史撤销增长、离线追赶时间、SaaS 数据保留及灾备后序号连续性未签收,不能声称容量有界或真实联调/生产可用。