fix(historian): #691.3 strict-ceiling gateway: re-ask once at the named ceiling, never answer a truncated read

This commit is contained in:
Joseph Doherty
2026-10-12 16:13:14 -04:00
parent 39552e15b9
commit dbffb6bdb4
7 changed files with 391 additions and 56 deletions
@@ -102,10 +102,30 @@ public sealed class FakeHistorianGatewayClient : IHistorianGatewayClient
LastReadRawMaxValues = maxValues;
ReadRawCallCount++;
RawCalls.Add((startUtc, endUtc, maxValues));
if (MaxValuesCeiling is { } ceiling && maxValues > ceiling)
{
// The real gateway's refusal (HistorianReadService.ReadRaw), raised on the first MoveNext before any row, as
// the client package surfaces it: a HistorianGatewayException wrapping the RpcException.
var rpc = new Grpc.Core.RpcException(new Grpc.Core.Status(Grpc.Core.StatusCode.InvalidArgument,
CeilingRejectionDetail ?? $"max_values exceeds the server ceiling of {ceiling}; read large ranges by time-slicing " +
"(split the range and read the slices sequentially), or enable " +
"Historian:ReadLimits:AllowStreamingBeyondCeiling to page through server-side."));
return ToAsyncStream(Array.Empty<HistorianSample>(),
new ZB.MOM.WW.HistorianGateway.Client.HistorianGatewayException(rpc.Status.Detail, rpc), ct);
}
var items = RawSource is null ? RawSamples : RawSource(startUtc, endUtc, maxValues).ToList();
return CountingStream(ToAsyncStream(items, ThrowOnRead, ct));
}
/// <summary>
/// A strict gateway (<c>Historian:ReadLimits:AllowStreamingBeyondCeiling=false</c>) with this
/// <c>MaxValuesCeiling</c>: a ReadRaw asking for more is refused <c>InvalidArgument</c> (#691.3).
/// </summary>
public int? MaxValuesCeiling;
/// <summary>Overrides the refusal's detail text (an older/other gateway wording).</summary>
public string? CeilingRejectionDetail;
public IAsyncEnumerable<HistorianAggregateSample> ReadAggregateAsync(
string tag,
DateTime startUtc,