feat(ipc): negotiate worker frame max, add gRPC headroom, bound DrainEvents (IPC-02/03/04 gateway half)
Proto foundation + gateway-side of the size/backpressure pass: - IPC-02: add GatewayHello.max_frame_bytes (regen Generated/); gateway sends its negotiated worker-frame max in the handshake so the worker can adopt it instead of a hard-coded default. Worker read-half lands separately. - IPC-03: give the pipe frame max envelope-overhead headroom above the public gRPC cap (WorkerFrameProtocolOptions.EnvelopeOverheadReserveBytes = 64 KiB; default Worker.MaxMessageBytes bumped to 16 MiB + reserve), cross-validate the headroom at startup, and pre-check command envelope size in WorkerClient so an oversized command fails only that correlation (ResourceExhausted) instead of faulting the whole session. - IPC-04: reject DrainEvents max_events above a public ceiling in the request validator (worker per-reply cap lands with the worker half). Docs: GatewayConfiguration, WorkerFrameProtocol, gateway.md. Tests: headroom validation, DrainEvents bound, oversized-command per-command failure (pipe-harness, verified on windev).
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
using Grpc.Core;
|
||||
using ZB.MOM.WW.MxGateway.Contracts.Proto;
|
||||
using ZB.MOM.WW.MxGateway.Server.Grpc;
|
||||
|
||||
namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Grpc;
|
||||
|
||||
public sealed class MxAccessGrpcRequestValidatorTests
|
||||
{
|
||||
private static MxCommandRequest DrainRequest(uint maxEvents) => new()
|
||||
{
|
||||
SessionId = "session-1",
|
||||
Command = new MxCommand
|
||||
{
|
||||
Kind = MxCommandKind.DrainEvents,
|
||||
DrainEvents = new DrainEventsCommand { MaxEvents = maxEvents },
|
||||
},
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Verifies a DrainEvents request within the per-request ceiling passes validation, including the
|
||||
/// <c>max_events = 0</c> "worker default cap" sentinel (IPC-04).
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[InlineData(0u)]
|
||||
[InlineData(1u)]
|
||||
[InlineData(10_000u)]
|
||||
public void ValidateInvoke_AllowsDrainEvents_WithinCeiling(uint maxEvents)
|
||||
{
|
||||
MxAccessGrpcRequestValidator validator = new();
|
||||
validator.ValidateInvoke(DrainRequest(maxEvents));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies a DrainEvents request above the per-request ceiling is rejected with InvalidArgument
|
||||
/// so one accepted request cannot pack an unbounded reply frame (IPC-04).
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ValidateInvoke_RejectsDrainEvents_AboveCeiling()
|
||||
{
|
||||
MxAccessGrpcRequestValidator validator = new();
|
||||
RpcException exception = Assert.Throws<RpcException>(() => validator.ValidateInvoke(DrainRequest(10_001)));
|
||||
Assert.Equal(StatusCode.InvalidArgument, exception.StatusCode);
|
||||
Assert.Contains("max_events", exception.Status.Detail, StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user