fix(IPC-23,IPC-24,IPC-25,IPC-32): proto-comment regen wave + codegen-freshness guards
Proto comments (comment-only, no wire change): - mxaccess_worker.proto GatewayHello.max_frame_bytes: every worker->gateway frame must serialize within the negotiated max; reply builders truncate (IPC-23). - mxaccess_gateway.proto DrainEventsReply: count-cap + byte-cap, drain-until-empty caller contract (IPC-23). - mxaccess_gateway.proto ReplayGap.oldest_available_sequence: empty-ring value is highest-observed+1, oldest-1 resume formula stays valid (GWC-25 deferred amendment). Regen wave: Contracts/Generated (C# XML doc), rust vendored protos (byte-copy), Go bindings (worker binding was genuinely stale - lacked MaxFrameBytes entirely), Python worker _pb2 (real descriptor delta), Java aggregates (javadoc, zero protobuf-version churn under the pinned toolchain), client descriptor set. IPC-24: pinned Java toolchain regenerates with no gencode-version churn, so the unconditional churn-revert step in ci.yml is a fossil - deleted it; git diff is now a true message-level drift gate for the single-file Java aggregates. IPC-25: pin protoc-gen-go v1.36.11 / protoc-gen-go-grpc 1.6.2 in the Go generate script (+ fix a latent pwsh-7 parse bug); add Check 4 to check-codegen.ps1 (regenerate Go+Python bindings, fail on diff, tool-missing fails not skips); add the pinned-generator installs to the portable CI job. IPC-32: relabel check-codegen banners 1/4..4/4 (folded into the Check 4 edit). Docs: ClientProtoGeneration.md, Contracts.md, GatewayTesting.md, build.gradle checkGeneratedClean caveat. Tracking: IPC-23/24/25/32 -> Done, GWC-25 proto note resolved, change-log 2026-08-07.
This commit is contained in:
+22
-11
@@ -60,7 +60,19 @@ jobs:
|
|||||||
dotnet tool install --global PowerShell
|
dotnet tool install --global PowerShell
|
||||||
echo "$HOME/.dotnet/tools" >> "$GITHUB_PATH"
|
echo "$HOME/.dotnet/tools" >> "$GITHUB_PATH"
|
||||||
|
|
||||||
# IPC-01 / IPC-19 / IPC-20: descriptor set + Contracts/Generated must match the current protos.
|
# IPC-25 Check 4 regenerates the Go and Python client bindings and diffs them, so the pinned
|
||||||
|
# generators must be present. protoc 34.1 is already installed above; Go and Python are set up
|
||||||
|
# above. Pin protoc-gen-go / protoc-gen-go-grpc to match the committed header stamps and grpcio
|
||||||
|
# -tools to match the committed _pb2 stamp, or Check 4 false-fails (or masks drift) under churn.
|
||||||
|
- name: Install pinned client codegen generators (Check 4)
|
||||||
|
run: |
|
||||||
|
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.11
|
||||||
|
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.6.2
|
||||||
|
echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
|
||||||
|
python -m pip install 'grpcio-tools==1.80.0'
|
||||||
|
|
||||||
|
# IPC-01 / IPC-19 / IPC-20 / IPC-25: descriptor set + Contracts/Generated + Go/Python bindings
|
||||||
|
# must match the current protos.
|
||||||
- name: Codegen / descriptor freshness
|
- name: Codegen / descriptor freshness
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: ./scripts/check-codegen.ps1
|
run: ./scripts/check-codegen.ps1
|
||||||
@@ -93,10 +105,12 @@ jobs:
|
|||||||
python -m pytest
|
python -m pytest
|
||||||
|
|
||||||
java:
|
java:
|
||||||
# Java client runs on a JDK-17 Linux runner (the macOS dev box has no JRE). The protobuf gradle
|
# Java client runs on a JDK-17 Linux runner (the macOS dev box has no JRE). The grpc/protobuf
|
||||||
# plugin rewrites MxaccessGateway.java with spurious protobuf-runtime-version churn on every
|
# toolchain is fully pinned (clients/java/build.gradle: grpcVersion 1.76.0 / protobufVersion
|
||||||
# build; when no .proto changed, revert that one file so checkGeneratedClean / a dirty tree does
|
# 4.33.1), so a regeneration is byte-identical to the committed aggregates modulo real .proto
|
||||||
# not fail the build (repo memory project_java_generated_churn).
|
# changes — `Verify generated tree is clean` (git diff) is the true drift gate (IPC-24). The
|
||||||
|
# single-file Java aggregates are where message-level proto drift lands, so this job now catches
|
||||||
|
# a .proto edited without regenerating and committing the Java client.
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -115,13 +129,10 @@ jobs:
|
|||||||
- name: Gradle test
|
- name: Gradle test
|
||||||
working-directory: clients/java
|
working-directory: clients/java
|
||||||
run: gradle test
|
run: gradle test
|
||||||
- name: Revert spurious protobuf-version churn (no .proto changed)
|
|
||||||
# Both generated aggregates can pick up protobuf-runtime-version churn on regen; revert
|
|
||||||
# both so verify-clean still catches a real, uncommitted proto/codegen change elsewhere.
|
|
||||||
run: |
|
|
||||||
git checkout -- clients/java/src/main/generated/main/java/mxaccess_gateway/v1/MxaccessGateway.java || true
|
|
||||||
git checkout -- clients/java/src/main/generated/main/java/mxaccess_worker/v1/MxaccessWorker.java || true
|
|
||||||
- name: Verify generated tree is clean
|
- name: Verify generated tree is clean
|
||||||
|
# IPC-24: the pinned grpc/protobuf toolchain regenerates byte-identical output, so this
|
||||||
|
# git-diff gate now catches message-level proto drift in the single-file Java aggregates
|
||||||
|
# (the old unconditional churn-revert step masked exactly that class and was deleted).
|
||||||
run: git diff --exit-code -- clients/java/src/main/generated
|
run: git diff --exit-code -- clients/java/src/main/generated
|
||||||
|
|
||||||
windows-x86:
|
windows-x86:
|
||||||
|
|||||||
@@ -44,12 +44,12 @@ Sequenced by cluster; a cluster is one change set.
|
|||||||
| CLI-35 | Medium | S | GWC-25 (coord) | Done | Python CLI `stream-events` crashes on a ReplayGap |
|
| CLI-35 | Medium | S | GWC-25 (coord) | Done | Python CLI `stream-events` crashes on a ReplayGap |
|
||||||
| CLI-36 | Medium | S | GWC-25 (coord) | Done | Go CLI `stream-events` silently destroys the ReplayGap signal |
|
| CLI-36 | Medium | S | GWC-25 (coord) | Done | Go CLI `stream-events` silently destroys the ReplayGap signal |
|
||||||
| WRK-21 | Medium | M | owns IPC-23 fix; WRK-28 same batch | Done | DrainEvents bound is count-based only; oversized reply kills the session and loses the drained events |
|
| WRK-21 | Medium | M | owns IPC-23 fix; WRK-28 same batch | Done | DrainEvents bound is count-based only; oversized reply kills the session and loses the drained events |
|
||||||
| IPC-23 | Medium | S | WRK-21 | In progress — mechanics landed with WRK-21; proto-comment/doc wave pending | DrainEvents contract requirements (reply fits negotiated max, no event loss, drain-until-empty) + proto-comment/doc wave |
|
| IPC-23 | Medium | S | WRK-21 | Done | DrainEvents contract requirements (reply fits negotiated max, no event loss, drain-until-empty) + proto-comment/doc wave |
|
||||||
| IPC-30 | Low | M | WRK-21 (same batch) | Done | Oversized event frame stays session-fatal by design, but the death becomes structured (fault frame + logged identity) |
|
| IPC-30 | Low | M | WRK-21 (same batch) | Done | Oversized event frame stays session-fatal by design, but the death becomes structured (fault frame + logged identity) |
|
||||||
| SEC-31 | Medium | M | — | Done | Failure limiter partitions on attacker-controlled key id and blocks before verification (lockout DoS) |
|
| SEC-31 | Medium | M | — | Done | Failure limiter partitions on attacker-controlled key id and blocks before verification (lockout DoS) |
|
||||||
| SEC-32 | Low | S | SEC-31 | Done | Failure-limiter LRU flushable by junk-token spray; token prefix never validated |
|
| SEC-32 | Low | S | SEC-31 | Done | Failure-limiter LRU flushable by junk-token spray; token prefix never validated |
|
||||||
| IPC-24 | Medium | S | — | Not started | CI's unconditional Java churn-revert masks real drift |
|
| IPC-24 | Medium | S | — | Done | CI's unconditional Java churn-revert masks real drift |
|
||||||
| IPC-25 | Medium | M | — | Not started | Regenerate stale Go/Python worker bindings + add binding-freshness guard (Check 4) to check-codegen.ps1 |
|
| IPC-25 | Medium | M | — | Done | Regenerate stale Go/Python worker bindings + add binding-freshness guard (Check 4) to check-codegen.ps1 |
|
||||||
|
|
||||||
## Finding registers by domain
|
## Finding registers by domain
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ Full design + implementation for each row lives in the linked domain doc under i
|
|||||||
| IPC-29 | Low | — | S | WRK-26 (discharged by) | Not started | WorkerFrameProtocol.md missing write-scheduling/sequencing section |
|
| IPC-29 | Low | — | S | WRK-26 (discharged by) | Not started | WorkerFrameProtocol.md missing write-scheduling/sequencing section |
|
||||||
| IPC-30 | Low | P0 | M | WRK-21 (same batch) | Done | Oversized event frame: keep session-fatal, make the death structured |
|
| IPC-30 | Low | P0 | M | WRK-21 (same batch) | Done | Oversized event frame: keep session-fatal, make the death structured |
|
||||||
| IPC-31 | Info | — | — | — | N/A | Gateway creation-time sequence stamping accepted; diagnostic-only, decision recorded |
|
| IPC-31 | Info | — | — | — | N/A | Gateway creation-time sequence stamping accepted; diagnostic-only, decision recorded |
|
||||||
| IPC-32 | Info | — | S | IPC-25 (folded in) | Not started | check-codegen banner relabel 1/4…4/4 |
|
| IPC-32 | Info | — | S | IPC-25 (folded in) | Done | check-codegen banner relabel 1/4…4/4 |
|
||||||
|
|
||||||
### Security & dashboard — [40-security-dashboard.md](40-security-dashboard.md)
|
### Security & dashboard — [40-security-dashboard.md](40-security-dashboard.md)
|
||||||
|
|
||||||
@@ -174,3 +174,4 @@ Sequence these together rather than piecemeal — several are one change set spa
|
|||||||
| 2026-08-07 | **GWC-28, GWC-29, GWC-30, TST-28 → `Done`** (branch `fix/gwc-28-29-30-polish`). GWC-28: `WorkerClient.WriteLoopAsync` now stamps `envelope.Sequence = unchecked(++_nextSequence)` immediately before `_writer.WriteAsync`, and `CreateEnvelope` leaves it unset; `_nextSequence` dropped from `long` + `Interlocked` to a plain `ulong` touched only by the write loop (the channel's single consumer, `SingleReader = true`), so wire order and sequence order are the same thing by construction. Mirrors the worker's WRK-04 stamping, which the gateway half had never received; `gateway.md`'s envelope-sequence rule now states that both sides stamp at write inside their single write path and that inbound enforcement (still open, old **GWC-10**) would rely on it. New `WorkerClientTests.ConcurrentInvokesEmitStrictlyIncreasingSequencesOnTheWire` (32 parallel invokes, sequences asserted strictly increasing in wire order) failed 3/3 pre-fix. GWC-29: added `MxAccessGrpcMapper.MapCommand(MxCommand)`; `Invoke` no longer deep-clones the whole `MxCommandRequest` just to overwrite and discard its command. The one clone inside `MapCommand` stays and is documented as required — `commandToInvoke` may be the gRPC-owned `request.Command` and is read again after dispatch by `TrackCommandReply`, so it is what keeps `CreateCommandEnvelope`'s no-aliasing invariant true. New `MxAccessGrpcMapperTests.MapCommandFromCommandClonesPayload` (isolation + both overloads equal under a `FakeTimeProvider`). GWC-30: `WorkerFrameReader` reuses a per-instance `_lengthPrefix` scratch buffer instead of allocating 4 bytes per frame, with a class remark that `ReadAsync` is not reentrant (single read loop per `WorkerClient`; handshake reads complete before the loop starts); guarded by new `WorkerFrameProtocolTests.ReadAsync_WithMultipleFramesOnOneReader_ParsesEveryFrame` (5 frames, varying payload lengths, one reader). TST-28: new `[Theory] WorkerClientTests.StartAsync_SendsGatewayHelloWithConfiguredMaxFrameBytes` over the default and a 2 MiB override via `FakeWorkerHarness.CreateConnectedPairAsync(maxMessageBytes:)` — test-only, and the mutation check (hard-code `MaxFrameBytes = 0`) failed both cases before being reverted. Verification: `NonWindows.slnx` 0 warnings/0 errors; `WorkerClientTests` 25 passed, `WorkerFrameProtocolTests` 11 passed, `MxAccessGrpcMapperTests` 6 passed, `MxAccessGatewayService*` 29 passed, full gateway suite 844 passed / 0 failed (`TMPDIR=/tmp` on macOS). |
|
| 2026-08-07 | **GWC-28, GWC-29, GWC-30, TST-28 → `Done`** (branch `fix/gwc-28-29-30-polish`). GWC-28: `WorkerClient.WriteLoopAsync` now stamps `envelope.Sequence = unchecked(++_nextSequence)` immediately before `_writer.WriteAsync`, and `CreateEnvelope` leaves it unset; `_nextSequence` dropped from `long` + `Interlocked` to a plain `ulong` touched only by the write loop (the channel's single consumer, `SingleReader = true`), so wire order and sequence order are the same thing by construction. Mirrors the worker's WRK-04 stamping, which the gateway half had never received; `gateway.md`'s envelope-sequence rule now states that both sides stamp at write inside their single write path and that inbound enforcement (still open, old **GWC-10**) would rely on it. New `WorkerClientTests.ConcurrentInvokesEmitStrictlyIncreasingSequencesOnTheWire` (32 parallel invokes, sequences asserted strictly increasing in wire order) failed 3/3 pre-fix. GWC-29: added `MxAccessGrpcMapper.MapCommand(MxCommand)`; `Invoke` no longer deep-clones the whole `MxCommandRequest` just to overwrite and discard its command. The one clone inside `MapCommand` stays and is documented as required — `commandToInvoke` may be the gRPC-owned `request.Command` and is read again after dispatch by `TrackCommandReply`, so it is what keeps `CreateCommandEnvelope`'s no-aliasing invariant true. New `MxAccessGrpcMapperTests.MapCommandFromCommandClonesPayload` (isolation + both overloads equal under a `FakeTimeProvider`). GWC-30: `WorkerFrameReader` reuses a per-instance `_lengthPrefix` scratch buffer instead of allocating 4 bytes per frame, with a class remark that `ReadAsync` is not reentrant (single read loop per `WorkerClient`; handshake reads complete before the loop starts); guarded by new `WorkerFrameProtocolTests.ReadAsync_WithMultipleFramesOnOneReader_ParsesEveryFrame` (5 frames, varying payload lengths, one reader). TST-28: new `[Theory] WorkerClientTests.StartAsync_SendsGatewayHelloWithConfiguredMaxFrameBytes` over the default and a 2 MiB override via `FakeWorkerHarness.CreateConnectedPairAsync(maxMessageBytes:)` — test-only, and the mutation check (hard-code `MaxFrameBytes = 0`) failed both cases before being reverted. Verification: `NonWindows.slnx` 0 warnings/0 errors; `WorkerClientTests` 25 passed, `WorkerFrameProtocolTests` 11 passed, `MxAccessGrpcMapperTests` 6 passed, `MxAccessGatewayService*` 29 passed, full gateway suite 844 passed / 0 failed (`TMPDIR=/tmp` on macOS). |
|
||||||
| 2026-08-07 | **WRK-21 + WRK-28 + WRK-23 + IPC-30 → `Done`** (branch `fix/wrk-21-drain-cluster`, commits `33ba612` + test-fixture follow-ups `7c2eaf0`/`a256560`). WRK-21: `MxAccessEventQueue` gains a byte-budgeted `Drain(maxEvents, maxTotalBytes)` returning the new `WorkerEventDrainResult`, sizing inside the queue lock so an event that will not fit is never dequeued; `CreateDrainEventsReply` budgets against the negotiated frame max less a 64 KiB wrapper reserve and reports truncation through the existing `DiagnosticMessage` (no proto change), satisfying IPC-23 R1–R3; both reply-write seams (`HandleControlCommandAsync`, `ProcessCommandAsync`) now catch `MessageTooLarge` and answer the correlation with an `InvalidRequest` reply instead of unwinding/faulting the session. WRK-28: the 10,000 ceiling moved to `GatewayContractInfo.MaxDrainEventsPerCommand`, referenced by the gateway validator and the worker clamp (C# const, no `.proto` change). WRK-23: `WorkerFrameWriter` peek-stamps then commits `Sequence` only immediately before the stream write, so rejections leave no wire gap. IPC-30: an oversized event frame stays session-fatal but writes a `PROTOCOL_VIOLATION` `WorkerFault` with `command_method = EventDrain` naming family/handles/sequence/sizes (never the value) before exiting. Docs same commit: `MxAccessWorkerInstanceDesign.md`, `WorkerFrameProtocol.md`, `gateway.md`. **IPC-23 → `In progress`** — mechanics landed here; the proto-comment/doc wave (and its regen fan-out) is still pending and must not be folded into this branch. **Evidence** — macOS: `dotnet build src/ZB.MOM.WW.MxGateway.NonWindows.slnx` 0 warnings/0 errors, `dotnet test …MxGateway.Tests --filter FullyQualifiedName~MxAccessGrpcRequestValidator` 4/4 passed. windev (`scripts/ci/windev-worker-ci.ps1 -Sha a2565604 -Mode test`, 2026-08-07 06:47): x86 Worker build 0 warnings/0 errors, `Worker.Tests` **367 passed / 0 failed / 11 skipped** (skips are the live-MXAccess/dev-rig opt-ins), script exit 0. **Harness note:** `PipePair` runs both pipe ends in one process with blocking `FlushFileBuffers` per frame, so it wedges on multi-MB frames or after ~85 large round trips; the pipe tests therefore negotiate a 128 KiB frame maximum and walk 1,000 events to empty, while the full 10,000-event drain-to-empty no-loss proof runs at the queue layer (`MxAccessEventQueueTests`). |
|
| 2026-08-07 | **WRK-21 + WRK-28 + WRK-23 + IPC-30 → `Done`** (branch `fix/wrk-21-drain-cluster`, commits `33ba612` + test-fixture follow-ups `7c2eaf0`/`a256560`). WRK-21: `MxAccessEventQueue` gains a byte-budgeted `Drain(maxEvents, maxTotalBytes)` returning the new `WorkerEventDrainResult`, sizing inside the queue lock so an event that will not fit is never dequeued; `CreateDrainEventsReply` budgets against the negotiated frame max less a 64 KiB wrapper reserve and reports truncation through the existing `DiagnosticMessage` (no proto change), satisfying IPC-23 R1–R3; both reply-write seams (`HandleControlCommandAsync`, `ProcessCommandAsync`) now catch `MessageTooLarge` and answer the correlation with an `InvalidRequest` reply instead of unwinding/faulting the session. WRK-28: the 10,000 ceiling moved to `GatewayContractInfo.MaxDrainEventsPerCommand`, referenced by the gateway validator and the worker clamp (C# const, no `.proto` change). WRK-23: `WorkerFrameWriter` peek-stamps then commits `Sequence` only immediately before the stream write, so rejections leave no wire gap. IPC-30: an oversized event frame stays session-fatal but writes a `PROTOCOL_VIOLATION` `WorkerFault` with `command_method = EventDrain` naming family/handles/sequence/sizes (never the value) before exiting. Docs same commit: `MxAccessWorkerInstanceDesign.md`, `WorkerFrameProtocol.md`, `gateway.md`. **IPC-23 → `In progress`** — mechanics landed here; the proto-comment/doc wave (and its regen fan-out) is still pending and must not be folded into this branch. **Evidence** — macOS: `dotnet build src/ZB.MOM.WW.MxGateway.NonWindows.slnx` 0 warnings/0 errors, `dotnet test …MxGateway.Tests --filter FullyQualifiedName~MxAccessGrpcRequestValidator` 4/4 passed. windev (`scripts/ci/windev-worker-ci.ps1 -Sha a2565604 -Mode test`, 2026-08-07 06:47): x86 Worker build 0 warnings/0 errors, `Worker.Tests` **367 passed / 0 failed / 11 skipped** (skips are the live-MXAccess/dev-rig opt-ins), script exit 0. **Harness note:** `PipePair` runs both pipe ends in one process with blocking `FlushFileBuffers` per frame, so it wedges on multi-MB frames or after ~85 large round trips; the pipe tests therefore negotiate a 128 KiB frame maximum and walk 1,000 events to empty, while the full 10,000-event drain-to-empty no-loss proof runs at the queue layer (`MxAccessEventQueueTests`). |
|
||||||
| 2026-08-07 | Code-review follow-ups on the same branch (commit `6bc3f9b`). (1) **Important** — `ResolveDrainReplyByteBudget` was a step, not a floor: just above the 64 KiB reserve the budget collapsed to a few bytes (exactly 1024 at the validator floor `MaxMessageBytes = 1024 + 64 KiB`), so a byte-heavy `DrainEvents` truncated on every call and the drain-until-empty loop never terminated. Now `Math.Max(frameMax - reserve, frameMax / 2)` — monotonic, never below half the frame max. New test `WorkerPipeSessionTests.DrainEvents_AtValidatorFloorFrameMax_MakesProgressAndTerminates` drives a byte-heavy queue at the exact validator floor and asserts drain-to-empty with no head reported oversized. (2) **Hardening** — the reply-too-large fallback write is now itself size-guarded (`WriteReplyTooLargeFallbackAsync`, shared by the control and STA reply seams) so a pathologically tiny negotiated max below the gateway floor (the WRK-24 gap) cannot make even the backstop session-fatal; log-and-swallow, comment points at WRK-24. (3) **Comment** — corrected the `RepeatedFieldOverheadBytes` docs: `WorkerEvent.CalculateSize()` already includes the event's tag+length, so the 8 bytes is pure slack, not wrapper compensation. **Evidence** — macOS build 0/0, validator filter 4/4. windev (`windev-worker-ci.ps1 -Sha 6bc3f9b -Mode test`, 07:07): x86 Worker build 0/0, `Worker.Tests` **368 passed / 0 failed / 11 skipped**, script exit 0. (An earlier run of the same SHA flaked on the pre-existing `RunAsync_WhenStaActivityIsStale_WritesWatchdogFault` — a 5 s CTS timeout under first-run load, untouched by this change; it passed on the clean re-run and in both prior full runs.) |
|
| 2026-08-07 | Code-review follow-ups on the same branch (commit `6bc3f9b`). (1) **Important** — `ResolveDrainReplyByteBudget` was a step, not a floor: just above the 64 KiB reserve the budget collapsed to a few bytes (exactly 1024 at the validator floor `MaxMessageBytes = 1024 + 64 KiB`), so a byte-heavy `DrainEvents` truncated on every call and the drain-until-empty loop never terminated. Now `Math.Max(frameMax - reserve, frameMax / 2)` — monotonic, never below half the frame max. New test `WorkerPipeSessionTests.DrainEvents_AtValidatorFloorFrameMax_MakesProgressAndTerminates` drives a byte-heavy queue at the exact validator floor and asserts drain-to-empty with no head reported oversized. (2) **Hardening** — the reply-too-large fallback write is now itself size-guarded (`WriteReplyTooLargeFallbackAsync`, shared by the control and STA reply seams) so a pathologically tiny negotiated max below the gateway floor (the WRK-24 gap) cannot make even the backstop session-fatal; log-and-swallow, comment points at WRK-24. (3) **Comment** — corrected the `RepeatedFieldOverheadBytes` docs: `WorkerEvent.CalculateSize()` already includes the event's tag+length, so the 8 bytes is pure slack, not wrapper compensation. **Evidence** — macOS build 0/0, validator filter 4/4. windev (`windev-worker-ci.ps1 -Sha 6bc3f9b -Mode test`, 07:07): x86 Worker build 0/0, `Worker.Tests` **368 passed / 0 failed / 11 skipped**, script exit 0. (An earlier run of the same SHA flaked on the pre-existing `RunAsync_WhenStaActivityIsStale_WritesWatchdogFault` — a 5 s CTS timeout under first-run load, untouched by this change; it passed on the clean re-run and in both prior full runs.) |
|
||||||
|
| 2026-08-07 | **IPC-23 + IPC-24 + IPC-25 + IPC-32 → `Done`; GWC-25 deferred proto-comment resolved** (branch `fix/ipc-24-25-codegen`). The proto-comment/doc + regen wave for the P0 codegen-freshness cluster. **Proto comments (comment-only):** `mxaccess_worker.proto` `GatewayHello.max_frame_bytes` gained the every-frame-must-fit / reply-builders-truncate sentence (IPC-23); `mxaccess_gateway.proto` `DrainEventsReply` gained the count-cap+byte-cap / drain-until-empty comment (IPC-23); `mxaccess_gateway.proto` `ReplayGap.oldest_available_sequence` gained the empty-ring value definition (`highest observed + 1`, `oldest − 1` formula stays valid) resolving GWC-25's deferred amendment. **Regen wave:** `Contracts/Generated/{MxaccessGateway,MxaccessWorker}.cs` (XML-doc only, no descriptor delta), `clients/rust/protos/{mxaccess_gateway,mxaccess_worker}.proto` byte-copied, Go `internal/generated/{mxaccess_gateway,mxaccess_worker}.pb.go` (worker binding was genuinely stale — it lacked the whole `MaxFrameBytes` field/accessor/rawDesc, now refreshed; gateway.pb.go got the new doc comments), Python `generated/mxaccess_worker_pb2.py` (real descriptor delta — `max_frame_bytes` field + cascaded offsets), Java aggregates `MxaccessGateway.java`/`MxaccessWorker.java` (javadoc from the new proto comments — **zero** protobuf-version churn under the pinned toolchain), and the client descriptor set `mxaccessgw-client-v1.protoset`. **IPC-24:** regenerating Java on the pinned toolchain (grpc 1.76.0 / protobuf 4.33.1, Homebrew JDK 17) produced only the legitimate javadoc delta with no `validateProtobufGencodeVersion`/`major=/minor=/patch=` churn — so the preferred path was taken: the unconditional churn-revert step and its comment were **deleted** from `.gitea/workflows/ci.yml` (the `git diff --exit-code` gate is now a true message-level drift gate for the single-file Java aggregates). **IPC-25:** pinned the Go generators in `clients/go/generate-proto.ps1` (`protoc-gen-go` v1.36.11 assert, `protoc-gen-go-grpc` 1.6.2 assert, protoc warn-only; also fixed a latent `(if …)`→`$(if …)` parse bug that broke the script under pwsh 7); added **Check 4** to `scripts/check-codegen.ps1` (regenerate Go+Python bindings, fail on any diff, tool-missing FAILS not skips) and relabeled the banners `1/4`…`4/4` + header comment (**IPC-32** folded in); added the pinned-generator installs to the `portable` CI job before the codegen step. **Docs same commit:** `ClientProtoGeneration.md` (pinned-versions table + Go/Python Check-4 guard + Java-revert-deleted note), `Contracts.md` (four-check enumeration), `GatewayTesting.md` (java job + four-check prose), `clients/java/zb-mom-ww-mxgateway-client/build.gradle` checkGeneratedClean caveat. **IPC-23 DrainEvents-truncation doc deviation:** `docs/Grpc.md` has no DrainEvents row (it documents only the seven public RPCs; DrainEvents is a worker diagnostic), and `docs/WorkerFrameProtocol.md` (owned by the parallel doc batch) already carries the byte-cap/drain-until-empty prose via WRK-21 — so no Grpc.md edit was made. **Evidence (macOS):** `pwsh scripts/check-codegen.ps1` all four checks green (banners `1/4`…`4/4`); `dotnet build …NonWindows.slnx` 0 warnings/0 errors; `dotnet test …Tests --filter ~ClientProtoInputTests` green; `grep -c max_frame_bytes` → Go worker 2, Python worker 1 (both non-zero, were 0); `clients/go` gofmt clean + `go build` + `go test` ok; `clients/python` `pytest` 163 passed/1 skipped; Java `gradle generateProto` clean under JDK 17. **Negative-path proof:** added a scratch field to `mxaccess_worker.proto`, regenerated only `Contracts/Generated/`, reran `check-codegen.ps1` and confirmed **Check 4 fails naming both `clients/go/internal/generated` and `clients/python/…/generated`**, then reverted. **Not published** (CLI-39 gates Go/Python republish). |
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ Coordinate with (do not block on) open GWC-21: if `EventChannelFullModeTimeout`
|
|||||||
|
|
||||||
The proto comment currently states "`oldest_available_sequence` itself IS still retained", which becomes false in the empty-ring case — per the docs-with-source rule, amend the field comment in the same commit to define the empty-ring value ("when nothing is retained, this is the next sequence that can be delivered — `highest observed + 1` — and the `oldest − 1` resume formula remains valid; the interval evicted is unchanged"). This is a comment-only proto change (no descriptor delta), but the repo's codegen rules still apply — see the steps.
|
The proto comment currently states "`oldest_available_sequence` itself IS still retained", which becomes false in the empty-ring case — per the docs-with-source rule, amend the field comment in the same commit to define the empty-ring value ("when nothing is retained, this is the next sequence that can be delivered — `highest observed + 1` — and the `oldest − 1` resume formula remains valid; the interval evicted is unchanged"). This is a comment-only proto change (no descriptor delta), but the repo's codegen rules still apply — see the steps.
|
||||||
|
|
||||||
**Implementation.**
|
**Implementation.** (Code + `docs/Sessions.md` landed 2026-08-07 on `fix/gwc-25-replaygap-trio`; the deferred proto-comment amendment below **landed 2026-08-07** with the IPC-23 codegen wave on `fix/ipc-24-25-codegen` — GWC-25 is fully resolved.)
|
||||||
- `Sessions/SessionEventDistributor.cs:463-467`: replace `oldestAvailableSequence = 0;` with `oldestAvailableSequence = gap ? _highestSequenceSeen + 1 : 0;` plus a comment explaining the `oldest − 1` client formula this must keep valid (cite this finding).
|
- `Sessions/SessionEventDistributor.cs:463-467`: replace `oldestAvailableSequence = 0;` with `oldestAvailableSequence = gap ? _highestSequenceSeen + 1 : 0;` plus a comment explaining the `oldest − 1` client formula this must keep valid (cite this finding).
|
||||||
- `src/ZB.MOM.WW.MxGateway.Contracts/Protos/mxaccess_gateway.proto` (`ReplayGap.oldest_available_sequence`, ~line 759): append the empty-ring sentence above. Then regenerate per repo rules: delete `src/ZB.MOM.WW.MxGateway.Contracts/Generated/*.cs`, `dotnet build src/ZB.MOM.WW.MxGateway.Contracts/ZB.MOM.WW.MxGateway.Contracts.csproj`, and **commit `Generated/`** (net48 worker builds break otherwise). Sync the vendored client copies of the proto byte-identical (`clients/*/`); a comment-only edit changes no descriptor, so: Python `*_pb2*` output is unchanged (comments are not embedded — regenerate with the pinned grpcio-tools only if the files actually differ), Go/C#/Rust generated doc comments will churn — regenerate those per each client README, and revert spurious Java aggregate-file churn if no message-level delta appears (per the established Java convention).
|
- `src/ZB.MOM.WW.MxGateway.Contracts/Protos/mxaccess_gateway.proto` (`ReplayGap.oldest_available_sequence`, ~line 759): append the empty-ring sentence above. Then regenerate per repo rules: delete `src/ZB.MOM.WW.MxGateway.Contracts/Generated/*.cs`, `dotnet build src/ZB.MOM.WW.MxGateway.Contracts/ZB.MOM.WW.MxGateway.Contracts.csproj`, and **commit `Generated/`** (net48 worker builds break otherwise). Sync the vendored client copies of the proto byte-identical (`clients/*/`); a comment-only edit changes no descriptor, so: Python `*_pb2*` output is unchanged (comments are not embedded — regenerate with the pinned grpcio-tools only if the files actually differ), Go/C#/Rust generated doc comments will churn — regenerate those per each client README, and revert spurious Java aggregate-file churn if no message-level delta appears (per the established Java convention).
|
||||||
- `docs/Sessions.md` (~lines 228-234, ReplayGap section): document the empty-ring sentinel value and that `after_worker_sequence = oldest_available_sequence − 1` is the universal resume formula in both the retained and fully-evicted cases.
|
- `docs/Sessions.md` (~lines 228-234, ReplayGap section): document the empty-ring sentinel value and that `after_worker_sequence = oldest_available_sequence − 1` is the universal resume formula in both the retained and fully-evicted cases.
|
||||||
|
|||||||
@@ -12,16 +12,16 @@ All `path:line` citations were re-verified against the working tree at `4f5371f`
|
|||||||
|
|
||||||
| ID | Sev | Tier | Eff | Dep | Status | Title |
|
| ID | Sev | Tier | Eff | Dep | Status | Title |
|
||||||
|----|-----|------|-----|-----|--------|-------|
|
|----|-----|------|-----|-----|--------|-------|
|
||||||
| IPC-23 | Medium | P0 | S¹ | WRK-21 | In progress — mechanics landed with WRK-21; proto-comment/doc wave pending | DrainEvents bound is count-based only; byte-heavy queue still builds a session-killing reply frame (contract requirements here; fix mechanics in WRK-21) |
|
| IPC-23 | Medium | P0 | S¹ | WRK-21 | Done | DrainEvents bound is count-based only; byte-heavy queue still builds a session-killing reply frame (contract requirements here; fix mechanics in WRK-21) |
|
||||||
| IPC-24 | Medium | P0 | S | — | Not started | CI's unconditional Java churn-revert masks real generated-code drift for message-level proto changes |
|
| IPC-24 | Medium | P0 | S | — | Done | CI's unconditional Java churn-revert masks real generated-code drift for message-level proto changes |
|
||||||
| IPC-25 | Medium | P0 | M | — | Not started | Committed Go/Python worker bindings are stale at HEAD; no guard covers them |
|
| IPC-25 | Medium | P0 | M | — | Done | Committed Go/Python worker bindings are stale at HEAD; no guard covers them |
|
||||||
| IPC-26 | Low | P2 | S¹ | WRK-22 | Not started | Cancelled write leaves a ghost frame that is still written (contract requirement here; fix mechanics in WRK-22) |
|
| IPC-26 | Low | P2 | S¹ | WRK-22 | Not started | Cancelled write leaves a ghost frame that is still written (contract requirement here; fix mechanics in WRK-22) |
|
||||||
| IPC-27 | Low | P2 | S | — | Not started | Descriptor freshness test blind to enums, enum values, services/methods, and the Galaxy contract |
|
| IPC-27 | Low | P2 | S | — | Not started | Descriptor freshness test blind to enums, enum values, services/methods, and the Galaxy contract |
|
||||||
| IPC-28 | Low | — | S | — | Not started | `docs/Grpc.md` omits the `CommandTooLarge` → `ResourceExhausted` mapping |
|
| IPC-28 | Low | — | S | — | Not started | `docs/Grpc.md` omits the `CommandTooLarge` → `ResourceExhausted` mapping |
|
||||||
| IPC-29 | Low | — | S | — | Not started | Worker writer priority scheduling and write-time sequence stamping undocumented in the frame-protocol doc |
|
| IPC-29 | Low | — | S | — | Not started | Worker writer priority scheduling and write-time sequence stamping undocumented in the frame-protocol doc |
|
||||||
| IPC-30 | Low | P0 | M | WRK-21 (same file/batch) | Done | Oversized worker→gateway event frame is session-fatal — make the death deliberate, structured, and diagnosable |
|
| IPC-30 | Low | P0 | M | WRK-21 (same file/batch) | Done | Oversized worker→gateway event frame is session-fatal — make the death deliberate, structured, and diagnosable |
|
||||||
| IPC-31 | Info | — | — | — | N/A | Gateway stamps sequence at creation, worker at write — accepted divergence; sequence is documented diagnostic-only (`gateway.md:328-330`); revisit only if sequence ever becomes load-bearing |
|
| IPC-31 | Info | — | — | — | N/A | Gateway stamps sequence at creation, worker at write — accepted divergence; sequence is documented diagnostic-only (`gateway.md:328-330`); revisit only if sequence ever becomes load-bearing |
|
||||||
| IPC-32 | Info | — | S | IPC-25 | Not started | `check-codegen.ps1` check labels miscounted (folded into the IPC-25 script edit) |
|
| IPC-32 | Info | — | S | IPC-25 | Done | `check-codegen.ps1` check labels miscounted (folded into the IPC-25 script edit) |
|
||||||
|
|
||||||
¹ Effort for the work owned by *this* plan (proto comments + docs + acceptance criteria). The code mechanics are M and are tracked under WRK-21 / WRK-22 in the worker plan.
|
¹ Effort for the work owned by *this* plan (proto comments + docs + acceptance criteria). The code mechanics are M and are tracked under WRK-21 / WRK-22 in the worker plan.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,16 @@
|
|||||||
Set-StrictMode -Version Latest
|
Set-StrictMode -Version Latest
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
# Pinned generator baseline. The committed Go bindings stamp these plugin versions in their
|
||||||
|
# headers (protoc-gen-go v1.36.11 / protoc-gen-go-grpc v1.6.2). Plugin-version drift rewrites
|
||||||
|
# those header stamps, so a regeneration on an off-pin machine would churn the tree and make
|
||||||
|
# check-codegen Check 4 false-fail (or mask real drift under churn). Assert the exact versions
|
||||||
|
# so a regen is deterministic. protoc itself is warn-only (source_code_info is normalized out of
|
||||||
|
# the committed bindings), matching publish-client-proto-inputs.ps1.
|
||||||
|
$PinnedProtocGenGoVersion = 'protoc-gen-go v1.36.11'
|
||||||
|
$PinnedProtocGenGoGrpcVersion = 'protoc-gen-go-grpc 1.6.2'
|
||||||
|
$PinnedProtocVersion = 'libprotoc 34.1'
|
||||||
|
|
||||||
$repoRoot = Resolve-Path (Join-Path $PSScriptRoot '..\..')
|
$repoRoot = Resolve-Path (Join-Path $PSScriptRoot '..\..')
|
||||||
$protoRoot = Join-Path $repoRoot 'src\ZB.MOM.WW.MxGateway.Contracts\Protos'
|
$protoRoot = Join-Path $repoRoot 'src\ZB.MOM.WW.MxGateway.Contracts\Protos'
|
||||||
$outputRoot = Join-Path $PSScriptRoot 'internal\generated'
|
$outputRoot = Join-Path $PSScriptRoot 'internal\generated'
|
||||||
@@ -36,8 +46,25 @@ $wingetProtoc = if ($env:LOCALAPPDATA) {
|
|||||||
$goBin = if ($env:USERPROFILE) { Join-Path $env:USERPROFILE 'go\bin' } elseif ($env:HOME) { Join-Path $env:HOME 'go/bin' } else { $null }
|
$goBin = if ($env:USERPROFILE) { Join-Path $env:USERPROFILE 'go\bin' } elseif ($env:HOME) { Join-Path $env:HOME 'go/bin' } else { $null }
|
||||||
|
|
||||||
$protoc = Resolve-Tool -Names @('protoc', 'protoc.exe') -FallbackPaths @($wingetProtoc)
|
$protoc = Resolve-Tool -Names @('protoc', 'protoc.exe') -FallbackPaths @($wingetProtoc)
|
||||||
$protocGenGo = Resolve-Tool -Names @('protoc-gen-go', 'protoc-gen-go.exe') -FallbackPaths @((if ($goBin) { Join-Path $goBin 'protoc-gen-go.exe' }), (if ($goBin) { Join-Path $goBin 'protoc-gen-go' }))
|
$protocGenGo = Resolve-Tool -Names @('protoc-gen-go', 'protoc-gen-go.exe') -FallbackPaths @(($(if ($goBin) { Join-Path $goBin 'protoc-gen-go.exe' })), ($(if ($goBin) { Join-Path $goBin 'protoc-gen-go' })))
|
||||||
$protocGenGoGrpc = Resolve-Tool -Names @('protoc-gen-go-grpc', 'protoc-gen-go-grpc.exe') -FallbackPaths @((if ($goBin) { Join-Path $goBin 'protoc-gen-go-grpc.exe' }), (if ($goBin) { Join-Path $goBin 'protoc-gen-go-grpc' }))
|
$protocGenGoGrpc = Resolve-Tool -Names @('protoc-gen-go-grpc', 'protoc-gen-go-grpc.exe') -FallbackPaths @(($(if ($goBin) { Join-Path $goBin 'protoc-gen-go-grpc.exe' })), ($(if ($goBin) { Join-Path $goBin 'protoc-gen-go-grpc' })))
|
||||||
|
|
||||||
|
# Assert the pinned plugin versions before generating so Check 4 cannot false-fail (or mask drift)
|
||||||
|
# on an off-pin machine. protoc is warn-only.
|
||||||
|
$protocGenGoVersion = (& $protocGenGo --version 2>&1 | Out-String).Trim()
|
||||||
|
if ($protocGenGoVersion -ne $PinnedProtocGenGoVersion) {
|
||||||
|
throw "protoc-gen-go reports '$protocGenGoVersion', but regeneration is pinned to '$PinnedProtocGenGoVersion'. " +
|
||||||
|
"Install the pin: go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.11"
|
||||||
|
}
|
||||||
|
$protocGenGoGrpcVersion = (& $protocGenGoGrpc --version 2>&1 | Out-String).Trim()
|
||||||
|
if ($protocGenGoGrpcVersion -ne $PinnedProtocGenGoGrpcVersion) {
|
||||||
|
throw "protoc-gen-go-grpc reports '$protocGenGoGrpcVersion', but regeneration is pinned to '$PinnedProtocGenGoGrpcVersion'. " +
|
||||||
|
"Install the pin: go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.6.2"
|
||||||
|
}
|
||||||
|
$protocVersion = (& $protoc --version 2>&1 | Out-String).Trim()
|
||||||
|
if ($protocVersion -ne $PinnedProtocVersion) {
|
||||||
|
Write-Warning "protoc reports '$protocVersion', pin is '$PinnedProtocVersion'. Descriptor comments are normalized out of the committed Go bindings, so patch drift is tolerated; keep CI on the pin."
|
||||||
|
}
|
||||||
|
|
||||||
# protoc discovers the plugins on PATH; prepend the directories the resolved plugins live in.
|
# protoc discovers the plugins on PATH; prepend the directories the resolved plugins live in.
|
||||||
$env:Path = (Split-Path $protocGenGo -Parent) + [System.IO.Path]::PathSeparator + (Split-Path $protocGenGoGrpc -Parent) + [System.IO.Path]::PathSeparator + $env:Path
|
$env:Path = (Split-Path $protocGenGo -Parent) + [System.IO.Path]::PathSeparator + (Split-Path $protocGenGoGrpc -Parent) + [System.IO.Path]::PathSeparator + $env:Path
|
||||||
|
|||||||
@@ -5974,8 +5974,12 @@ func (x *WorkerInfoReply) GetMxaccessClsid() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DrainEventsReply struct {
|
type DrainEventsReply struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Events []*MxEvent `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"`
|
// The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
// worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
// `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
// empty reply.
|
||||||
|
Events []*MxEvent `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
@@ -6411,6 +6415,11 @@ type ReplayGap struct {
|
|||||||
// after_worker_sequence = oldest_available_sequence - 1 in the next
|
// after_worker_sequence = oldest_available_sequence - 1 in the next
|
||||||
// StreamEventsRequest, which will cause the server to replay starting at
|
// StreamEventsRequest, which will cause the server to replay starting at
|
||||||
// oldest_available_sequence (the first retained event).
|
// oldest_available_sequence (the first retained event).
|
||||||
|
// When nothing is retained (the replay ring is empty), this is the next sequence
|
||||||
|
// that can be delivered — `highest observed + 1` — and the `oldest - 1` resume
|
||||||
|
// formula remains valid: it resolves to the highest sequence already seen, so the
|
||||||
|
// follow-up resume replays nothing, reports no gap, and every newer live event
|
||||||
|
// passes. The interval evicted is unchanged.
|
||||||
OldestAvailableSequence uint64 `protobuf:"varint,2,opt,name=oldest_available_sequence,json=oldestAvailableSequence,proto3" json:"oldest_available_sequence,omitempty"`
|
OldestAvailableSequence uint64 `protobuf:"varint,2,opt,name=oldest_available_sequence,json=oldestAvailableSequence,proto3" json:"oldest_available_sequence,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
|
|||||||
@@ -431,8 +431,17 @@ type GatewayHello struct {
|
|||||||
SupportedProtocolVersion uint32 `protobuf:"varint,1,opt,name=supported_protocol_version,json=supportedProtocolVersion,proto3" json:"supported_protocol_version,omitempty"`
|
SupportedProtocolVersion uint32 `protobuf:"varint,1,opt,name=supported_protocol_version,json=supportedProtocolVersion,proto3" json:"supported_protocol_version,omitempty"`
|
||||||
Nonce string `protobuf:"bytes,2,opt,name=nonce,proto3" json:"nonce,omitempty"`
|
Nonce string `protobuf:"bytes,2,opt,name=nonce,proto3" json:"nonce,omitempty"`
|
||||||
GatewayVersion string `protobuf:"bytes,3,opt,name=gateway_version,json=gatewayVersion,proto3" json:"gateway_version,omitempty"`
|
GatewayVersion string `protobuf:"bytes,3,opt,name=gateway_version,json=gatewayVersion,proto3" json:"gateway_version,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
// Maximum worker-frame payload size, in bytes, negotiated by the gateway from its
|
||||||
sizeCache protoimpl.SizeCache
|
// configured pipe limit. The worker adopts this as its frame-protocol MaxMessageBytes
|
||||||
|
// instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
||||||
|
// "use the worker's built-in default". Sits above the public gRPC cap by an
|
||||||
|
// envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
||||||
|
// Every worker->gateway frame — events, heartbeats, faults, and control replies
|
||||||
|
// including DrainEvents — must serialize within this limit; reply builders truncate
|
||||||
|
// to fit rather than emit an oversized frame.
|
||||||
|
MaxFrameBytes uint32 `protobuf:"varint,4,opt,name=max_frame_bytes,json=maxFrameBytes,proto3" json:"max_frame_bytes,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GatewayHello) Reset() {
|
func (x *GatewayHello) Reset() {
|
||||||
@@ -486,6 +495,13 @@ func (x *GatewayHello) GetGatewayVersion() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *GatewayHello) GetMaxFrameBytes() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.MaxFrameBytes
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
type WorkerHello struct {
|
type WorkerHello struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
ProtocolVersion uint32 `protobuf:"varint,1,opt,name=protocol_version,json=protocolVersion,proto3" json:"protocol_version,omitempty"`
|
ProtocolVersion uint32 `protobuf:"varint,1,opt,name=protocol_version,json=protocolVersion,proto3" json:"protocol_version,omitempty"`
|
||||||
@@ -1109,11 +1125,12 @@ const file_mxaccess_worker_proto_rawDesc = "" +
|
|||||||
"\fworker_event\x18\x12 \x01(\v2\x1f.mxaccess_worker.v1.WorkerEventH\x00R\vworkerEvent\x12P\n" +
|
"\fworker_event\x18\x12 \x01(\v2\x1f.mxaccess_worker.v1.WorkerEventH\x00R\vworkerEvent\x12P\n" +
|
||||||
"\x10worker_heartbeat\x18\x13 \x01(\v2#.mxaccess_worker.v1.WorkerHeartbeatH\x00R\x0fworkerHeartbeat\x12D\n" +
|
"\x10worker_heartbeat\x18\x13 \x01(\v2#.mxaccess_worker.v1.WorkerHeartbeatH\x00R\x0fworkerHeartbeat\x12D\n" +
|
||||||
"\fworker_fault\x18\x14 \x01(\v2\x1f.mxaccess_worker.v1.WorkerFaultH\x00R\vworkerFaultB\x06\n" +
|
"\fworker_fault\x18\x14 \x01(\v2\x1f.mxaccess_worker.v1.WorkerFaultH\x00R\vworkerFaultB\x06\n" +
|
||||||
"\x04body\"\x8b\x01\n" +
|
"\x04body\"\xb3\x01\n" +
|
||||||
"\fGatewayHello\x12<\n" +
|
"\fGatewayHello\x12<\n" +
|
||||||
"\x1asupported_protocol_version\x18\x01 \x01(\rR\x18supportedProtocolVersion\x12\x14\n" +
|
"\x1asupported_protocol_version\x18\x01 \x01(\rR\x18supportedProtocolVersion\x12\x14\n" +
|
||||||
"\x05nonce\x18\x02 \x01(\tR\x05nonce\x12'\n" +
|
"\x05nonce\x18\x02 \x01(\tR\x05nonce\x12'\n" +
|
||||||
"\x0fgateway_version\x18\x03 \x01(\tR\x0egatewayVersion\"\xa1\x01\n" +
|
"\x0fgateway_version\x18\x03 \x01(\tR\x0egatewayVersion\x12&\n" +
|
||||||
|
"\x0fmax_frame_bytes\x18\x04 \x01(\rR\rmaxFrameBytes\"\xa1\x01\n" +
|
||||||
"\vWorkerHello\x12)\n" +
|
"\vWorkerHello\x12)\n" +
|
||||||
"\x10protocol_version\x18\x01 \x01(\rR\x0fprotocolVersion\x12\x14\n" +
|
"\x10protocol_version\x18\x01 \x01(\rR\x0fprotocolVersion\x12\x14\n" +
|
||||||
"\x05nonce\x18\x02 \x01(\tR\x05nonce\x12*\n" +
|
"\x05nonce\x18\x02 \x01(\tR\x05nonce\x12*\n" +
|
||||||
|
|||||||
@@ -69110,24 +69110,59 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
com.google.protobuf.MessageOrBuilder {
|
com.google.protobuf.MessageOrBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
java.util.List<mxaccess_gateway.v1.MxaccessGateway.MxEvent>
|
java.util.List<mxaccess_gateway.v1.MxaccessGateway.MxEvent>
|
||||||
getEventsList();
|
getEventsList();
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
mxaccess_gateway.v1.MxaccessGateway.MxEvent getEvents(int index);
|
mxaccess_gateway.v1.MxaccessGateway.MxEvent getEvents(int index);
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
int getEventsCount();
|
int getEventsCount();
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
java.util.List<? extends mxaccess_gateway.v1.MxaccessGateway.MxEventOrBuilder>
|
java.util.List<? extends mxaccess_gateway.v1.MxaccessGateway.MxEventOrBuilder>
|
||||||
getEventsOrBuilderList();
|
getEventsOrBuilderList();
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
mxaccess_gateway.v1.MxaccessGateway.MxEventOrBuilder getEventsOrBuilder(
|
mxaccess_gateway.v1.MxaccessGateway.MxEventOrBuilder getEventsOrBuilder(
|
||||||
@@ -69175,6 +69210,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
private java.util.List<mxaccess_gateway.v1.MxaccessGateway.MxEvent> events_;
|
private java.util.List<mxaccess_gateway.v1.MxaccessGateway.MxEvent> events_;
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
@java.lang.Override
|
@java.lang.Override
|
||||||
@@ -69182,6 +69224,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
return events_;
|
return events_;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
@java.lang.Override
|
@java.lang.Override
|
||||||
@@ -69190,6 +69239,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
return events_;
|
return events_;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
@java.lang.Override
|
@java.lang.Override
|
||||||
@@ -69197,6 +69253,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
return events_.size();
|
return events_.size();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
@java.lang.Override
|
@java.lang.Override
|
||||||
@@ -69204,6 +69267,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
return events_.get(index);
|
return events_.get(index);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
@java.lang.Override
|
@java.lang.Override
|
||||||
@@ -69567,6 +69637,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
mxaccess_gateway.v1.MxaccessGateway.MxEvent, mxaccess_gateway.v1.MxaccessGateway.MxEvent.Builder, mxaccess_gateway.v1.MxaccessGateway.MxEventOrBuilder> eventsBuilder_;
|
mxaccess_gateway.v1.MxaccessGateway.MxEvent, mxaccess_gateway.v1.MxaccessGateway.MxEvent.Builder, mxaccess_gateway.v1.MxaccessGateway.MxEventOrBuilder> eventsBuilder_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public java.util.List<mxaccess_gateway.v1.MxaccessGateway.MxEvent> getEventsList() {
|
public java.util.List<mxaccess_gateway.v1.MxaccessGateway.MxEvent> getEventsList() {
|
||||||
@@ -69577,6 +69654,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public int getEventsCount() {
|
public int getEventsCount() {
|
||||||
@@ -69587,6 +69671,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public mxaccess_gateway.v1.MxaccessGateway.MxEvent getEvents(int index) {
|
public mxaccess_gateway.v1.MxaccessGateway.MxEvent getEvents(int index) {
|
||||||
@@ -69597,6 +69688,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public Builder setEvents(
|
public Builder setEvents(
|
||||||
@@ -69614,6 +69712,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public Builder setEvents(
|
public Builder setEvents(
|
||||||
@@ -69628,6 +69733,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public Builder addEvents(mxaccess_gateway.v1.MxaccessGateway.MxEvent value) {
|
public Builder addEvents(mxaccess_gateway.v1.MxaccessGateway.MxEvent value) {
|
||||||
@@ -69644,6 +69756,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public Builder addEvents(
|
public Builder addEvents(
|
||||||
@@ -69661,6 +69780,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public Builder addEvents(
|
public Builder addEvents(
|
||||||
@@ -69675,6 +69801,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public Builder addEvents(
|
public Builder addEvents(
|
||||||
@@ -69689,6 +69822,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public Builder addAllEvents(
|
public Builder addAllEvents(
|
||||||
@@ -69704,6 +69844,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public Builder clearEvents() {
|
public Builder clearEvents() {
|
||||||
@@ -69717,6 +69864,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public Builder removeEvents(int index) {
|
public Builder removeEvents(int index) {
|
||||||
@@ -69730,6 +69884,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public mxaccess_gateway.v1.MxaccessGateway.MxEvent.Builder getEventsBuilder(
|
public mxaccess_gateway.v1.MxaccessGateway.MxEvent.Builder getEventsBuilder(
|
||||||
@@ -69737,6 +69898,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
return internalGetEventsFieldBuilder().getBuilder(index);
|
return internalGetEventsFieldBuilder().getBuilder(index);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public mxaccess_gateway.v1.MxaccessGateway.MxEventOrBuilder getEventsOrBuilder(
|
public mxaccess_gateway.v1.MxaccessGateway.MxEventOrBuilder getEventsOrBuilder(
|
||||||
@@ -69747,6 +69915,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public java.util.List<? extends mxaccess_gateway.v1.MxaccessGateway.MxEventOrBuilder>
|
public java.util.List<? extends mxaccess_gateway.v1.MxaccessGateway.MxEventOrBuilder>
|
||||||
@@ -69758,6 +69933,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public mxaccess_gateway.v1.MxaccessGateway.MxEvent.Builder addEventsBuilder() {
|
public mxaccess_gateway.v1.MxaccessGateway.MxEvent.Builder addEventsBuilder() {
|
||||||
@@ -69765,6 +69947,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
mxaccess_gateway.v1.MxaccessGateway.MxEvent.getDefaultInstance());
|
mxaccess_gateway.v1.MxaccessGateway.MxEvent.getDefaultInstance());
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public mxaccess_gateway.v1.MxaccessGateway.MxEvent.Builder addEventsBuilder(
|
public mxaccess_gateway.v1.MxaccessGateway.MxEvent.Builder addEventsBuilder(
|
||||||
@@ -69773,6 +69962,13 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
index, mxaccess_gateway.v1.MxaccessGateway.MxEvent.getDefaultInstance());
|
index, mxaccess_gateway.v1.MxaccessGateway.MxEvent.getDefaultInstance());
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* <pre>
|
||||||
|
* The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
* worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
* `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
* empty reply.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
* <code>repeated .mxaccess_gateway.v1.MxEvent events = 1;</code>
|
||||||
*/
|
*/
|
||||||
public java.util.List<mxaccess_gateway.v1.MxaccessGateway.MxEvent.Builder>
|
public java.util.List<mxaccess_gateway.v1.MxaccessGateway.MxEvent.Builder>
|
||||||
@@ -75305,6 +75501,11 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
* after_worker_sequence = oldest_available_sequence - 1 in the next
|
* after_worker_sequence = oldest_available_sequence - 1 in the next
|
||||||
* StreamEventsRequest, which will cause the server to replay starting at
|
* StreamEventsRequest, which will cause the server to replay starting at
|
||||||
* oldest_available_sequence (the first retained event).
|
* oldest_available_sequence (the first retained event).
|
||||||
|
* When nothing is retained (the replay ring is empty), this is the next sequence
|
||||||
|
* that can be delivered — `highest observed + 1` — and the `oldest - 1` resume
|
||||||
|
* formula remains valid: it resolves to the highest sequence already seen, so the
|
||||||
|
* follow-up resume replays nothing, reports no gap, and every newer live event
|
||||||
|
* passes. The interval evicted is unchanged.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <code>uint64 oldest_available_sequence = 2;</code>
|
* <code>uint64 oldest_available_sequence = 2;</code>
|
||||||
@@ -75386,6 +75587,11 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
* after_worker_sequence = oldest_available_sequence - 1 in the next
|
* after_worker_sequence = oldest_available_sequence - 1 in the next
|
||||||
* StreamEventsRequest, which will cause the server to replay starting at
|
* StreamEventsRequest, which will cause the server to replay starting at
|
||||||
* oldest_available_sequence (the first retained event).
|
* oldest_available_sequence (the first retained event).
|
||||||
|
* When nothing is retained (the replay ring is empty), this is the next sequence
|
||||||
|
* that can be delivered — `highest observed + 1` — and the `oldest - 1` resume
|
||||||
|
* formula remains valid: it resolves to the highest sequence already seen, so the
|
||||||
|
* follow-up resume replays nothing, reports no gap, and every newer live event
|
||||||
|
* passes. The interval evicted is unchanged.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <code>uint64 oldest_available_sequence = 2;</code>
|
* <code>uint64 oldest_available_sequence = 2;</code>
|
||||||
@@ -75781,6 +75987,11 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
* after_worker_sequence = oldest_available_sequence - 1 in the next
|
* after_worker_sequence = oldest_available_sequence - 1 in the next
|
||||||
* StreamEventsRequest, which will cause the server to replay starting at
|
* StreamEventsRequest, which will cause the server to replay starting at
|
||||||
* oldest_available_sequence (the first retained event).
|
* oldest_available_sequence (the first retained event).
|
||||||
|
* When nothing is retained (the replay ring is empty), this is the next sequence
|
||||||
|
* that can be delivered — `highest observed + 1` — and the `oldest - 1` resume
|
||||||
|
* formula remains valid: it resolves to the highest sequence already seen, so the
|
||||||
|
* follow-up resume replays nothing, reports no gap, and every newer live event
|
||||||
|
* passes. The interval evicted is unchanged.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <code>uint64 oldest_available_sequence = 2;</code>
|
* <code>uint64 oldest_available_sequence = 2;</code>
|
||||||
@@ -75800,6 +76011,11 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
* after_worker_sequence = oldest_available_sequence - 1 in the next
|
* after_worker_sequence = oldest_available_sequence - 1 in the next
|
||||||
* StreamEventsRequest, which will cause the server to replay starting at
|
* StreamEventsRequest, which will cause the server to replay starting at
|
||||||
* oldest_available_sequence (the first retained event).
|
* oldest_available_sequence (the first retained event).
|
||||||
|
* When nothing is retained (the replay ring is empty), this is the next sequence
|
||||||
|
* that can be delivered — `highest observed + 1` — and the `oldest - 1` resume
|
||||||
|
* formula remains valid: it resolves to the highest sequence already seen, so the
|
||||||
|
* follow-up resume replays nothing, reports no gap, and every newer live event
|
||||||
|
* passes. The interval evicted is unchanged.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <code>uint64 oldest_available_sequence = 2;</code>
|
* <code>uint64 oldest_available_sequence = 2;</code>
|
||||||
@@ -75823,6 +76039,11 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile {
|
|||||||
* after_worker_sequence = oldest_available_sequence - 1 in the next
|
* after_worker_sequence = oldest_available_sequence - 1 in the next
|
||||||
* StreamEventsRequest, which will cause the server to replay starting at
|
* StreamEventsRequest, which will cause the server to replay starting at
|
||||||
* oldest_available_sequence (the first retained event).
|
* oldest_available_sequence (the first retained event).
|
||||||
|
* When nothing is retained (the replay ring is empty), this is the next sequence
|
||||||
|
* that can be delivered — `highest observed + 1` — and the `oldest - 1` resume
|
||||||
|
* formula remains valid: it resolves to the highest sequence already seen, so the
|
||||||
|
* follow-up resume replays nothing, reports no gap, and every newer live event
|
||||||
|
* passes. The interval evicted is unchanged.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <code>uint64 oldest_available_sequence = 2;</code>
|
* <code>uint64 oldest_available_sequence = 2;</code>
|
||||||
|
|||||||
@@ -3797,6 +3797,9 @@ public final class MxaccessWorker extends com.google.protobuf.GeneratedFile {
|
|||||||
* instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
* instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
||||||
* "use the worker's built-in default". Sits above the public gRPC cap by an
|
* "use the worker's built-in default". Sits above the public gRPC cap by an
|
||||||
* envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
* envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
||||||
|
* Every worker->gateway frame — events, heartbeats, faults, and control replies
|
||||||
|
* including DrainEvents — must serialize within this limit; reply builders truncate
|
||||||
|
* to fit rather than emit an oversized frame.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <code>uint32 max_frame_bytes = 4;</code>
|
* <code>uint32 max_frame_bytes = 4;</code>
|
||||||
@@ -3941,6 +3944,9 @@ public final class MxaccessWorker extends com.google.protobuf.GeneratedFile {
|
|||||||
* instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
* instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
||||||
* "use the worker's built-in default". Sits above the public gRPC cap by an
|
* "use the worker's built-in default". Sits above the public gRPC cap by an
|
||||||
* envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
* envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
||||||
|
* Every worker->gateway frame — events, heartbeats, faults, and control replies
|
||||||
|
* including DrainEvents — must serialize within this limit; reply builders truncate
|
||||||
|
* to fit rather than emit an oversized frame.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <code>uint32 max_frame_bytes = 4;</code>
|
* <code>uint32 max_frame_bytes = 4;</code>
|
||||||
@@ -4499,6 +4505,9 @@ public final class MxaccessWorker extends com.google.protobuf.GeneratedFile {
|
|||||||
* instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
* instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
||||||
* "use the worker's built-in default". Sits above the public gRPC cap by an
|
* "use the worker's built-in default". Sits above the public gRPC cap by an
|
||||||
* envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
* envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
||||||
|
* Every worker->gateway frame — events, heartbeats, faults, and control replies
|
||||||
|
* including DrainEvents — must serialize within this limit; reply builders truncate
|
||||||
|
* to fit rather than emit an oversized frame.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <code>uint32 max_frame_bytes = 4;</code>
|
* <code>uint32 max_frame_bytes = 4;</code>
|
||||||
@@ -4515,6 +4524,9 @@ public final class MxaccessWorker extends com.google.protobuf.GeneratedFile {
|
|||||||
* instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
* instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
||||||
* "use the worker's built-in default". Sits above the public gRPC cap by an
|
* "use the worker's built-in default". Sits above the public gRPC cap by an
|
||||||
* envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
* envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
||||||
|
* Every worker->gateway frame — events, heartbeats, faults, and control replies
|
||||||
|
* including DrainEvents — must serialize within this limit; reply builders truncate
|
||||||
|
* to fit rather than emit an oversized frame.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <code>uint32 max_frame_bytes = 4;</code>
|
* <code>uint32 max_frame_bytes = 4;</code>
|
||||||
@@ -4535,6 +4547,9 @@ public final class MxaccessWorker extends com.google.protobuf.GeneratedFile {
|
|||||||
* instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
* instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
||||||
* "use the worker's built-in default". Sits above the public gRPC cap by an
|
* "use the worker's built-in default". Sits above the public gRPC cap by an
|
||||||
* envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
* envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
||||||
|
* Every worker->gateway frame — events, heartbeats, faults, and control replies
|
||||||
|
* including DrainEvents — must serialize within this limit; reply builders truncate
|
||||||
|
* to fit rather than emit an oversized frame.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* <code>uint32 max_frame_bytes = 4;</code>
|
* <code>uint32 max_frame_bytes = 4;</code>
|
||||||
|
|||||||
@@ -63,10 +63,11 @@ protobuf {
|
|||||||
// or a plugin/protobuf version bump, silently drifts the committed output. checkGeneratedClean
|
// or a plugin/protobuf version bump, silently drifts the committed output. checkGeneratedClean
|
||||||
// fails when the regenerated tree differs from what is committed.
|
// fails when the regenerated tree differs from what is committed.
|
||||||
//
|
//
|
||||||
// Caveat (repo memory project_java_generated_churn): the protobuf gradle plugin also rewrites
|
// The grpc/protobuf toolchain is pinned (build.gradle: grpcVersion / protobufVersion), so a
|
||||||
// MxaccessGateway.java with a spurious protobuf-runtime-version delta on every build even when no
|
// regeneration is byte-identical to the committed single-file aggregates modulo real .proto
|
||||||
// .proto changed. CI reverts that one file (git checkout) before invoking this task; locally, do the
|
// changes — no spurious protobuf-runtime-version churn (IPC-24 verified this and deleted the old
|
||||||
// same when you did not touch a .proto. See docs/GatewayTesting.md "Continuous Integration".
|
// unconditional CI churn-revert step, which masked message-level drift). Regenerate and commit
|
||||||
|
// after any .proto change. See docs/GatewayTesting.md "Continuous Integration".
|
||||||
tasks.register('checkGeneratedClean') {
|
tasks.register('checkGeneratedClean') {
|
||||||
group = 'verification'
|
group = 'verification'
|
||||||
description = 'Fails if the committed generated Java tree differs from a fresh regeneration.'
|
description = 'Fails if the committed generated Java tree differs from a fresh regeneration.'
|
||||||
@@ -83,9 +84,9 @@ tasks.register('checkGeneratedClean') {
|
|||||||
def dirty = stdout.toString().trim()
|
def dirty = stdout.toString().trim()
|
||||||
if (!dirty.isEmpty()) {
|
if (!dirty.isEmpty()) {
|
||||||
throw new GradleException(
|
throw new GradleException(
|
||||||
"Generated Java is stale or churned:\n${dirty}\n" +
|
"Generated Java is stale:\n${dirty}\n" +
|
||||||
"Regenerate and commit after a .proto change, or 'git checkout' the spurious " +
|
"Regenerate and commit the Java client after a .proto change " +
|
||||||
"MxaccessGateway.java protobuf-version churn when no .proto changed.")
|
"(gradle :zb-mom-ww-mxgateway-client:generateProto).")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -27,7 +27,7 @@ from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__
|
|||||||
import mxaccess_gateway_pb2 as mxaccess__gateway__pb2
|
import mxaccess_gateway_pb2 as mxaccess__gateway__pb2
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15mxaccess_worker.proto\x12\x12mxaccess_worker.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x16mxaccess_gateway.proto\"\x95\x06\n\x0eWorkerEnvelope\x12\x18\n\x10protocol_version\x18\x01 \x01(\r\x12\x12\n\nsession_id\x18\x02 \x01(\t\x12\x10\n\x08sequence\x18\x03 \x01(\x04\x12\x16\n\x0e\x63orrelation_id\x18\x04 \x01(\t\x12\x39\n\rgateway_hello\x18\n \x01(\x0b\x32 .mxaccess_worker.v1.GatewayHelloH\x00\x12\x37\n\x0cworker_hello\x18\x0b \x01(\x0b\x32\x1f.mxaccess_worker.v1.WorkerHelloH\x00\x12\x37\n\x0cworker_ready\x18\x0c \x01(\x0b\x32\x1f.mxaccess_worker.v1.WorkerReadyH\x00\x12;\n\x0eworker_command\x18\r \x01(\x0b\x32!.mxaccess_worker.v1.WorkerCommandH\x00\x12\x46\n\x14worker_command_reply\x18\x0e \x01(\x0b\x32&.mxaccess_worker.v1.WorkerCommandReplyH\x00\x12\x39\n\rworker_cancel\x18\x0f \x01(\x0b\x32 .mxaccess_worker.v1.WorkerCancelH\x00\x12=\n\x0fworker_shutdown\x18\x10 \x01(\x0b\x32\".mxaccess_worker.v1.WorkerShutdownH\x00\x12\x44\n\x13worker_shutdown_ack\x18\x11 \x01(\x0b\x32%.mxaccess_worker.v1.WorkerShutdownAckH\x00\x12\x37\n\x0cworker_event\x18\x12 \x01(\x0b\x32\x1f.mxaccess_worker.v1.WorkerEventH\x00\x12?\n\x10worker_heartbeat\x18\x13 \x01(\x0b\x32#.mxaccess_worker.v1.WorkerHeartbeatH\x00\x12\x37\n\x0cworker_fault\x18\x14 \x01(\x0b\x32\x1f.mxaccess_worker.v1.WorkerFaultH\x00\x42\x06\n\x04\x62ody\"Z\n\x0cGatewayHello\x12\"\n\x1asupported_protocol_version\x18\x01 \x01(\r\x12\r\n\x05nonce\x18\x02 \x01(\t\x12\x17\n\x0fgateway_version\x18\x03 \x01(\t\"i\n\x0bWorkerHello\x12\x18\n\x10protocol_version\x18\x01 \x01(\r\x12\r\n\x05nonce\x18\x02 \x01(\t\x12\x19\n\x11worker_process_id\x18\x03 \x01(\x05\x12\x16\n\x0eworker_version\x18\x04 \x01(\t\"\x8e\x01\n\x0bWorkerReady\x12\x19\n\x11worker_process_id\x18\x01 \x01(\x05\x12\x17\n\x0fmxaccess_progid\x18\x02 \x01(\t\x12\x16\n\x0emxaccess_clsid\x18\x03 \x01(\t\x12\x33\n\x0fready_timestamp\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"w\n\rWorkerCommand\x12/\n\x07\x63ommand\x18\x01 \x01(\x0b\x32\x1e.mxaccess_gateway.v1.MxCommand\x12\x35\n\x11\x65nqueue_timestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\x81\x01\n\x12WorkerCommandReply\x12\x32\n\x05reply\x18\x01 \x01(\x0b\x32#.mxaccess_gateway.v1.MxCommandReply\x12\x37\n\x13\x63ompleted_timestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\x1e\n\x0cWorkerCancel\x12\x0e\n\x06reason\x18\x01 \x01(\t\"Q\n\x0eWorkerShutdown\x12/\n\x0cgrace_period\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0e\n\x06reason\x18\x02 \x01(\t\"H\n\x11WorkerShutdownAck\x12\x33\n\x06status\x18\x01 \x01(\x0b\x32#.mxaccess_gateway.v1.ProtocolStatus\":\n\x0bWorkerEvent\x12+\n\x05\x65vent\x18\x01 \x01(\x0b\x32\x1c.mxaccess_gateway.v1.MxEvent\"\xa5\x02\n\x0fWorkerHeartbeat\x12\x19\n\x11worker_process_id\x18\x01 \x01(\x05\x12.\n\x05state\x18\x02 \x01(\x0e\x32\x1f.mxaccess_worker.v1.WorkerState\x12?\n\x1blast_sta_activity_timestamp\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15pending_command_count\x18\x04 \x01(\r\x12\"\n\x1aoutbound_event_queue_depth\x18\x05 \x01(\r\x12\x1b\n\x13last_event_sequence\x18\x06 \x01(\x04\x12&\n\x1e\x63urrent_command_correlation_id\x18\x07 \x01(\t\"\xf4\x01\n\x0bWorkerFault\x12\x39\n\x08\x63\x61tegory\x18\x01 \x01(\x0e\x32\'.mxaccess_worker.v1.WorkerFaultCategory\x12\x16\n\x0e\x63ommand_method\x18\x02 \x01(\t\x12\x14\n\x07hresult\x18\x03 \x01(\x05H\x00\x88\x01\x01\x12\x16\n\x0e\x65xception_type\x18\x04 \x01(\t\x12\x1a\n\x12\x64iagnostic_message\x18\x05 \x01(\t\x12<\n\x0fprotocol_status\x18\x06 \x01(\x0b\x32#.mxaccess_gateway.v1.ProtocolStatusB\n\n\x08_hresult*\x97\x02\n\x0bWorkerState\x12\x1c\n\x18WORKER_STATE_UNSPECIFIED\x10\x00\x12\x19\n\x15WORKER_STATE_STARTING\x10\x01\x12\x1c\n\x18WORKER_STATE_HANDSHAKING\x10\x02\x12!\n\x1dWORKER_STATE_INITIALIZING_STA\x10\x03\x12\x16\n\x12WORKER_STATE_READY\x10\x04\x12\"\n\x1eWORKER_STATE_EXECUTING_COMMAND\x10\x05\x12\x1e\n\x1aWORKER_STATE_SHUTTING_DOWN\x10\x06\x12\x18\n\x14WORKER_STATE_STOPPED\x10\x07\x12\x18\n\x14WORKER_STATE_FAULTED\x10\x08*\xc7\x04\n\x13WorkerFaultCategory\x12%\n!WORKER_FAULT_CATEGORY_UNSPECIFIED\x10\x00\x12+\n\'WORKER_FAULT_CATEGORY_INVALID_ARGUMENTS\x10\x01\x12\x37\n3WORKER_FAULT_CATEGORY_GATEWAY_AUTHENTICATION_FAILED\x10\x02\x12+\n\'WORKER_FAULT_CATEGORY_PROTOCOL_MISMATCH\x10\x03\x12,\n(WORKER_FAULT_CATEGORY_PROTOCOL_VIOLATION\x10\x04\x12+\n\'WORKER_FAULT_CATEGORY_PIPE_DISCONNECTED\x10\x05\x12\x32\n.WORKER_FAULT_CATEGORY_MXACCESS_CREATION_FAILED\x10\x06\x12\x31\n-WORKER_FAULT_CATEGORY_MXACCESS_COMMAND_FAILED\x10\x07\x12:\n6WORKER_FAULT_CATEGORY_MXACCESS_EVENT_CONVERSION_FAILED\x10\x08\x12\"\n\x1eWORKER_FAULT_CATEGORY_STA_HUNG\x10\t\x12(\n$WORKER_FAULT_CATEGORY_QUEUE_OVERFLOW\x10\n\x12*\n&WORKER_FAULT_CATEGORY_SHUTDOWN_TIMEOUT\x10\x0b\x42&\xaa\x02#ZB.MOM.WW.MxGateway.Contracts.Protob\x06proto3')
|
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x15mxaccess_worker.proto\x12\x12mxaccess_worker.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x16mxaccess_gateway.proto\"\x95\x06\n\x0eWorkerEnvelope\x12\x18\n\x10protocol_version\x18\x01 \x01(\r\x12\x12\n\nsession_id\x18\x02 \x01(\t\x12\x10\n\x08sequence\x18\x03 \x01(\x04\x12\x16\n\x0e\x63orrelation_id\x18\x04 \x01(\t\x12\x39\n\rgateway_hello\x18\n \x01(\x0b\x32 .mxaccess_worker.v1.GatewayHelloH\x00\x12\x37\n\x0cworker_hello\x18\x0b \x01(\x0b\x32\x1f.mxaccess_worker.v1.WorkerHelloH\x00\x12\x37\n\x0cworker_ready\x18\x0c \x01(\x0b\x32\x1f.mxaccess_worker.v1.WorkerReadyH\x00\x12;\n\x0eworker_command\x18\r \x01(\x0b\x32!.mxaccess_worker.v1.WorkerCommandH\x00\x12\x46\n\x14worker_command_reply\x18\x0e \x01(\x0b\x32&.mxaccess_worker.v1.WorkerCommandReplyH\x00\x12\x39\n\rworker_cancel\x18\x0f \x01(\x0b\x32 .mxaccess_worker.v1.WorkerCancelH\x00\x12=\n\x0fworker_shutdown\x18\x10 \x01(\x0b\x32\".mxaccess_worker.v1.WorkerShutdownH\x00\x12\x44\n\x13worker_shutdown_ack\x18\x11 \x01(\x0b\x32%.mxaccess_worker.v1.WorkerShutdownAckH\x00\x12\x37\n\x0cworker_event\x18\x12 \x01(\x0b\x32\x1f.mxaccess_worker.v1.WorkerEventH\x00\x12?\n\x10worker_heartbeat\x18\x13 \x01(\x0b\x32#.mxaccess_worker.v1.WorkerHeartbeatH\x00\x12\x37\n\x0cworker_fault\x18\x14 \x01(\x0b\x32\x1f.mxaccess_worker.v1.WorkerFaultH\x00\x42\x06\n\x04\x62ody\"s\n\x0cGatewayHello\x12\"\n\x1asupported_protocol_version\x18\x01 \x01(\r\x12\r\n\x05nonce\x18\x02 \x01(\t\x12\x17\n\x0fgateway_version\x18\x03 \x01(\t\x12\x17\n\x0fmax_frame_bytes\x18\x04 \x01(\r\"i\n\x0bWorkerHello\x12\x18\n\x10protocol_version\x18\x01 \x01(\r\x12\r\n\x05nonce\x18\x02 \x01(\t\x12\x19\n\x11worker_process_id\x18\x03 \x01(\x05\x12\x16\n\x0eworker_version\x18\x04 \x01(\t\"\x8e\x01\n\x0bWorkerReady\x12\x19\n\x11worker_process_id\x18\x01 \x01(\x05\x12\x17\n\x0fmxaccess_progid\x18\x02 \x01(\t\x12\x16\n\x0emxaccess_clsid\x18\x03 \x01(\t\x12\x33\n\x0fready_timestamp\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"w\n\rWorkerCommand\x12/\n\x07\x63ommand\x18\x01 \x01(\x0b\x32\x1e.mxaccess_gateway.v1.MxCommand\x12\x35\n\x11\x65nqueue_timestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\x81\x01\n\x12WorkerCommandReply\x12\x32\n\x05reply\x18\x01 \x01(\x0b\x32#.mxaccess_gateway.v1.MxCommandReply\x12\x37\n\x13\x63ompleted_timestamp\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\x1e\n\x0cWorkerCancel\x12\x0e\n\x06reason\x18\x01 \x01(\t\"Q\n\x0eWorkerShutdown\x12/\n\x0cgrace_period\x18\x01 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x0e\n\x06reason\x18\x02 \x01(\t\"H\n\x11WorkerShutdownAck\x12\x33\n\x06status\x18\x01 \x01(\x0b\x32#.mxaccess_gateway.v1.ProtocolStatus\":\n\x0bWorkerEvent\x12+\n\x05\x65vent\x18\x01 \x01(\x0b\x32\x1c.mxaccess_gateway.v1.MxEvent\"\xa5\x02\n\x0fWorkerHeartbeat\x12\x19\n\x11worker_process_id\x18\x01 \x01(\x05\x12.\n\x05state\x18\x02 \x01(\x0e\x32\x1f.mxaccess_worker.v1.WorkerState\x12?\n\x1blast_sta_activity_timestamp\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x1d\n\x15pending_command_count\x18\x04 \x01(\r\x12\"\n\x1aoutbound_event_queue_depth\x18\x05 \x01(\r\x12\x1b\n\x13last_event_sequence\x18\x06 \x01(\x04\x12&\n\x1e\x63urrent_command_correlation_id\x18\x07 \x01(\t\"\xf4\x01\n\x0bWorkerFault\x12\x39\n\x08\x63\x61tegory\x18\x01 \x01(\x0e\x32\'.mxaccess_worker.v1.WorkerFaultCategory\x12\x16\n\x0e\x63ommand_method\x18\x02 \x01(\t\x12\x14\n\x07hresult\x18\x03 \x01(\x05H\x00\x88\x01\x01\x12\x16\n\x0e\x65xception_type\x18\x04 \x01(\t\x12\x1a\n\x12\x64iagnostic_message\x18\x05 \x01(\t\x12<\n\x0fprotocol_status\x18\x06 \x01(\x0b\x32#.mxaccess_gateway.v1.ProtocolStatusB\n\n\x08_hresult*\x97\x02\n\x0bWorkerState\x12\x1c\n\x18WORKER_STATE_UNSPECIFIED\x10\x00\x12\x19\n\x15WORKER_STATE_STARTING\x10\x01\x12\x1c\n\x18WORKER_STATE_HANDSHAKING\x10\x02\x12!\n\x1dWORKER_STATE_INITIALIZING_STA\x10\x03\x12\x16\n\x12WORKER_STATE_READY\x10\x04\x12\"\n\x1eWORKER_STATE_EXECUTING_COMMAND\x10\x05\x12\x1e\n\x1aWORKER_STATE_SHUTTING_DOWN\x10\x06\x12\x18\n\x14WORKER_STATE_STOPPED\x10\x07\x12\x18\n\x14WORKER_STATE_FAULTED\x10\x08*\xc7\x04\n\x13WorkerFaultCategory\x12%\n!WORKER_FAULT_CATEGORY_UNSPECIFIED\x10\x00\x12+\n\'WORKER_FAULT_CATEGORY_INVALID_ARGUMENTS\x10\x01\x12\x37\n3WORKER_FAULT_CATEGORY_GATEWAY_AUTHENTICATION_FAILED\x10\x02\x12+\n\'WORKER_FAULT_CATEGORY_PROTOCOL_MISMATCH\x10\x03\x12,\n(WORKER_FAULT_CATEGORY_PROTOCOL_VIOLATION\x10\x04\x12+\n\'WORKER_FAULT_CATEGORY_PIPE_DISCONNECTED\x10\x05\x12\x32\n.WORKER_FAULT_CATEGORY_MXACCESS_CREATION_FAILED\x10\x06\x12\x31\n-WORKER_FAULT_CATEGORY_MXACCESS_COMMAND_FAILED\x10\x07\x12:\n6WORKER_FAULT_CATEGORY_MXACCESS_EVENT_CONVERSION_FAILED\x10\x08\x12\"\n\x1eWORKER_FAULT_CATEGORY_STA_HUNG\x10\t\x12(\n$WORKER_FAULT_CATEGORY_QUEUE_OVERFLOW\x10\n\x12*\n&WORKER_FAULT_CATEGORY_SHUTDOWN_TIMEOUT\x10\x0b\x42&\xaa\x02#ZB.MOM.WW.MxGateway.Contracts.Protob\x06proto3')
|
||||||
|
|
||||||
_globals = globals()
|
_globals = globals()
|
||||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
||||||
@@ -35,32 +35,32 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'mxaccess_worker_pb2', _glob
|
|||||||
if not _descriptor._USE_C_DESCRIPTORS:
|
if not _descriptor._USE_C_DESCRIPTORS:
|
||||||
_globals['DESCRIPTOR']._loaded_options = None
|
_globals['DESCRIPTOR']._loaded_options = None
|
||||||
_globals['DESCRIPTOR']._serialized_options = b'\252\002#ZB.MOM.WW.MxGateway.Contracts.Proto'
|
_globals['DESCRIPTOR']._serialized_options = b'\252\002#ZB.MOM.WW.MxGateway.Contracts.Proto'
|
||||||
_globals['_WORKERSTATE']._serialized_start=2316
|
_globals['_WORKERSTATE']._serialized_start=2341
|
||||||
_globals['_WORKERSTATE']._serialized_end=2595
|
_globals['_WORKERSTATE']._serialized_end=2620
|
||||||
_globals['_WORKERFAULTCATEGORY']._serialized_start=2598
|
_globals['_WORKERFAULTCATEGORY']._serialized_start=2623
|
||||||
_globals['_WORKERFAULTCATEGORY']._serialized_end=3181
|
_globals['_WORKERFAULTCATEGORY']._serialized_end=3206
|
||||||
_globals['_WORKERENVELOPE']._serialized_start=135
|
_globals['_WORKERENVELOPE']._serialized_start=135
|
||||||
_globals['_WORKERENVELOPE']._serialized_end=924
|
_globals['_WORKERENVELOPE']._serialized_end=924
|
||||||
_globals['_GATEWAYHELLO']._serialized_start=926
|
_globals['_GATEWAYHELLO']._serialized_start=926
|
||||||
_globals['_GATEWAYHELLO']._serialized_end=1016
|
_globals['_GATEWAYHELLO']._serialized_end=1041
|
||||||
_globals['_WORKERHELLO']._serialized_start=1018
|
_globals['_WORKERHELLO']._serialized_start=1043
|
||||||
_globals['_WORKERHELLO']._serialized_end=1123
|
_globals['_WORKERHELLO']._serialized_end=1148
|
||||||
_globals['_WORKERREADY']._serialized_start=1126
|
_globals['_WORKERREADY']._serialized_start=1151
|
||||||
_globals['_WORKERREADY']._serialized_end=1268
|
_globals['_WORKERREADY']._serialized_end=1293
|
||||||
_globals['_WORKERCOMMAND']._serialized_start=1270
|
_globals['_WORKERCOMMAND']._serialized_start=1295
|
||||||
_globals['_WORKERCOMMAND']._serialized_end=1389
|
_globals['_WORKERCOMMAND']._serialized_end=1414
|
||||||
_globals['_WORKERCOMMANDREPLY']._serialized_start=1392
|
_globals['_WORKERCOMMANDREPLY']._serialized_start=1417
|
||||||
_globals['_WORKERCOMMANDREPLY']._serialized_end=1521
|
_globals['_WORKERCOMMANDREPLY']._serialized_end=1546
|
||||||
_globals['_WORKERCANCEL']._serialized_start=1523
|
_globals['_WORKERCANCEL']._serialized_start=1548
|
||||||
_globals['_WORKERCANCEL']._serialized_end=1553
|
_globals['_WORKERCANCEL']._serialized_end=1578
|
||||||
_globals['_WORKERSHUTDOWN']._serialized_start=1555
|
_globals['_WORKERSHUTDOWN']._serialized_start=1580
|
||||||
_globals['_WORKERSHUTDOWN']._serialized_end=1636
|
_globals['_WORKERSHUTDOWN']._serialized_end=1661
|
||||||
_globals['_WORKERSHUTDOWNACK']._serialized_start=1638
|
_globals['_WORKERSHUTDOWNACK']._serialized_start=1663
|
||||||
_globals['_WORKERSHUTDOWNACK']._serialized_end=1710
|
_globals['_WORKERSHUTDOWNACK']._serialized_end=1735
|
||||||
_globals['_WORKEREVENT']._serialized_start=1712
|
_globals['_WORKEREVENT']._serialized_start=1737
|
||||||
_globals['_WORKEREVENT']._serialized_end=1770
|
_globals['_WORKEREVENT']._serialized_end=1795
|
||||||
_globals['_WORKERHEARTBEAT']._serialized_start=1773
|
_globals['_WORKERHEARTBEAT']._serialized_start=1798
|
||||||
_globals['_WORKERHEARTBEAT']._serialized_end=2066
|
_globals['_WORKERHEARTBEAT']._serialized_end=2091
|
||||||
_globals['_WORKERFAULT']._serialized_start=2069
|
_globals['_WORKERFAULT']._serialized_start=2094
|
||||||
_globals['_WORKERFAULT']._serialized_end=2313
|
_globals['_WORKERFAULT']._serialized_end=2338
|
||||||
# @@protoc_insertion_point(module_scope)
|
# @@protoc_insertion_point(module_scope)
|
||||||
|
|||||||
@@ -676,6 +676,10 @@ message WorkerInfoReply {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message DrainEventsReply {
|
message DrainEventsReply {
|
||||||
|
// The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
// worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
// `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
// empty reply.
|
||||||
repeated MxEvent events = 1;
|
repeated MxEvent events = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -760,6 +764,11 @@ message ReplayGap {
|
|||||||
// after_worker_sequence = oldest_available_sequence - 1 in the next
|
// after_worker_sequence = oldest_available_sequence - 1 in the next
|
||||||
// StreamEventsRequest, which will cause the server to replay starting at
|
// StreamEventsRequest, which will cause the server to replay starting at
|
||||||
// oldest_available_sequence (the first retained event).
|
// oldest_available_sequence (the first retained event).
|
||||||
|
// When nothing is retained (the replay ring is empty), this is the next sequence
|
||||||
|
// that can be delivered — `highest observed + 1` — and the `oldest - 1` resume
|
||||||
|
// formula remains valid: it resolves to the highest sequence already seen, so the
|
||||||
|
// follow-up resume replays nothing, reports no gap, and every newer live event
|
||||||
|
// passes. The interval evicted is unchanged.
|
||||||
uint64 oldest_available_sequence = 2;
|
uint64 oldest_available_sequence = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ message GatewayHello {
|
|||||||
// instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
// instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
||||||
// "use the worker's built-in default". Sits above the public gRPC cap by an
|
// "use the worker's built-in default". Sits above the public gRPC cap by an
|
||||||
// envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
// envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
||||||
|
// Every worker->gateway frame — events, heartbeats, faults, and control replies
|
||||||
|
// including DrainEvents — must serialize within this limit; reply builders truncate
|
||||||
|
// to fit rather than emit an oversized frame.
|
||||||
uint32 max_frame_bytes = 4;
|
uint32 max_frame_bytes = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,15 +88,23 @@ scripts assert the pin and resolve tools from `PATH`:
|
|||||||
| Generator | Pinned version | Guard |
|
| Generator | Pinned version | Guard |
|
||||||
|-----------|----------------|-------|
|
|-----------|----------------|-------|
|
||||||
| protoc (descriptor set) | 34.1 | version assertion in `scripts/publish-client-proto-inputs.ps1` |
|
| protoc (descriptor set) | 34.1 | version assertion in `scripts/publish-client-proto-inputs.ps1` |
|
||||||
| `Grpc.Tools` (C# `Generated/`) | 2.80.0 (contracts csproj) | `scripts/check-codegen.ps1` git-diff of `Generated/` |
|
| `Grpc.Tools` (C# `Generated/`) | 2.80.0 (contracts csproj) | `scripts/check-codegen.ps1` git-diff of `Generated/` (Check 2) |
|
||||||
| `grpcio-tools` (Python) | 1.80.0 (protobuf runtime 6.31.1) | version assertion in `clients/python/generate-proto.ps1` |
|
| `protoc-gen-go` (Go) | v1.36.11 | version assertion in `clients/go/generate-proto.ps1`; `check-codegen.ps1` Check 4 |
|
||||||
| protobuf / grpc-java (Java) | `protobufVersion` / `grpcVersion` in `clients/java/build.gradle` | `checkGeneratedClean` gradle task |
|
| `protoc-gen-go-grpc` (Go) | 1.6.2 | version assertion in `clients/go/generate-proto.ps1`; `check-codegen.ps1` Check 4 |
|
||||||
|
| `grpcio-tools` (Python) | 1.80.0 (protobuf runtime 6.31.1) | version assertion in `clients/python/generate-proto.ps1`; `check-codegen.ps1` Check 4 |
|
||||||
|
| protobuf / grpc-java (Java) | `protobufVersion` / `grpcVersion` in `clients/java/build.gradle` | CI `git diff --exit-code` over `clients/java/src/main/generated` after `gradle test` (the `checkGeneratedClean` gradle task is the equivalent local check) |
|
||||||
|
|
||||||
A newer `grpcio-tools` stamps a `GRPC_GENERATED_VERSION` above the pinned grpcio
|
A newer `grpcio-tools` stamps a `GRPC_GENERATED_VERSION` above the pinned grpcio
|
||||||
runtime and breaks Python `pytest`; the Java protobuf plugin rewrites
|
runtime and breaks Python `pytest`, so the Python and Go scripts assert their
|
||||||
`MxaccessGateway.java` with spurious protobuf-runtime-version churn on every build
|
generator pins before regenerating. Under the pinned grpc/protobuf toolchain the
|
||||||
(revert that one file when no `.proto` changed — see
|
Java protobuf plugin regenerates byte-identical output (modulo real `.proto`
|
||||||
[Gateway Testing](./GatewayTesting.md) "Continuous Integration").
|
changes), so CI enforces Java freshness with a direct `git diff --exit-code -- clients/java/src/main/generated`
|
||||||
|
step after `gradle test` (which transitively regenerates via `generateProto`); the
|
||||||
|
`checkGeneratedClean` gradle task is the equivalent check for local/manual use. The
|
||||||
|
old unconditional churn-revert CI step (which masked message-level drift in the
|
||||||
|
single-file Java aggregates) was deleted (IPC-24). Go and Python committed
|
||||||
|
bindings are guarded by `check-codegen.ps1` **Check 4**, which regenerates both
|
||||||
|
and fails on any diff.
|
||||||
|
|
||||||
## Output Directories
|
## Output Directories
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -114,7 +114,11 @@ dotnet build src/ZB.MOM.WW.MxGateway.Contracts/ZB.MOM.WW.MxGateway.Contracts.csp
|
|||||||
`scripts/check-codegen.ps1` enforces this in CI (it force-regenerates and fails on any
|
`scripts/check-codegen.ps1` enforces this in CI (it force-regenerates and fails on any
|
||||||
`git diff` against the committed `Generated/`) — that regeneration diff in the `portable`
|
`git diff` against the committed `Generated/`) — that regeneration diff in the `portable`
|
||||||
job is the primary guard. The SSH-driven `windows-x86` job's net48 worker build is the
|
job is the primary guard. The SSH-driven `windows-x86` job's net48 worker build is the
|
||||||
secondary guard (a stale `Generated/` also breaks the x86 build with `CS0246`).
|
secondary guard (a stale `Generated/` also breaks the x86 build with `CS0246`). The same
|
||||||
|
script runs four checks in total: the committed client descriptor set (Check 1), the C#
|
||||||
|
`Generated/` (Check 2), the Rust vendored protos (Check 3), and the Go/Python client bindings
|
||||||
|
(Check 4) each regenerate and fail on any diff. See
|
||||||
|
[Client Proto Generation](./ClientProtoGeneration.md) for the pinned generator versions.
|
||||||
|
|
||||||
Client generation inputs are published through
|
Client generation inputs are published through
|
||||||
`clients/proto/proto-inputs.json` and the descriptor set under
|
`clients/proto/proto-inputs.json` and the descriptor set under
|
||||||
|
|||||||
+15
-8
@@ -428,10 +428,13 @@ runtime because the x86 Worker cannot build on Linux:
|
|||||||
gateway fake-worker tests, and builds/tests the clients that run on Linux: .NET client
|
gateway fake-worker tests, and builds/tests the clients that run on Linux: .NET client
|
||||||
build, Go (`gofmt` + `go build` + `go test`), Rust (`cargo fmt --check` + `cargo test`
|
build, Go (`gofmt` + `go build` + `go test`), Rust (`cargo fmt --check` + `cargo test`
|
||||||
+ `cargo clippy -D warnings`), and Python (`pytest`).
|
+ `cargo clippy -D warnings`), and Python (`pytest`).
|
||||||
- **`java`** (Linux, JDK 17) — `gradle test`. The protobuf gradle plugin rewrites
|
- **`java`** (Linux, JDK 17) — `gradle test`, then `git diff --exit-code` over the generated
|
||||||
`MxaccessGateway.java` with spurious protobuf-runtime-version churn on every build, so
|
tree. The grpc/protobuf toolchain is pinned (`clients/java/build.gradle`), so a regeneration
|
||||||
when no `.proto` changed the job reverts that one file (`git checkout`) before asserting
|
is byte-identical to the committed single-file aggregates modulo real `.proto` changes; the
|
||||||
the generated tree is clean. The dev Mac has no JRE, so Java verification is CI-only.
|
git-diff is therefore a true drift gate that now catches message-level proto drift in the Java
|
||||||
|
client (IPC-24 deleted the old unconditional churn-revert step, which masked exactly that
|
||||||
|
class). The dev Mac has a Homebrew JDK 17, so `gradle generateProto` can be run there to refresh
|
||||||
|
the Java aggregates when a `.proto` changes.
|
||||||
- **`windows-x86`** (Linux runner, per push/PR) — builds the **x86 / net48 Worker and
|
- **`windows-x86`** (Linux runner, per push/PR) — builds the **x86 / net48 Worker and
|
||||||
Worker.Tests**, which are Windows-only and out of scope for the Linux jobs. It runs on a
|
Worker.Tests**, which are Windows-only and out of scope for the Linux jobs. It runs on a
|
||||||
Linux runner that always schedules and SSHes to windev (`10.100.0.48`), where
|
Linux runner that always schedules and SSHes to windev (`10.100.0.48`), where
|
||||||
@@ -449,10 +452,14 @@ runtime because the x86 Worker cannot build on Linux:
|
|||||||
`xUnit1030`). Gated `if: github.event_name == 'schedule'`, so it never gates a push. On
|
`xUnit1030`). Gated `if: github.event_name == 'schedule'`, so it never gates a push. On
|
||||||
failure it opens a Gitea issue via the Actions token, since nobody watches the Actions page.
|
failure it opens a Gitea issue via the Actions token, since nobody watches the Actions page.
|
||||||
|
|
||||||
The freshness guard `scripts/check-codegen.ps1` fails the build when the committed
|
The freshness guard `scripts/check-codegen.ps1` runs four checks and fails the build when the
|
||||||
client descriptor set or the C# `Generated/` no longer matches the current `.proto`
|
committed client descriptor set (Check 1), the C# `Generated/` (Check 2), the Rust vendored
|
||||||
sources — the codegen drift class this repo has hit repeatedly (stale client
|
protos (Check 3), or the Go/Python client bindings (Check 4, IPC-25) no longer match the current
|
||||||
descriptors, net48 `CS0246` on unregenerated protos). The **primary** guard for the
|
`.proto` sources — the codegen drift class this repo has hit repeatedly (stale client
|
||||||
|
descriptors, net48 `CS0246` on unregenerated protos, silently stale Go/Python worker bindings).
|
||||||
|
Check 4 regenerates the Go and Python bindings with their pinned generators (`protoc-gen-go`
|
||||||
|
v1.36.11 / `protoc-gen-go-grpc` 1.6.2, `grpcio-tools` 1.80.0) and fails on any diff; a missing
|
||||||
|
generator fails the check rather than skipping it. The **primary** guard for the
|
||||||
"regenerate and commit `Generated/`" rule is that regeneration diff in the `portable` job;
|
"regenerate and commit `Generated/`" rule is that regeneration diff in the `portable` job;
|
||||||
the `windows-x86` net48 compile is the **secondary** guard (a stale `Generated/` also breaks
|
the `windows-x86` net48 compile is the **secondary** guard (a stale `Generated/` also breaks
|
||||||
the x86 build with `CS0246`). See [Client Proto Generation](./ClientProtoGeneration.md) and
|
the x86 build with `CS0246`). See [Client Proto Generation](./ClientProtoGeneration.md) and
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env pwsh
|
#!/usr/bin/env pwsh
|
||||||
# Codegen freshness guard for CI (IPC-01, IPC-19, IPC-20, CLI-02).
|
# Codegen freshness guard for CI (IPC-01, IPC-19, IPC-20, IPC-25, CLI-02).
|
||||||
#
|
#
|
||||||
# Three checks, all Linux/macOS-runnable (no Server build, no x86 worker):
|
# Four checks, all Linux/macOS-runnable (no Server build, no x86 worker):
|
||||||
# 1. Published client descriptor set matches the current .proto sources (delegates to
|
# 1. Published client descriptor set matches the current .proto sources (delegates to
|
||||||
# publish-client-proto-inputs.ps1 -Check, which normalizes source_code_info so it is
|
# publish-client-proto-inputs.ps1 -Check, which normalizes source_code_info so it is
|
||||||
# protoc-version tolerant).
|
# protoc-version tolerant).
|
||||||
@@ -13,6 +13,12 @@
|
|||||||
# crate buildable outside the repo, CLI-02) are byte-identical to the canonical Contracts
|
# crate buildable outside the repo, CLI-02) are byte-identical to the canonical Contracts
|
||||||
# protos. A drift means a .proto was edited without refreshing the vendored copies, which would
|
# protos. A drift means a .proto was edited without refreshing the vendored copies, which would
|
||||||
# publish a stale wire contract to crate consumers while the in-repo build stays correct.
|
# publish a stale wire contract to crate consumers while the in-repo build stays correct.
|
||||||
|
# 4. The committed Go and Python client bindings match a fresh regeneration (IPC-25). The two
|
||||||
|
# per-client generate-proto.ps1 scripts pin their generators (protoc-gen-go v1.36.11 /
|
||||||
|
# protoc-gen-go-grpc v1.6.2 for Go; grpcio-tools 1.80.0 for Python), so a clean checkout
|
||||||
|
# regenerates deterministic output; a non-empty git diff means a .proto was edited without
|
||||||
|
# regenerating and committing those bindings. A missing generator FAILS the check (a skipped
|
||||||
|
# guard is the exact silent-drift hole IPC-25 closes), never skips it.
|
||||||
#
|
#
|
||||||
# The x86 Worker + Worker.Tests are Windows-only and are guarded by the SSH-driven `windows-x86`
|
# The x86 Worker + Worker.Tests are Windows-only and are guarded by the SSH-driven `windows-x86`
|
||||||
# CI job (see docs/GatewayTesting.md, Continuous Integration), not here.
|
# CI job (see docs/GatewayTesting.md, Continuous Integration), not here.
|
||||||
@@ -28,7 +34,7 @@ $generatedDir = Join-Path $repoRoot 'src/ZB.MOM.WW.MxGateway.Contracts/Generated
|
|||||||
$contractsProject = Join-Path $repoRoot 'src/ZB.MOM.WW.MxGateway.Contracts/ZB.MOM.WW.MxGateway.Contracts.csproj'
|
$contractsProject = Join-Path $repoRoot 'src/ZB.MOM.WW.MxGateway.Contracts/ZB.MOM.WW.MxGateway.Contracts.csproj'
|
||||||
$failures = New-Object System.Collections.Generic.List[string]
|
$failures = New-Object System.Collections.Generic.List[string]
|
||||||
|
|
||||||
Write-Host '== Check 1/2: client descriptor set freshness =='
|
Write-Host '== Check 1/4: client descriptor set freshness =='
|
||||||
try {
|
try {
|
||||||
& (Join-Path $PSScriptRoot 'publish-client-proto-inputs.ps1') -Check
|
& (Join-Path $PSScriptRoot 'publish-client-proto-inputs.ps1') -Check
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
@@ -40,7 +46,7 @@ catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Write-Host ''
|
Write-Host ''
|
||||||
Write-Host '== Check 2/2: Contracts/Generated matches a fresh regeneration =='
|
Write-Host '== Check 2/4: Contracts/Generated matches a fresh regeneration =='
|
||||||
try {
|
try {
|
||||||
# Force a full regeneration: Grpc.Tools skips regen when the committed .cs look up to date, so
|
# Force a full regeneration: Grpc.Tools skips regen when the committed .cs look up to date, so
|
||||||
# remove them first (the documented "del Generated/*.cs to force regen" trick).
|
# remove them first (the documented "del Generated/*.cs to force regen" trick).
|
||||||
@@ -66,7 +72,7 @@ catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Write-Host ''
|
Write-Host ''
|
||||||
Write-Host '== Check 3/3: Rust vendored protos match canonical Contracts protos =='
|
Write-Host '== Check 3/4: Rust vendored protos match canonical Contracts protos =='
|
||||||
try {
|
try {
|
||||||
$canonicalProtoDir = Join-Path $repoRoot 'src/ZB.MOM.WW.MxGateway.Contracts/Protos'
|
$canonicalProtoDir = Join-Path $repoRoot 'src/ZB.MOM.WW.MxGateway.Contracts/Protos'
|
||||||
$vendoredProtoDir = Join-Path $repoRoot 'clients/rust/protos'
|
$vendoredProtoDir = Join-Path $repoRoot 'clients/rust/protos'
|
||||||
@@ -87,6 +93,28 @@ catch {
|
|||||||
$failures.Add("Rust vendored proto check failed: $($_.Exception.Message)")
|
$failures.Add("Rust vendored proto check failed: $($_.Exception.Message)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Write-Host ''
|
||||||
|
Write-Host '== Check 4/4: Go and Python client bindings match a fresh regeneration =='
|
||||||
|
try {
|
||||||
|
# Regenerate both binding sets with their pinned generators, then diff. The per-client scripts
|
||||||
|
# throw on a missing or off-pin generator, so any failure here FAILS the check rather than
|
||||||
|
# skipping it (a skipped guard is exactly the silent-drift hole IPC-25 closes).
|
||||||
|
$goBindingDir = 'clients/go/internal/generated'
|
||||||
|
$pyBindingDir = 'clients/python/src/zb_mom_ww_mxgateway/generated'
|
||||||
|
|
||||||
|
& (Join-Path $repoRoot 'clients/go/generate-proto.ps1') | Out-Host
|
||||||
|
& (Join-Path $repoRoot 'clients/python/generate-proto.ps1') | Out-Host
|
||||||
|
|
||||||
|
$bindingDiff = (& git -C $repoRoot status --porcelain -- $goBindingDir $pyBindingDir | Out-String).Trim()
|
||||||
|
if (-not [string]::IsNullOrEmpty($bindingDiff)) {
|
||||||
|
Write-Host $bindingDiff
|
||||||
|
$failures.Add("Go/Python client bindings differ from a fresh regeneration. Run clients/go/generate-proto.ps1 and clients/python/generate-proto.ps1 with the pinned generators and commit $goBindingDir and $pyBindingDir.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
$failures.Add("Go/Python codegen check failed (tool missing or regeneration error): $($_.Exception.Message)")
|
||||||
|
}
|
||||||
|
|
||||||
Write-Host ''
|
Write-Host ''
|
||||||
if ($failures.Count -gt 0) {
|
if ($failures.Count -gt 0) {
|
||||||
Write-Host 'Codegen freshness check FAILED:' -ForegroundColor Red
|
Write-Host 'Codegen freshness check FAILED:' -ForegroundColor Red
|
||||||
|
|||||||
@@ -22796,6 +22796,12 @@ namespace ZB.MOM.WW.MxGateway.Contracts.Proto {
|
|||||||
private static readonly pb::FieldCodec<global::ZB.MOM.WW.MxGateway.Contracts.Proto.MxEvent> _repeated_events_codec
|
private static readonly pb::FieldCodec<global::ZB.MOM.WW.MxGateway.Contracts.Proto.MxEvent> _repeated_events_codec
|
||||||
= pb::FieldCodec.ForMessage(10, global::ZB.MOM.WW.MxGateway.Contracts.Proto.MxEvent.Parser);
|
= pb::FieldCodec.ForMessage(10, global::ZB.MOM.WW.MxGateway.Contracts.Proto.MxEvent.Parser);
|
||||||
private readonly pbc::RepeatedField<global::ZB.MOM.WW.MxGateway.Contracts.Proto.MxEvent> events_ = new pbc::RepeatedField<global::ZB.MOM.WW.MxGateway.Contracts.Proto.MxEvent>();
|
private readonly pbc::RepeatedField<global::ZB.MOM.WW.MxGateway.Contracts.Proto.MxEvent> events_ = new pbc::RepeatedField<global::ZB.MOM.WW.MxGateway.Contracts.Proto.MxEvent>();
|
||||||
|
/// <summary>
|
||||||
|
/// The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
/// worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
/// `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
/// empty reply.
|
||||||
|
/// </summary>
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||||
public pbc::RepeatedField<global::ZB.MOM.WW.MxGateway.Contracts.Proto.MxEvent> Events {
|
public pbc::RepeatedField<global::ZB.MOM.WW.MxGateway.Contracts.Proto.MxEvent> Events {
|
||||||
@@ -24510,6 +24516,11 @@ namespace ZB.MOM.WW.MxGateway.Contracts.Proto {
|
|||||||
/// after_worker_sequence = oldest_available_sequence - 1 in the next
|
/// after_worker_sequence = oldest_available_sequence - 1 in the next
|
||||||
/// StreamEventsRequest, which will cause the server to replay starting at
|
/// StreamEventsRequest, which will cause the server to replay starting at
|
||||||
/// oldest_available_sequence (the first retained event).
|
/// oldest_available_sequence (the first retained event).
|
||||||
|
/// When nothing is retained (the replay ring is empty), this is the next sequence
|
||||||
|
/// that can be delivered — `highest observed + 1` — and the `oldest - 1` resume
|
||||||
|
/// formula remains valid: it resolves to the highest sequence already seen, so the
|
||||||
|
/// follow-up resume replays nothing, reports no gap, and every newer live event
|
||||||
|
/// passes. The interval evicted is unchanged.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||||
|
|||||||
@@ -1164,6 +1164,9 @@ namespace ZB.MOM.WW.MxGateway.Contracts.Proto {
|
|||||||
/// instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
/// instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
||||||
/// "use the worker's built-in default". Sits above the public gRPC cap by an
|
/// "use the worker's built-in default". Sits above the public gRPC cap by an
|
||||||
/// envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
/// envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
||||||
|
/// Every worker->gateway frame — events, heartbeats, faults, and control replies
|
||||||
|
/// including DrainEvents — must serialize within this limit; reply builders truncate
|
||||||
|
/// to fit rather than emit an oversized frame.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||||
|
|||||||
@@ -676,6 +676,10 @@ message WorkerInfoReply {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message DrainEventsReply {
|
message DrainEventsReply {
|
||||||
|
// The reply is bounded by both a server-side count cap and the negotiated
|
||||||
|
// worker-frame byte cap; a reply may therefore carry fewer events than
|
||||||
|
// `max_events` and fewer than are queued. Callers drain iteratively until an
|
||||||
|
// empty reply.
|
||||||
repeated MxEvent events = 1;
|
repeated MxEvent events = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -760,6 +764,11 @@ message ReplayGap {
|
|||||||
// after_worker_sequence = oldest_available_sequence - 1 in the next
|
// after_worker_sequence = oldest_available_sequence - 1 in the next
|
||||||
// StreamEventsRequest, which will cause the server to replay starting at
|
// StreamEventsRequest, which will cause the server to replay starting at
|
||||||
// oldest_available_sequence (the first retained event).
|
// oldest_available_sequence (the first retained event).
|
||||||
|
// When nothing is retained (the replay ring is empty), this is the next sequence
|
||||||
|
// that can be delivered — `highest observed + 1` — and the `oldest - 1` resume
|
||||||
|
// formula remains valid: it resolves to the highest sequence already seen, so the
|
||||||
|
// follow-up resume replays nothing, reports no gap, and every newer live event
|
||||||
|
// passes. The interval evicted is unchanged.
|
||||||
uint64 oldest_available_sequence = 2;
|
uint64 oldest_available_sequence = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ message GatewayHello {
|
|||||||
// instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
// instead of a hard-coded default; 0 (an older gateway that never set the field) means
|
||||||
// "use the worker's built-in default". Sits above the public gRPC cap by an
|
// "use the worker's built-in default". Sits above the public gRPC cap by an
|
||||||
// envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
// envelope-overhead margin so an accepted gRPC payload always fits one worker frame.
|
||||||
|
// Every worker->gateway frame — events, heartbeats, faults, and control replies
|
||||||
|
// including DrainEvents — must serialize within this limit; reply builders truncate
|
||||||
|
// to fit rather than emit an oversized frame.
|
||||||
uint32 max_frame_bytes = 4;
|
uint32 max_frame_bytes = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user