docs(TST-27,WRK-26,CLI-42,CLI-43,IPC-28): P1 doc-drift batch, discharges IPC-29
TST-27: docs/GatewayConfiguration.md's ShowTagValues row no longer says "Reserved" — it now states what false (default) does (DashboardEventBroadcaster blanks tag values from a deep-cloned MxEvent before the SignalR events-hub mirror), the security relevance (no per-session hub ACL yet, so this redaction is the only thing between a low-trust Viewer and other sessions' tag values), and the honest scope limit (does not cover /browse). WRK-26 (discharges IPC-29): docs/MxAccessWorkerInstanceDesign.md's "Outbound Queues" section rewritten from the stale five-level priority list to the two-class Control/Event scheduler actually shipped, with the collapsed- decision rationale, and the overflow paragraph rewritten to the implemented fail-fast. docs/WorkerFrameProtocol.md gained a "Write Scheduling And Sequencing" section describing HEAD truthfully: WRK-23's peek-stamp-commit sequencing is live, WRK-25's event-batch flush coalescing is not (the drain loop still awaits each event write individually), and WRK-22's cancellation tombstone is not yet defined (noted as pending, not documented as shipped). CLI-42: clients/rust/README.md and docs/ClientPackaging.md document the vendored Rust proto layout matching build.rs — repo-path-first resolution falling back to clients/rust/protos/, the check-codegen.ps1 Check 3 refresh rule, and why cargo package/publish run without --no-verify. CLI-43: docs/style-guides/JavaStyleGuide.md now says Java 17 (Ignition 8.3 baseline), mirroring CLI-12's wording, matching the shipped build.gradle. IPC-28: docs/Grpc.md's exception-mapping prose gained CommandTooLarge -> ResourceExhausted, and the Invoke section gained the oversized-payload sentence, cross-referencing GatewayConfiguration.md's headroom rule. Tracking: TST-27, WRK-26, CLI-42, CLI-43, IPC-28 flipped to Done and IPC-29 marked discharged-by-WRK-26 in 00-tracking.md and the 20/30/50/60 domain registers, with a 2026-08-07 change-log entry. Doc-only change; no source, proto, or test edits.
This commit is contained in:
@@ -638,27 +638,42 @@ Rules:
|
||||
|
||||
## Outbound Queues
|
||||
|
||||
The worker should use bounded outbound queues for replies, events, heartbeats,
|
||||
and faults.
|
||||
`WorkerFrameWriter` is a two-class cooperative priority scheduler, not the
|
||||
five-level queue an earlier design draft called for. Every outbound frame is
|
||||
enqueued at one of two `WorkerFrameWritePriority` values:
|
||||
|
||||
Priority order when writing:
|
||||
- **Control** — hello, ready, command replies, faults, heartbeats, shutdown
|
||||
acknowledgements.
|
||||
- **Event** — MXAccess events drained from the queue.
|
||||
|
||||
1. faults,
|
||||
2. command replies,
|
||||
3. shutdown acknowledgements,
|
||||
4. heartbeats,
|
||||
5. events.
|
||||
A caller enqueues its frame under a lock, then contends for a single write
|
||||
lock; whichever caller wins drains **every** currently-queued frame before
|
||||
releasing the lock, so a reply, fault, or heartbeat enqueued while a large
|
||||
event backlog is draining still gets written on the very next drain pass
|
||||
rather than waiting behind it. Within a class the queue is strict FIFO — a
|
||||
fault does not jump ahead of an already-queued heartbeat or reply. This
|
||||
collapses the originally-specified five-level order (faults > replies >
|
||||
shutdown acks > heartbeats > events) into two classes; the decision is
|
||||
deliberate, not a shortfall: the control queue is shallow in practice (faults
|
||||
and shutdown acks are rare, replies and heartbeats are the steady traffic), so
|
||||
the FIFO delay within it is bounded, and a two-class scheduler is simpler to
|
||||
reason about and test than a five-level one for that same bound. See
|
||||
`docs/WorkerFrameProtocol.md`'s "Write scheduling and sequencing" section for
|
||||
the wire-level detail (sequence stamping, per-frame vs. stream-failure
|
||||
semantics, flush coalescing).
|
||||
|
||||
Event overflow policy defaults to fail-fast for parity testing. If the event
|
||||
queue fills:
|
||||
|
||||
1. Capture overflow metrics.
|
||||
2. Send `WorkerFault` if possible.
|
||||
3. Stop accepting new commands.
|
||||
4. Let the gateway close or kill the worker.
|
||||
|
||||
Production coalescing may be added later, but it must be explicit and tested.
|
||||
Do not drop or coalesce events in v1.
|
||||
Event overflow policy is fail-fast, not "stop accepting new commands and let
|
||||
the gateway close or kill the worker." When `MxAccessEventQueue.Enqueue` finds
|
||||
the queue full, it throws and the queue self-records a `WorkerFault` with
|
||||
category `QueueOverflow`. The event drain loop's next pass observes the fault
|
||||
through `DrainFault()`, writes the fault frame — a Control-priority frame, so
|
||||
it is not stuck behind a queued event backlog — and then throws to unwind
|
||||
`RunAsync`: the worker process exits rather than continuing in a state where
|
||||
events are being silently lost. The exit currently uses the generic
|
||||
`WorkerExitCode.UnexpectedFailure` rather than a dedicated overflow code; a
|
||||
distinct exit code remains open (tracked separately). Do not drop or coalesce
|
||||
events to avoid this exit — that is explicitly out of scope for v1. Production
|
||||
coalescing may be added later, but it must be explicit and tested.
|
||||
|
||||
The gateway side of the event path is bounded to match. `WorkerClient` buffers
|
||||
inbound events in a bounded consumer channel plus a staging channel bounded at
|
||||
|
||||
Reference in New Issue
Block a user