feat(audit-log): surface partition-purge failure as health event + counter

This commit is contained in:
Joseph Doherty
2026-07-09 06:49:28 -04:00
parent b59aa2d717
commit 14c4df54f9
9 changed files with 202 additions and 5 deletions
@@ -543,4 +543,50 @@ public class AuditLogPurgeActorTests : TestKit, IClassFixture<MsSqlMigrationFixt
duration: TimeSpan.FromSeconds(3),
interval: TimeSpan.FromMilliseconds(50));
}
// ---------------------------------------------------------------------
// 11. SwitchThrows_PublishesPurgeFailedEvent_AndIncrementsHealthCounter (Task 5)
// ---------------------------------------------------------------------
[Fact]
public void SwitchThrows_PublishesPurgeFailedEvent_AndIncrementsHealthCounter()
{
// A silently failing retention job is a health-surface condition, not just a log line:
// the per-boundary catch must publish AuditLogPurgeFailedEvent AND bump the
// AuditCentralHealthSnapshot.PurgeFailures counter (arch-review 04, S2).
var boundary = new DateTime(2025, 9, 1, 0, 0, 0, DateTimeKind.Utc);
var repo = new RecordingRepo
{
Boundaries = new List<DateTime> { boundary },
ThrowOnBoundary = boundary,
BoundaryException = new InvalidOperationException("simulated switch timeout"),
};
var snapshot = new AuditCentralHealthSnapshot();
var services = new ServiceCollection();
services.AddScoped<IAuditLogRepository>(_ => repo);
services.AddSingleton(snapshot);
services.AddSingleton<IAuditPurgeFailureCounter>(snapshot);
var sp = services.BuildServiceProvider();
var probe = CreateTestProbe();
Sys.EventStream.Subscribe(probe.Ref, typeof(AuditLogPurgeFailedEvent));
Sys.ActorOf(Props.Create(() => new AuditLogPurgeActor(
sp,
Options.Create(FastTickOptions()),
Options.Create(new AuditLogOptions()),
NullLogger<AuditLogPurgeActor>.Instance)));
var evt = probe.ExpectMsg<AuditLogPurgeFailedEvent>(TimeSpan.FromSeconds(5));
Assert.Equal(boundary, evt.MonthBoundary);
Assert.Contains("simulated switch timeout", evt.Error);
Assert.True(evt.ElapsedMilliseconds >= 0);
AwaitAssert(
() => Assert.True(snapshot.PurgeFailures >= 1,
$"expected PurgeFailures >= 1, got {snapshot.PurgeFailures}"),
duration: TimeSpan.FromSeconds(3),
interval: TimeSpan.FromMilliseconds(50));
}
}