fix(management): purge terminal PendingSecuredWrites rows on the list sweep after a retention window (review 2026-10-21 08/G3)

This commit is contained in:
Joseph Doherty
2026-10-22 09:25:48 -04:00
parent baab6ac78e
commit d495494074
8 changed files with 237 additions and 1 deletions
@@ -358,6 +358,53 @@ public class SecuredWriteRepositoryTests : IClassFixture<MsSqlMigrationFixture>
Assert.Equal(4, rows.Count);
}
/// <summary>
/// Review 2026-10-21 08/G3: the terminal purge deletes decided/executed rows whose last
/// lifecycle instant is before the cutoff, and never touches Pending or recent rows.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
[SkippableFact]
public async Task PurgeTerminalAsync_DeletesOnlyOldTerminalRows()
{
Skip.IfNot(_fixture.Available, _fixture.SkipReason);
var siteId = NewSiteId();
var old = new DateTime(2001, 1, 1, 0, 0, 0, DateTimeKind.Utc);
long oldExecuted, oldRejected, oldPending, recentlyExecuted;
await using (var context = CreateContext())
{
var repo = new SecuredWriteRepository(context);
oldExecuted = await repo.AddAsync(With(NewRow(siteId, "Executed"), old, executedAt: old.AddMinutes(1)));
oldRejected = await repo.AddAsync(With(NewRow(siteId, "Rejected"), old, decidedAt: old.AddMinutes(1)));
oldPending = await repo.AddAsync(With(NewRow(siteId, "Pending"), old));
// Submitted long ago but executed recently: its LAST lifecycle instant is recent.
recentlyExecuted = await repo.AddAsync(With(NewRow(siteId, "Executed"), old, executedAt: DateTime.UtcNow));
}
await using (var purgeContext = CreateContext())
{
var deleted = await new SecuredWriteRepository(purgeContext)
.PurgeTerminalAsync(new DateTime(2002, 1, 1, 0, 0, 0, DateTimeKind.Utc), batchSize: 1000);
Assert.True(deleted >= 2);
}
await using var verify = CreateContext();
var verifyRepo = new SecuredWriteRepository(verify);
Assert.Null(await verifyRepo.GetAsync(oldExecuted));
Assert.Null(await verifyRepo.GetAsync(oldRejected));
Assert.NotNull(await verifyRepo.GetAsync(oldPending));
Assert.NotNull(await verifyRepo.GetAsync(recentlyExecuted));
}
private static PendingSecuredWrite With(
PendingSecuredWrite row, DateTime submittedAt, DateTime? decidedAt = null, DateTime? executedAt = null)
{
row.SubmittedAtUtc = submittedAt;
row.DecidedAtUtc = decidedAt;
row.ExecutedAtUtc = executedAt;
return row;
}
// --- helpers ------------------------------------------------------------
private ScadaBridgeDbContext CreateContext()