feat(health): report permanently rejected site audit rows on the site health report (ScadaBridge#69)
SiteAuditBacklogSnapshot gains an optional trailing RejectedCount (gauge of Rejected forward-state rows, read from the site store), carried on the wire as SiteAuditBacklogSnapshotDto.rejected_count = 4 (additive; old sites read as 0, old central ignores it). Health page shows an 'Audit rows rejected' badge. Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
@@ -133,6 +133,29 @@ public class SqliteAuditWriterForwardStateTests : IDisposable
|
||||
Assert.Equal(1, writer.RejectedPushRowCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The backlog snapshot reports permanently refused rows via <c>RejectedCount</c> (Gitea #69):
|
||||
/// a Rejected row is still owed (counted in <c>PendingCount</c>) but is also counted separately,
|
||||
/// and rows still Pending do not inflate it.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task BacklogStats_ReportsRejectedCount_SeparatelyFromPending()
|
||||
{
|
||||
await using var writer = CreateWriter();
|
||||
var t = DateTime.UtcNow.AddMinutes(-5);
|
||||
var poison = await WriteAsync(writer, t);
|
||||
await WriteAsync(writer, t.AddSeconds(1));
|
||||
|
||||
Assert.Equal(0, (await writer.GetBacklogStatsAsync()).RejectedCount);
|
||||
|
||||
await writer.RecordRejectedPushAttemptsAsync(new[] { poison }, maxAttempts: 1);
|
||||
|
||||
var stats = await writer.GetBacklogStatsAsync();
|
||||
Assert.Equal(1, stats.RejectedCount);
|
||||
Assert.Equal(2, stats.PendingCount); // Rejected is still owed to central via the pull
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The served high-water mark survives a writer restart: rows served before the restart are
|
||||
/// retired by the first cursor that covers them after it, instead of being stranded owed
|
||||
|
||||
Reference in New Issue
Block a user