fix(auditlog)+fix(configdb): budget the ingest fallback loop; index + varchar-type the SiteCalls list query (arch-review 2026-08-19 P5-1 + P5-2)
P5-1: AuditLogIngestActor.OnCachedTelemetryAsync's per-entry fallback loop (used when the cached-telemetry batch fast path fails) ran with no budget/cancellation, unlike OnIngestAsync's fallback. A slow/wedged DB could freeze the central ingest singleton's mailbox for minutes. The loop now runs under its own fresh IngestFallbackBudget CancellationTokenSource (mirroring OnIngestAsync), passes the token into BeginTransactionAsync/ InsertIfNotExistsAsync/UpsertAsync, and stops early on budget exhaustion, logging how many entries were left for the periodic reconciliation pull to pick up. P5-2: SiteCallAuditRepository.QueryAsync ordered by (CreatedAtUtc DESC, TrackedOperationId DESC) with no index leading unconditionally on CreatedAtUtc, forcing a full scan+sort on an unfiltered page. Added IX_SiteCalls_Created_TrackedOperationId (migration AddSiteCallsListSortIndex + matching hand-written production-parity script under docs/plans/sql/). Also switched the query from FromSqlInterpolated (which binds string filters as nvarchar(4000)) to FromSqlRaw with explicitly SqlDbType.VarChar-typed parameters, matching the SiteCalls columns' IsUnicode(false) declaration and the write path's existing Param(...) pattern, so seeks — including the keyset predicate — are no longer blocked by an implicit conversion. Tests: new AuditLogIngestActorCombinedTelemetryTests case proves the fallback budget bounds the wait (hanging repo stub, ~5s not indefinite), that remaining entries are skipped, and that a non-default/cancellable token reaches the repository call; verified fail-unfixed by reverting the actor change (test times out at its 20s bound). Existing SiteCallAuditRepositoryTests QueryAsync/keyset/stuck-cutoff cases (real MSSQL) confirm the raw-SQL rewrite still returns correct pages.
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
-- arch-review 2026-08-19 P5-2 (register row-35 class): the SiteCalls list page's
|
||||
-- sort key gets its own index.
|
||||
--
|
||||
-- SiteCallAuditRepository.QueryAsync orders (CreatedAtUtc DESC, TrackedOperationId
|
||||
-- DESC), and its keyset predicate is exactly that pair. None of the existing
|
||||
-- SiteCalls indexes lead unconditionally on CreatedAtUtc:
|
||||
-- - IX_SiteCalls_Source_Created requires an equality on SourceSite first.
|
||||
-- - IX_SiteCalls_NonTerminal / IX_SiteCalls_Terminal are each filtered to one
|
||||
-- side of TerminalAtUtc.
|
||||
-- So an unfiltered (or lightly filtered) page fell back to a full clustered-index
|
||||
-- scan + sort. IX_SiteCalls_Created_TrackedOperationId (CreatedAtUtc DESC,
|
||||
-- TrackedOperationId DESC) makes a forward scan of the index deliver rows in the
|
||||
-- requested order directly, so a keyset page reads a Top-N off the index instead
|
||||
-- of sorting the whole table on every page request.
|
||||
--
|
||||
-- SiteCalls is small enough today that a plain (offline) index build is fine. On
|
||||
-- an Enterprise edition instance where the table has grown large and the Central
|
||||
-- UI must stay responsive, add WITH (ONLINE = ON) to the CREATE INDEX below.
|
||||
--
|
||||
-- Run with QUOTED_IDENTIFIER ON. Several tables in this database carry filtered
|
||||
-- indexes and persisted computed columns, and SQL Server refuses DDL/DML against
|
||||
-- them with error 1934 when the session has QUOTED_IDENTIFIER OFF -- which is
|
||||
-- exactly what `sqlcmd` gives you by default (pass -I, or keep this header). The
|
||||
-- SETs sit in their own batch so they are in force when the statements after the
|
||||
-- GO parse.
|
||||
SET QUOTED_IDENTIFIER ON;
|
||||
SET ANSI_NULLS ON;
|
||||
GO
|
||||
|
||||
BEGIN TRANSACTION;
|
||||
IF NOT EXISTS (
|
||||
SELECT * FROM [__EFMigrationsHistory]
|
||||
WHERE [MigrationId] = N'20260819183326_AddSiteCallsListSortIndex'
|
||||
)
|
||||
BEGIN
|
||||
EXEC(N'CREATE INDEX [IX_SiteCalls_Created_TrackedOperationId]
|
||||
ON [SiteCalls] ([CreatedAtUtc] DESC, [TrackedOperationId] DESC)');
|
||||
END;
|
||||
|
||||
IF NOT EXISTS (
|
||||
SELECT * FROM [__EFMigrationsHistory]
|
||||
WHERE [MigrationId] = N'20260819183326_AddSiteCallsListSortIndex'
|
||||
)
|
||||
BEGIN
|
||||
INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion])
|
||||
VALUES (N'20260819183326_AddSiteCallsListSortIndex', N'10.0.7');
|
||||
END;
|
||||
|
||||
COMMIT;
|
||||
GO
|
||||
Reference in New Issue
Block a user