fix(sitecallaudit): push StuckOnly filter into SQL; doc accuracy fixes
This commit is contained in:
@@ -21,10 +21,9 @@ namespace ScadaLink.SiteCallAudit;
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// M3 ships the minimum surface: ingest only. Reconciliation, KPIs, and
|
||||
/// central→site Retry/Discard relay are deferred (per CLAUDE.md scope
|
||||
/// discipline — Site Call Audit's KPIs and the Retry/Discard relay land in a
|
||||
/// follow-up).
|
||||
/// Query, detail and KPIs land in Task 4; reconciliation and the central→site
|
||||
/// Retry/Discard relay remain deferred (per CLAUDE.md scope discipline — they
|
||||
/// land in a later follow-up).
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Per CLAUDE.md "audit-write failure NEVER aborts the user-facing action" —
|
||||
@@ -195,13 +194,20 @@ public class SiteCallAuditActor : ReceiveActor
|
||||
|
||||
private async Task<SiteCallQueryResponse> QueryAsync(SiteCallQueryRequest request, DateTime now)
|
||||
{
|
||||
var stuckCutoff = now - _options.StuckAgeThreshold;
|
||||
|
||||
var filter = new SiteCallQueryFilter(
|
||||
Channel: NullIfBlank(request.ChannelFilter),
|
||||
SourceSite: NullIfBlank(request.SourceSiteFilter),
|
||||
Status: NullIfBlank(request.StatusFilter),
|
||||
Target: NullIfBlank(request.TargetKeyword),
|
||||
FromUtc: request.FromUtc,
|
||||
ToUtc: request.ToUtc);
|
||||
ToUtc: request.ToUtc,
|
||||
// StuckOnly is pushed into the repository SQL via StuckCutoffUtc —
|
||||
// TerminalAtUtc IS NULL AND CreatedAtUtc < cutoff composes with the
|
||||
// keyset cursor, so the page is always honest (full pages, no empty
|
||||
// pages with a non-null next cursor).
|
||||
StuckCutoffUtc: request.StuckOnly ? stuckCutoff : null);
|
||||
|
||||
var pageSize = Math.Clamp(request.PageSize, 1, MaxPageSize);
|
||||
var paging = new SiteCallPaging(
|
||||
@@ -214,21 +220,11 @@ public class SiteCallAuditActor : ReceiveActor
|
||||
{
|
||||
var rows = await repository.QueryAsync(filter, paging).ConfigureAwait(false);
|
||||
|
||||
var stuckCutoff = now - _options.StuckAgeThreshold;
|
||||
var summaries = rows
|
||||
// StuckOnly is post-filtered here rather than pushed into the
|
||||
// repository SQL — the SiteCallQueryFilter has no stuck predicate
|
||||
// and a status-aware created-before clause does not compose with
|
||||
// the keyset cursor. The page may therefore return fewer than
|
||||
// PageSize rows when StuckOnly is set; that is acceptable for a
|
||||
// display-only filter.
|
||||
.Where(row => !request.StuckOnly || IsStuck(row, stuckCutoff))
|
||||
.Select(row => ToSummary(row, stuckCutoff))
|
||||
.ToList();
|
||||
|
||||
// The next-page cursor is the LAST row of the materialised page —
|
||||
// before StuckOnly post-filtering, so paging still advances even
|
||||
// when every row on a page was filtered out.
|
||||
// The next-page cursor is the last row of the materialised page.
|
||||
var cursorRow = rows.Count > 0 ? rows[^1] : null;
|
||||
|
||||
return new SiteCallQueryResponse(
|
||||
|
||||
Reference in New Issue
Block a user