feat(inventory): prune acquire history above 300-row cap

Adds PruneAcquireHistoryAsync to InventoryTransaction.CommitAsync; runs
inside the open DB transaction after history rows are flushed, keeping at
most 300 rows per viewer (oldest discarded). Adds a covering test that
verifies the cap and per-viewer isolation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-06-09 14:41:04 -04:00
parent fb1e6829b7
commit 77ad614258
2 changed files with 54 additions and 0 deletions

View File

@@ -9,6 +9,8 @@ namespace SVSim.Database.Services.Inventory;
internal sealed class InventoryTransaction : IInventoryTransaction
{
private const int AcquireHistoryRetention = 300;
private readonly SVSimDbContext _db;
private readonly IDbContextTransaction _dbTx;
private readonly ILogger _log;
@@ -282,6 +284,8 @@ internal sealed class InventoryTransaction : IInventoryTransaction
WriteAcquireHistory();
await _db.SaveChangesAsync(ct);
await PruneAcquireHistoryAsync(ct);
await _dbTx.CommitAsync(ct);
_committed = true;
@@ -290,6 +294,22 @@ internal sealed class InventoryTransaction : IInventoryTransaction
return new InventoryCommitResult(rewardList, deltas);
}
private async Task PruneAcquireHistoryAsync(CancellationToken ct)
{
var overflowIds = await _db.ViewerAcquireHistory
.Where(h => h.ViewerId == Viewer.Id)
.OrderByDescending(h => h.AcquireTime).ThenByDescending(h => h.Id)
.Skip(AcquireHistoryRetention)
.Select(h => h.Id)
.ToListAsync(ct);
if (overflowIds.Count == 0) return;
await _db.ViewerAcquireHistory
.Where(h => overflowIds.Contains(h.Id))
.ExecuteDeleteAsync(ct);
}
private void WriteAcquireHistory()
{
var now = DateTime.UtcNow;