perf(sql): sweep/KPI covering indexes + sliced notification terminal purge
This commit is contained in:
+23
-2
@@ -230,9 +230,30 @@ VALUES
|
||||
/// <inheritdoc />
|
||||
public async Task<int> DeleteTerminalOlderThanAsync(DateTimeOffset cutoff, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _context.Notifications
|
||||
// Time-sliced batches: each DELETE covers at most one hour of terminal rows,
|
||||
// capping the lock/log footprint per statement — mirrors
|
||||
// KpiHistoryRepository.PurgeOlderThanAsync (arch-review WP1.4; an unbounded
|
||||
// single-statement ExecuteDeleteAsync would otherwise turn a long-idle catch-up
|
||||
// of the default 365-day window into one giant transaction against
|
||||
// dbo.Notifications). Pure EF LINQ (no raw SQL) so this stays portable across
|
||||
// the SQL Server production provider and the SQLite provider the repository
|
||||
// tests run against.
|
||||
var total = 0;
|
||||
var floor = await _context.Notifications
|
||||
.Where(n => TerminalStatuses.Contains(n.Status) && n.CreatedAt < cutoff)
|
||||
.ExecuteDeleteAsync(cancellationToken);
|
||||
.MinAsync(n => (DateTimeOffset?)n.CreatedAt, cancellationToken);
|
||||
while (floor is not null && floor < cutoff)
|
||||
{
|
||||
var ceiling = floor.Value.AddHours(1) < cutoff ? floor.Value.AddHours(1) : cutoff;
|
||||
total += await _context.Notifications
|
||||
.Where(n => TerminalStatuses.Contains(n.Status) && n.CreatedAt < ceiling)
|
||||
.ExecuteDeleteAsync(cancellationToken);
|
||||
floor = await _context.Notifications
|
||||
.Where(n => TerminalStatuses.Contains(n.Status) && n.CreatedAt < cutoff)
|
||||
.MinAsync(n => (DateTimeOffset?)n.CreatedAt, cancellationToken);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
Reference in New Issue
Block a user