{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://git.yuntuo.hk/k2safe/orbit/schema/worker.v1.json", "title": "Orbit Pulse Worker v1", "description": "HTTP Upgrade 子协议 pulse.worker.v1 的 JSON 文本帧。根接受双向帧;clientFrame/serverFrame 可单独校验方向。状态、权限、消息关联、长度与租约约束仍由运行时执行。", "oneOf": [ { "$ref": "#/$defs/clientFrame" }, { "$ref": "#/$defs/serverFrame" } ], "$defs": { "id": { "type": "string", "pattern": "^[0-9a-f]{32}$", "description": "32 位小写十六进制资源/操作身份。" }, "uint64": { "type": "string", "pattern": "^(?:[1-9][0-9]{0,18}|1[0-7][0-9]{18}|18[0-3][0-9]{17}|184[0-3][0-9]{16}|1844[0-5][0-9]{15}|18446[0-6][0-9]{14}|184467[0-3][0-9]{13}|1844674[0-3][0-9]{12}|184467440[0-6][0-9]{10}|1844674407[0-2][0-9]{9}|18446744073[0-6][0-9]{8}|1844674407370[0-8][0-9]{6}|18446744073709[0-4][0-9]{5}|184467440737095[0-4][0-9]{4}|18446744073709550[0-9]{3}|18446744073709551[0-5][0-9]{2}|1844674407370955160[0-9]{1}|1844674407370955161[0-4]|18446744073709551615)$", "description": "1 至 18446744073709551615 的规范十进制字符串,不允许前导零。" }, "secret": { "type": "string", "pattern": "^[A-Za-z0-9_-]{42}[AEIMQUYcgkosw048]$", "description": "32 字节秘密的严格无填充 base64url,43 字符;禁止日志记录。" }, "time": { "type": "string", "format": "date-time", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\\.[0-9]{1,6})?Z$", "description": "服务端 UTC RFC 3339,最多微秒精度。" }, "json": { "not": { "type": "null" }, "description": "非 null 业务 JSON;256 KiB、数值文本和完整帧深度限制由运行时校验。" }, "capability": { "type": "object", "properties": { "handler": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.:-]*$" }, "handler_version": { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.:-]*$" }, "payload_version": { "type": "string", "minLength": 1, "maxLength": 32, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.:-]*$" } }, "required": [ "handler", "handler_version", "payload_version" ], "additionalProperties": false }, "attemptState": { "enum": [ "LEASED", "RUNNING", "SUCCEEDED", "FAILED", "CANCELLED", "EXPIRED", "UNKNOWN" ] }, "taskState": { "enum": [ "WAITING", "LEASED", "RUNNING", "SUCCEEDED", "FAILED", "CANCELLED", "NEEDS_REVIEW" ] }, "hello": { "type": "object", "properties": { "instance_id": { "$ref": "#/$defs/id" }, "instance_secret": { "$ref": "#/$defs/secret" }, "queue_id": { "$ref": "#/$defs/id" }, "capabilities": { "type": "array", "minItems": 1, "maxItems": 32, "uniqueItems": true, "items": { "$ref": "#/$defs/capability" } }, "capacity": { "type": "integer", "minimum": 1, "maximum": 256 } }, "required": [ "instance_id", "instance_secret", "queue_id", "capabilities", "capacity" ], "additionalProperties": false, "description": "重连保留身份、凭据、队列和能力,进程重启换新身份。" }, "capacity": { "type": "object", "properties": { "sequence": { "$ref": "#/$defs/uint64" }, "capacity": { "type": "integer", "minimum": 0, "maximum": 256 }, "drain": { "type": "boolean" } }, "required": [ "sequence", "capacity", "drain" ], "additionalProperties": false, "description": "覆盖容量,零暂不领取;drain 一旦生效不能清除。" }, "attemptRef": { "type": "object", "properties": { "task_id": { "$ref": "#/$defs/id" }, "attempt_id": { "$ref": "#/$defs/id" }, "epoch": { "$ref": "#/$defs/uint64" }, "lease_secret": { "$ref": "#/$defs/secret" } }, "required": [ "task_id", "attempt_id", "epoch", "lease_secret" ], "additionalProperties": false }, "finish": { "type": "object", "properties": { "ref": { "$ref": "#/$defs/attemptRef" }, "outcome": { "enum": [ "SUCCEEDED", "FAILED", "UNKNOWN" ] }, "result": { "$ref": "#/$defs/json" }, "error_code": { "type": "string", "maxLength": 64 } }, "required": [ "ref", "outcome", "result" ], "additionalProperties": false, "allOf": [ { "if": { "properties": { "outcome": { "const": "SUCCEEDED" } } }, "then": { "properties": { "error_code": { "const": "" } } }, "else": { "required": [ "error_code" ], "properties": { "error_code": { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.:-]*$" } } } } ] }, "welcome": { "type": "object", "properties": { "session_id": { "$ref": "#/$defs/id" }, "epoch": { "$ref": "#/$defs/uint64" }, "server_time": { "$ref": "#/$defs/time" }, "expires_at": { "$ref": "#/$defs/time" }, "lease_duration_ms": { "type": "integer", "minimum": 1000, "maximum": 120000 }, "draining": { "type": "boolean" } }, "required": [ "session_id", "epoch", "server_time", "expires_at", "lease_duration_ms", "draining" ], "additionalProperties": false }, "lease": { "type": "object", "properties": { "active": { "type": "boolean" }, "state": { "$ref": "#/$defs/attemptState" }, "lease_until": { "$ref": "#/$defs/time" }, "server_time": { "$ref": "#/$defs/time" } }, "required": [ "active", "state", "lease_until", "server_time" ], "additionalProperties": false, "description": "本次重新核验的授权;只有 active 且 RUNNING 并在本地保守期限内才能执行。", "allOf": [ { "if": { "properties": { "active": { "const": true } } }, "then": { "properties": { "state": { "enum": [ "LEASED", "RUNNING" ] } } } } ] }, "receipt": { "type": "object", "properties": { "operation": { "enum": [ "start", "renew", "finish" ] }, "task_state": { "$ref": "#/$defs/taskState" }, "attempt_state": { "$ref": "#/$defs/attemptState" }, "task_revision": { "$ref": "#/$defs/uint64" }, "lease_until": { "$ref": "#/$defs/time" }, "disposition": { "enum": [ "APPLIED", "EVIDENCE_ONLY" ] } }, "required": [ "operation", "task_state", "attempt_state", "task_revision", "lease_until", "disposition" ], "additionalProperties": false, "description": "稳定操作身份的原始不可变回执,不提供当前执行权。" }, "commandResult": { "type": "object", "properties": { "receipt": { "$ref": "#/$defs/receipt" }, "lease": { "$ref": "#/$defs/lease" }, "deduplicated": { "type": "boolean" } }, "required": [ "receipt", "lease", "deduplicated" ], "additionalProperties": false }, "retry": { "type": "object", "properties": { "max_attempts": { "type": "integer", "minimum": 1, "maximum": 100 }, "initial_delay_ms": { "type": "integer", "minimum": 0, "maximum": 9223372036854 }, "max_delay_ms": { "type": "integer", "minimum": 0, "maximum": 9223372036854 }, "attempt_timeout_ms": { "type": "integer", "minimum": 1, "maximum": 2592000000 } }, "required": [ "max_attempts", "initial_delay_ms", "max_delay_ms", "attempt_timeout_ms" ], "additionalProperties": false }, "assignedTask": { "type": "object", "properties": { "id": { "$ref": "#/$defs/id" }, "namespace_id": { "$ref": "#/$defs/id" }, "queue_id": { "$ref": "#/$defs/id" }, "state": { "const": "LEASED" }, "revision": { "$ref": "#/$defs/uint64" }, "handler": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.:-]*$" }, "handler_version": { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.:-]*$" }, "payload_version": { "type": "string", "minLength": 1, "maxLength": 32, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.:-]*$" }, "payload": { "$ref": "#/$defs/json" }, "result": { "$ref": "#/$defs/json" }, "business_key": { "type": "string", "maxLength": 191 }, "available_at": { "$ref": "#/$defs/time" }, "start_deadline_at": { "$ref": "#/$defs/time" }, "deadline_at": { "$ref": "#/$defs/time" }, "recovery_safety": { "enum": [ "IDEMPOTENT", "RECONCILE_ONLY" ] }, "retry": { "$ref": "#/$defs/retry" }, "attempt_count": { "type": "integer", "minimum": 1, "maximum": 100 }, "cancel_requested_at": { "$ref": "#/$defs/time" }, "completed_at": { "$ref": "#/$defs/time" }, "created_at": { "$ref": "#/$defs/time" }, "updated_at": { "$ref": "#/$defs/time" } }, "required": [ "id", "namespace_id", "queue_id", "state", "revision", "handler", "handler_version", "payload_version", "payload", "available_at", "deadline_at", "recovery_safety", "retry", "attempt_count", "created_at", "updated_at" ], "additionalProperties": false }, "assignment": { "type": "object", "properties": { "task": { "$ref": "#/$defs/assignedTask" }, "attempt_id": { "$ref": "#/$defs/id" }, "epoch": { "$ref": "#/$defs/uint64" }, "lease_secret": { "$ref": "#/$defs/secret" }, "lease_until": { "$ref": "#/$defs/time" }, "server_time": { "$ref": "#/$defs/time" } }, "required": [ "task", "attempt_id", "epoch", "lease_secret", "lease_until", "server_time" ], "additionalProperties": false }, "error": { "type": "object", "properties": { "code": { "type": "string", "minLength": 1, "maxLength": 64, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.:-]*$" }, "message": { "type": "string", "maxLength": 1024 } }, "required": [ "code", "message" ], "additionalProperties": false, "description": "公开稳定分类,不包含 SQL、原始异常或秘密。" }, "helloFrame": { "type": "object", "properties": { "protocol_version": { "const": "1" }, "type": { "const": "worker.hello" }, "message_id": { "$ref": "#/$defs/id" }, "body": { "$ref": "#/$defs/hello" } }, "required": [ "protocol_version", "type", "message_id", "body" ], "additionalProperties": false }, "capacityFrame": { "type": "object", "properties": { "protocol_version": { "const": "1" }, "type": { "const": "worker.capacity" }, "message_id": { "$ref": "#/$defs/id" }, "session_id": { "$ref": "#/$defs/id" }, "body": { "$ref": "#/$defs/capacity" } }, "required": [ "protocol_version", "type", "message_id", "session_id", "body" ], "additionalProperties": false }, "resumeFrame": { "type": "object", "properties": { "protocol_version": { "const": "1" }, "type": { "const": "worker.resume" }, "message_id": { "$ref": "#/$defs/id" }, "session_id": { "$ref": "#/$defs/id" }, "body": { "$ref": "#/$defs/attemptRef" } }, "required": [ "protocol_version", "type", "message_id", "session_id", "body" ], "additionalProperties": false }, "startFrame": { "type": "object", "properties": { "protocol_version": { "const": "1" }, "type": { "const": "task.start" }, "message_id": { "$ref": "#/$defs/id" }, "session_id": { "$ref": "#/$defs/id" }, "body": { "$ref": "#/$defs/attemptRef" } }, "required": [ "protocol_version", "type", "message_id", "session_id", "body" ], "additionalProperties": false }, "renewFrame": { "type": "object", "properties": { "protocol_version": { "const": "1" }, "type": { "const": "task.renew" }, "message_id": { "$ref": "#/$defs/id" }, "session_id": { "$ref": "#/$defs/id" }, "body": { "$ref": "#/$defs/attemptRef" } }, "required": [ "protocol_version", "type", "message_id", "session_id", "body" ], "additionalProperties": false }, "finishFrame": { "type": "object", "properties": { "protocol_version": { "const": "1" }, "type": { "const": "task.finish" }, "message_id": { "$ref": "#/$defs/id" }, "session_id": { "$ref": "#/$defs/id" }, "body": { "$ref": "#/$defs/finish" } }, "required": [ "protocol_version", "type", "message_id", "session_id", "body" ], "additionalProperties": false }, "welcomeFrame": { "type": "object", "properties": { "protocol_version": { "const": "1" }, "type": { "const": "worker.welcome" }, "message_id": { "$ref": "#/$defs/id" }, "session_id": { "$ref": "#/$defs/id" }, "reply_to": { "$ref": "#/$defs/id" }, "body": { "$ref": "#/$defs/welcome" } }, "required": [ "protocol_version", "type", "message_id", "session_id", "reply_to", "body" ], "additionalProperties": false }, "assignmentFrame": { "type": "object", "properties": { "protocol_version": { "const": "1" }, "type": { "const": "task.assign" }, "message_id": { "$ref": "#/$defs/id" }, "session_id": { "$ref": "#/$defs/id" }, "body": { "$ref": "#/$defs/assignment" } }, "required": [ "protocol_version", "type", "message_id", "session_id", "body" ], "additionalProperties": false }, "ackFrame": { "type": "object", "properties": { "protocol_version": { "const": "1" }, "type": { "const": "ack" }, "message_id": { "$ref": "#/$defs/id" }, "session_id": { "$ref": "#/$defs/id" }, "reply_to": { "$ref": "#/$defs/id" }, "body": { "oneOf": [ { "$ref": "#/$defs/welcome" }, { "$ref": "#/$defs/lease" }, { "$ref": "#/$defs/commandResult" } ] } }, "required": [ "protocol_version", "type", "message_id", "session_id", "reply_to", "body" ], "additionalProperties": false }, "errorFrame": { "type": "object", "properties": { "protocol_version": { "const": "1" }, "type": { "const": "error" }, "message_id": { "$ref": "#/$defs/id" }, "session_id": { "$ref": "#/$defs/id" }, "error": { "$ref": "#/$defs/error" }, "reply_to": { "$ref": "#/$defs/id" } }, "required": [ "protocol_version", "type", "message_id", "error" ], "additionalProperties": false, "description": "注册失败可省略 session_id;会话内错误必须带当前会话。异步致命错误无 reply_to,其余与请求关联。" }, "clientFrame": { "oneOf": [ { "$ref": "#/$defs/helloFrame" }, { "$ref": "#/$defs/capacityFrame" }, { "$ref": "#/$defs/resumeFrame" }, { "$ref": "#/$defs/startFrame" }, { "$ref": "#/$defs/renewFrame" }, { "$ref": "#/$defs/finishFrame" } ] }, "serverFrame": { "oneOf": [ { "$ref": "#/$defs/welcomeFrame" }, { "$ref": "#/$defs/assignmentFrame" }, { "$ref": "#/$defs/ackFrame" }, { "$ref": "#/$defs/errorFrame" } ] } } }