fix(historian): #691.3 review — remember a strict gateway's ceiling per data source; re-probe once when a bounded read comes back full

This commit is contained in:
Joseph Doherty
2026-10-12 16:50:32 -04:00
parent ab5030174a
commit 7b86059daf
7 changed files with 190 additions and 38 deletions
@@ -47,6 +47,9 @@ public sealed class GatewayHistorianDataSource : IHistorianDataSource, IAsyncDis
private readonly int _maxRawRows;
private readonly TimeProvider _time;
/// <summary>A strict gateway's row ceiling, learned from its first refusal (#691.3).</summary>
private readonly GatewayRowCeiling _ceiling = new();
private readonly object _healthLock = new();
private DateTime? _lastSuccessUtc;
private DateTime? _lastFailureUtc;
@@ -204,8 +207,9 @@ public sealed class GatewayHistorianDataSource : IHistorianDataSource, IAsyncDis
// One drained pass; a strict gateway's refusal of the budget is retried once at the ceiling it names (#691.3).
Task<((List<HistorianSample> Samples, int PreWindowRows, bool Complete) Result, int Budget)> PassAsync(int budget) =>
GatewayReadLimits.ReadWithCeilingRetryAsync(budget,
b => ReadRawPassAsync(fullReference, startUtc, endUtc, cap, b, cancellationToken));
_ceiling.ReadAsync(budget,
b => ReadRawPassAsync(fullReference, startUtc, endUtc, cap, b, cancellationToken),
(r, _) => !r.Complete);
}
/// <summary>One forward raw read of a window, drained, with its pre-window row count and whether it is complete.</summary>
@@ -349,7 +353,7 @@ public sealed class GatewayHistorianDataSource : IHistorianDataSource, IAsyncDis
{
var now = _time.GetUtcNow().UtcDateTime;
var values = await RawAggregateReader
.ReadAsync(_client, fullReference, aggregate, plan, _maxRawRows, now, cancellationToken)
.ReadAsync(_client, _ceiling, fullReference, aggregate, plan, _maxRawRows, now, cancellationToken)
.ConfigureAwait(false);
RecordOutcome(success: true, error: null);
return new HistoryReadResult(values, ContinuationPoint: null);