@@ -12,7 +12,8 @@
**核心:Admin 是调度器,Client 是执行器,执行器不参与调度决策。 **
- Client 只有三个动作:领一个任务、提交结果、提交失败。**没有任何"去问 Admin 现在怎么想"的调用。**
- Client 的任务流程 只有三个动作:领一个任务、提交结果、提交失败。
设置页另有一个幂等 Client 登记动作。**没有任何"去问 Admin 现在怎么想"的调用。**
- Client 拿到任务就做完,中途不管任务是否被取消、是否被重派。
- Admin 负责任务的创建、更新、取消和派发(含重派),这些 Client 一律不感知。
- 结果提交必须幂等;网络重试不能创建重复结果。
@@ -109,6 +110,59 @@ Idempotency-Key: <stable-key>
任务对象里**不含 Admin 侧状态**。Client 不关心 Admin 那边把它标成什么,只管做完提交。
## 4.1 登记或更新 Client
``` http
P U T / a p i / v 1 / c l i e n t / r e g i s t r a t i o n
X - C l i e n t - I d : < s t a b l e - c l i e n t - i d >
X - R e q u e s t - I d : < u u i d >
```
请求:
``` json
{
"client" : {
"name" : "办公室-01"
} ,
"supported_types" : [ "collect" , "purchase" ] ,
"device" : {
"address" : "192.168.0.173:5555" ,
"platform" : "android" ,
"pdd_package" : "com.xunmeng.pinduoduo"
} ,
"capabilities" : {
"purchase_mode" : "dry_run" ,
"schema_versions" : [ 1 ]
}
}
```
成功统一返回 `200 OK` :
``` json
{
"registered" : true ,
"client_id" : "CLIENT-123456" ,
"registered_at" : "2026-08-06T09:00:00Z"
}
```
规则:
- `[必须]` `X-Client-Id` 是 Client 唯一键;相同编号重复 `PUT` 执行幂等 upsert,不创建重复记录。
- `[必须]` 登记接口不读取、领取或修改任务,也不返回任务。
- `[必须]` `client.name` 可选且最多 50 字。显式登记携带非空名称时允许更新 Admin 名称;空名称更新保留已有名称,新建时用 Client ID 兜底。
- `[必须]` 更新设备、能力、`last_seen_at` 和 `updated_at` 。
- `[必须]` `supported_types` 非空且只包含 `collect` 、`purchase` ; `purchase_mode` 只允许 `dry_run` 、`live` ; `schema_versions` 只包含正整数。
- `[必须]` Client 必须先把设备号和名称保存到 SQLite,再在后台线程调用本接口;远端失败不得回滚本地保存。
- `[必须]` 设备号生成后稳定复用,不向 Admin 发送生成设备号所用的原始硬件参数。
- `[必须]` 不增加定时心跳。在线状态仍由登记、领取和提交产生的 `last_seen_at` 派生。
错误至少包括 `MISSING_CLIENT_ID` 、`INVALID_BODY` 、`INVALID_CLIENT_PROFILE` 和 `CLIENT_REGISTER_FAILED` ,并使用 §3 的统一结构。
`claim` 继续支持隐式登记作为旧 Client 的兼容兜底:新编号可以创建 Client,已有 Client 只更新设备、能力和最近活动时间,不覆盖名称。
## 5. 领取任务
``` http
@@ -145,12 +199,11 @@ POST /api/v1/client/tasks/claim
无可领取任务时返回 `204 No Content` 。
`[必须]` * * `204` 不是错误。** 新客户端第一次调 `claim` 必然是 204——
它刚被登记,还没有人给它分配任务。Client 要把它当"暂时没活干"处理,
不要报错,也不要因此触发重试风暴。
`[必须]` * * `204` 不是错误。** Client 要把它当"暂时没活干"处理,
不要报错,也不要因此触发重试风暴。首次 claim 通常返回 204;如果该编号已经预先分配任务,也可以直接返回 200。
`client.name` 是给人看的显示名,可以不填(不填 时 Admin 用 `X-Client-Id` 兜底)。
它** 只在首次登记 时被采纳**,之后操作员在 Admin 改 的名字 不会被客户端覆盖 。
`client.name` 是给人看的显示名,可以不填(新建 时 Admin 用 `X-Client-Id` 兜底)。
在 claim 兼容登记中, 它只在首次创建 时被采纳,已有 Client 的名称 不会被后台领取覆盖;用户通过 §4.1 显式保存非空名称时可以更新 。
> 怎么把这条链路跑通、怎么确认设备登记成功,见
> [Admin 侧的设备登记联调手册](../admin/07-设备登记联调手册.md)。
@@ -266,9 +319,10 @@ Idempotency-Key: task-id:attempt-id:failure-v1
## 9. Mock Admin 要求
`MockAdminGateway` 与 HTTP 实现暴露同一应用层接口,只有三个方法 :
`MockAdminGateway` 与 HTTP 实现暴露同一应用层接口。登记和三个任务方法都必须使用同一契约 :
``` text
register_client(client, capabilities) # §4.1
claim_next(client, capabilities) # §5
submit_result(task_id, idempotency_key, result) # §6
submit_failure(task_id, idempotency_key, failure) # §7
@@ -300,7 +354,7 @@ Admin 还没做完,下面这些要和 Admin 一起定。**不许因此停工**
**已定案(不再是待确认项): **
- Admin 只把任务分配给指定 Client,Client 不读全局任务池。见 §5.1。
- **没有租约、没有心跳、没有状态回查。** Client 只有 §5 / §6 / §7 三个调用。见 §1 .1。
- **没有租约、没有心跳、没有状态回查。** 任务流程 只有 §5 / §6 / §7 三个调用;设置页另有 §4 .1 的幂等登记调用 。
- Admin 必须无条件接受已派发过的 Client 提交的结果。见 §6.1。
改动这张表里任何一条,都属于会影响业务结果的变更,必须先更新工单并经用户确认。