fix(site-event-log): queries on own read connection off the actor thread, bounded keyword window; cap trim counts/vacuums rarely (review 2026-10-21 02/P1, 02/P4)

This commit is contained in:
Joseph Doherty
2026-10-22 08:30:35 -04:00
parent f7c4adbaed
commit 3169429c3f
9 changed files with 194 additions and 35 deletions
@@ -363,6 +363,38 @@ public class EventLogStorageCapScopeTests : IDisposable
e.Level == LogLevel.Warning && e.Message.Contains("did not decrease", StringComparison.Ordinal));
}
private sealed class CountingRowCountPurgeService(
SiteEventLogger eventLogger,
IOptions<SiteEventLogOptions> options,
ILogger<EventLogPurgeService> logger)
: EventLogPurgeService(eventLogger, options, logger)
{
/// <summary>Gets how many times the row count was read from the database.</summary>
public int RowCountReads { get; private set; }
/// <inheritdoc />
internal override long GetSiteEventsRowCount()
{
RowCountReads++;
return base.GetSiteEventsRowCount();
}
}
/// <summary>Review 2026-10-21 02/P4: the cap trim must not COUNT(*) after every batch.</summary>
[Fact]
public void PurgeByStorageCap_RereadsRowCountRarely_NotPerBatch()
{
SeedEvents(12_000); // 12 batches of 1 000 at cap 0 MB
var purge = new CountingRowCountPurgeService(
_eventLogger, Options.Create(CapOptions(0)), new CapturingLogger());
purge.RunPurge();
Assert.Equal(0, EventCount());
Assert.True(purge.RowCountReads <= 3, $"Expected ≤3 COUNT(*) reads for 12 batches, saw {purge.RowCountReads}.");
}
private sealed record LogEntry(LogLevel Level, string Message);
private sealed class CapturingLogger : ILogger<EventLogPurgeService>