fix(store-and-forward): page retry sweep per (category,target) lane; drop dead GetAllMessagesAsync (review 2026-10-21 02/C2, 02/U2)
This commit is contained in:
@@ -822,19 +822,35 @@ public class StoreAndForwardStorageTests : IAsyncLifetime, IDisposable
|
||||
Status = status,
|
||||
};
|
||||
|
||||
/// <summary>Verifies that the all-messages query returns every status, oldest first, up to the limit.</summary>
|
||||
/// <summary>
|
||||
/// Review 2026-10-21 02/C2: a dead target holding more due rows than the sweep page must not
|
||||
/// starve a healthy target — the page is ranked per (category, target) lane, and each lane
|
||||
/// stays oldest-first.
|
||||
/// </summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
public async Task GetAllMessages_ReturnsEveryStatus_OldestFirst_UpToLimit()
|
||||
public async Task GetMessagesForRetry_PagesPerLane_DeadTargetCannotStarveOthers()
|
||||
{
|
||||
var @base = DateTimeOffset.UtcNow;
|
||||
await _storage.EnqueueAsync(NewMsg("p1", StoreAndForwardMessageStatus.Pending, @base));
|
||||
await _storage.EnqueueAsync(NewMsg("k1", StoreAndForwardMessageStatus.Parked, @base.AddSeconds(1)));
|
||||
await _storage.EnqueueAsync(NewMsg("p2", StoreAndForwardMessageStatus.Pending, @base.AddSeconds(2)));
|
||||
var @base = DateTimeOffset.UtcNow.AddHours(-1);
|
||||
for (var i = 0; i < 600; i++)
|
||||
{
|
||||
var m = NewMsg($"a{i:D3}", StoreAndForwardMessageStatus.Pending, @base.AddSeconds(i));
|
||||
m.Target = "dead";
|
||||
m.RetryIntervalMs = 0;
|
||||
await _storage.EnqueueAsync(m);
|
||||
}
|
||||
var healthy = NewMsg("b0", StoreAndForwardMessageStatus.Pending, @base.AddSeconds(1000));
|
||||
healthy.Target = "healthy";
|
||||
healthy.RetryIntervalMs = 0;
|
||||
await _storage.EnqueueAsync(healthy);
|
||||
|
||||
var (all, truncated) = await _storage.GetAllMessagesAsync(limit: 2);
|
||||
Assert.Equal(new[] { "p1", "k1" }, all.Select(m => m.Id)); // every status, oldest-first
|
||||
Assert.True(truncated); // a third row exists beyond the limit
|
||||
var page = await _storage.GetMessagesForRetryAsync(500);
|
||||
|
||||
Assert.Equal(500, page.Count);
|
||||
Assert.Contains(page, m => m.Id == "b0");
|
||||
var dead = page.Where(m => m.Target == "dead").Select(m => m.Id).ToList();
|
||||
Assert.Equal(dead.OrderBy(x => x).ToList(), dead); // per-target FIFO preserved
|
||||
Assert.Equal("a000", dead[0]);
|
||||
}
|
||||
|
||||
// ReplaceAll_SwapsTheEntireBuffer_Atomically was DELETED with ReplaceAllAsync in
|
||||
|
||||
Reference in New Issue
Block a user