Add persistent Run control stream

This commit is contained in:
npc0-hue
2026-08-26 23:05:40 +08:00
parent 3b4e857ef7
commit ac14f80306
8 changed files with 245 additions and 9 deletions
+20
View File
@@ -2,6 +2,12 @@ package protocol
import "time"
const (
RunControlEventTypeReady = "control.ready"
RunControlEventTypeHeartbeat = "control.heartbeat"
RunControlEventTypeJobChanged = "job.changed"
)
type RunCapacityReport struct {
MaxJobs int `json:"maxJobs"`
RunningJobs int `json:"runningJobs"`
@@ -60,6 +66,20 @@ type RunHeartbeatResponse struct {
ServerTime time.Time `json:"serverTime"`
}
type RunControlStreamRequest struct {
RunEndpointID string `json:"runEndpointId"`
SessionToken string `json:"sessionToken"`
LastEventSeq uint64 `json:"lastEventSeq,omitempty"`
}
type RunControlEvent struct {
RunEndpointID string `json:"runEndpointId"`
Sequence uint64 `json:"sequence"`
Type string `json:"type"`
ServerTime time.Time `json:"serverTime"`
RetrySeconds int `json:"retrySeconds,omitempty"`
}
type RunLifecycleReportRequest struct {
RunEndpointID string `json:"runEndpointId"`
SessionToken string `json:"sessionToken"`
+4
View File
@@ -6,6 +6,7 @@ Control is the lightweight high-priority channel between run and platform.
- `POST /api/v1/run/control/hello`: registers run metadata and receives a platform-issued session token.
- `POST /api/v1/run/control/heartbeat`: reports status, capacity, and capability fingerprint using the active session token.
- `POST /api/v1/run/control/events`: opens a signed `text/event-stream` control channel. Platform sends small wake events such as `control.ready`, `control.heartbeat`, and `job.changed`; Run then claims durable jobs through the job channel.
## Payloads
@@ -13,12 +14,15 @@ Control is the lightweight high-priority channel between run and platform.
- `RunHelloResponse`: session token, server time, polling hints, and feature flags.
- `RunHeartbeatRequest`: session token, version, status, capacity, and current capability fingerprint.
- `RunHeartbeatResponse`: accepted status, next heartbeat interval, and optional capability refresh request.
- `RunControlStreamRequest`: run ID, session token, and the last event sequence observed by Run.
- `RunControlEvent`: run ID, monotonic endpoint-local sequence, event type, server time, and reconnect hint.
- `RunCapabilityReport`: capability names and compact fingerprint metadata.
- `RunCapacityReport`: max jobs, active jobs, queued jobs, and local resource summary.
## Rules
- Control payloads must be small.
- Control events wake Run only; they must not carry job assignments or execution input.
- Control must not carry logs, artifact chunks, or long job result bodies.
- Control must have priority over job execution, log upload, and artifact transfer.
- Heartbeat capacity summaries must remain metadata-only and must not mention or carry heavy channel payloads.
+3 -2
View File
@@ -4,7 +4,7 @@ Jobs execute bounded server management work.
## Implemented Routes
- `POST /api/v1/run/jobs/claim`: claims one queued job for the registered run endpoint, optionally holding the request for a bounded wait window so Platform can wake Run immediately when work arrives.
- `POST /api/v1/run/jobs/claim`: claims one queued job for the registered run endpoint. New workers are normally awakened by the persistent control event stream and claim without holding this request; older workers may still use a bounded `waitSeconds` long-poll fallback.
- `POST /api/v1/run/jobs/ack`: acknowledges an active leased job before execution.
- `POST /api/v1/run/jobs/progress`: reports bounded progress for an active leased job.
- `POST /api/v1/run/jobs/result`: submits a bounded terminal result for an active leased job.
@@ -17,7 +17,7 @@ Jobs execute bounded server management work.
## Payloads
- `RunJobClaimRequest`: session token, run ID, capacity, supported capabilities, and optional `waitSeconds` for long-poll claim waiting.
- `RunJobClaimRequest`: session token, run ID, capacity, supported capabilities, and optional `waitSeconds` for legacy long-poll claim waiting.
- `RunJobClaimResponse`: optional job assignment with identity, capability, server instance, logical target key, scoped input ref, idempotency key, per-job attempt, max attempts, raw one-use lease token, ack deadline, execution lease deadline, and polling hint. Platform persists only the lease hash.
- `RunJobAckRequest`: job ID, run ID, session token, lease token, attempt, and bounded message.
- `RunJobProgressRequest`: job ID, run ID, session token, lease token, attempt, percent, sequence, and bounded message.
@@ -78,6 +78,7 @@ The executor resolves lifecycle action templates under the scoped server workspa
- Job payloads must not include logs, artifact chunks, raw host paths, raw credentials, direct sockets, or large inline result bodies.
- Process stdout/stderr must be redacted and written to the log spool rather than embedded in progress/result bodies.
- Job ack/progress/result/cancel/reconcile calls are lightweight lifecycle metadata and must be able to complete while artifact/file transfer work is active or retrying.
- Persistent control events are hints only. Run must still claim, ack, execute, and complete durable jobs through this job channel so retries, leases, and idempotency stay platform-authoritative.
- Dependency adapters and update downloads run in the job worker while control heartbeat, cancellation polling, log spool upload, and artifact upload retain independent bounded loops.
- Terminal results must remain idempotent under log and artifact retry pressure and must reference artifacts by safe `artifact://...` refs rather than embedding transfer payloads.