c8b3a2281a
Proto foundation + gateway-side of the size/backpressure pass: - IPC-02: add GatewayHello.max_frame_bytes (regen Generated/); gateway sends its negotiated worker-frame max in the handshake so the worker can adopt it instead of a hard-coded default. Worker read-half lands separately. - IPC-03: give the pipe frame max envelope-overhead headroom above the public gRPC cap (WorkerFrameProtocolOptions.EnvelopeOverheadReserveBytes = 64 KiB; default Worker.MaxMessageBytes bumped to 16 MiB + reserve), cross-validate the headroom at startup, and pre-check command envelope size in WorkerClient so an oversized command fails only that correlation (ResourceExhausted) instead of faulting the whole session. - IPC-04: reject DrainEvents max_events above a public ceiling in the request validator (worker per-reply cap lands with the worker half). Docs: GatewayConfiguration, WorkerFrameProtocol, gateway.md. Tests: headroom validation, DrainEvents bound, oversized-command per-command failure (pipe-harness, verified on windev).
69 lines
2.7 KiB
Markdown
69 lines
2.7 KiB
Markdown
# Worker Frame Protocol
|
|
|
|
The gateway uses the worker frame protocol to move `WorkerEnvelope` protobuf
|
|
messages over a bidirectional named pipe. The frame layer is deliberately small:
|
|
it handles message boundaries, size limits, protobuf parsing, and envelope
|
|
validation before higher-level worker client code routes commands, replies,
|
|
events, and faults.
|
|
|
|
## Frame Format
|
|
|
|
Each frame starts with a four-byte little-endian unsigned payload length,
|
|
followed by the serialized `WorkerEnvelope` payload:
|
|
|
|
```text
|
|
uint32 little-endian payload_length
|
|
payload_length bytes protobuf WorkerEnvelope
|
|
```
|
|
|
|
The reader rejects zero-length payloads and payloads larger than the configured
|
|
maximum before allocating the payload buffer. The default maximum is the 16 MiB
|
|
public gRPC cap plus a 64 KiB envelope-overhead reserve (16842752 bytes) so a
|
|
maximally-sized accepted gRPC payload always fits one worker frame once wrapped
|
|
in a `WorkerEnvelope`.
|
|
|
|
The gateway is the source of truth for this maximum: it conveys the negotiated
|
|
value in the handshake as `GatewayHello.max_frame_bytes`, and the worker adopts
|
|
it as its `WorkerFrameProtocolOptions.MaxMessageBytes` instead of a hard-coded
|
|
default. A `max_frame_bytes` of 0 (an older gateway that never set the field)
|
|
means "use the worker's built-in default". This keeps both ends framing to the
|
|
same limit rather than depending on matched compile-time constants.
|
|
|
|
## Envelope Validation
|
|
|
|
`WorkerFrameReader` and `WorkerFrameWriter` validate each envelope against the
|
|
owning session before returning or writing it:
|
|
|
|
- `protocol_version` must match the configured worker protocol version,
|
|
- `session_id` must match the owning gateway session,
|
|
- the envelope must contain one typed `body` value.
|
|
|
|
Protocol violations throw `WorkerFrameProtocolException` with a
|
|
`WorkerFrameProtocolErrorCode` so callers can distinguish malformed frames,
|
|
oversized frames, protocol version mismatches, and session mismatches.
|
|
|
|
## Verification
|
|
|
|
The frame protocol lives in `ZB.MOM.WW.MxGateway.Worker.Ipc` (`WorkerFrameReader`,
|
|
`WorkerFrameWriter`, `WorkerFrameProtocolOptions`) and is covered by
|
|
`src/ZB.MOM.WW.MxGateway.Worker.Tests/Ipc/WorkerFrameProtocolTests.cs`. The worker is an
|
|
x86 process, so build and test it with `-p:Platform=x86`.
|
|
|
|
Run the focused tests after changing the frame protocol:
|
|
|
|
```powershell
|
|
dotnet test src/ZB.MOM.WW.MxGateway.Worker.Tests/ZB.MOM.WW.MxGateway.Worker.Tests.csproj -p:Platform=x86 --filter WorkerFrameProtocolTests
|
|
```
|
|
|
|
Run the x86 worker build because the frame protocol is part of
|
|
`ZB.MOM.WW.MxGateway.Worker`:
|
|
|
|
```powershell
|
|
dotnet build src/ZB.MOM.WW.MxGateway.Worker/ZB.MOM.WW.MxGateway.Worker.csproj -p:Platform=x86
|
|
```
|
|
|
|
## Related Documentation
|
|
|
|
- [Gateway Process Detailed Design](./GatewayProcessDesign.md)
|
|
- [Protobuf Contracts](./Contracts.md)
|