fix(historian): #691.5 a reverse walk proves the rest empty once and carries it page to page
The last pages of a deep reverse page-through on a forward-only backend each walked down to 1970 one x4 growth step at a time (~14-16 reads, ~2.5 s live). After two empty segments the walk now asks once per page for the whole remainder at the page budget (a truncated answer is discarded and the walk carries on), and the stretch the page's last complete read proved empty rides the continuation point (HistoryContinuationState.EmptyFromTicks/EmptyToTicks, session-held, so no versioning) so the next page steps over it. Fuzz now pages with the walk's own hints and with true random empty stretches.
This commit is contained in:
@@ -739,6 +739,38 @@ public sealed class NodeManagerHistoryReadPagingTests : IDisposable
|
||||
await host.DisposeAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// #691: the last pages of a deep reverse page-through no longer each walk down to 1970 (live: ~14–16 reads, ~2.5 s
|
||||
/// per page). The stretch a page proved empty below its oldest row rides the continuation point, and a page that runs
|
||||
/// out of rows asks once for the whole remainder — so every page here is a couple of reads.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Raw_reverse_page_through_on_a_forward_only_backend_does_not_rewalk_to_the_epoch_on_each_last_page()
|
||||
{
|
||||
var source = new ForwardOnlyHistorianDataSource(MakeSeries(count: 25, stepSeconds: 1));
|
||||
var (host, nm, nodeId) = await BootForwardOnlyAsync(source, "FwdDeep691");
|
||||
nm.Clock = new FixedClock(Epoch.AddHours(1));
|
||||
|
||||
var collected = new List<double>();
|
||||
byte[]? cp = null;
|
||||
var page = 0;
|
||||
do
|
||||
{
|
||||
source.ResetCounts();
|
||||
var (values, error, next) = ReadRaw(nm, nodeId, DateTime.MinValue, Epoch.AddHours(1), max: 10, inboundCp: cp);
|
||||
error.StatusCode.Code.ShouldBe(StatusCodes.Good);
|
||||
collected.AddRange(values);
|
||||
cp = next;
|
||||
page++;
|
||||
source.ReadCount.ShouldBeLessThanOrEqualTo(page == 1 ? 4 : 1, $"page {page}");
|
||||
}
|
||||
while (cp is not null && page < 10);
|
||||
|
||||
collected.ShouldBe(Enumerable.Range(0, 25).Reverse().Select(i => (double)i));
|
||||
source.MinRequestedStart.ShouldBeGreaterThanOrEqualTo(DateTime.UnixEpoch);
|
||||
await host.DisposeAsync();
|
||||
}
|
||||
|
||||
/// <summary>#686 review: a reverse read from <c>StartTime = DateTime.MaxValue</c> walks back from now + 1 day, not from
|
||||
/// year 9999.</summary>
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user