fix(scadabridge): queue-depth seed uses Add (no lost concurrent enqueue) + clarify registration/discard comments
This commit is contained in:
@@ -173,4 +173,39 @@ public class QueueDepthGaugeTests : IAsyncLifetime, IDisposable
|
||||
await fresh.StopAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Review finding (FINDING 1): the startup seed must ADD to whatever the counter
|
||||
/// already holds, not overwrite it. A concurrent <c>BufferAsync</c> can
|
||||
/// <c>Interlocked.Increment</c> <c>_bufferedCount</c> in the window between
|
||||
/// <c>StartAsync</c>'s async <c>COUNT(*)</c> returning and the seed running; with an
|
||||
/// <c>Interlocked.Exchange</c> seed that increment would be clobbered (lost +1). This
|
||||
/// pre-increments the in-memory counter (standing in for that concurrent enqueue),
|
||||
/// then starts the service over an empty store and asserts the pre-increment survives.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task Gauge_SeedAddsToConcurrentPreSeedIncrement_NotClobber()
|
||||
{
|
||||
// Store is empty (StartAsync's pending COUNT(*) = 0), so the only contribution
|
||||
// is the simulated concurrent pre-seed enqueue increment.
|
||||
var fresh = new StoreAndForwardService(
|
||||
_storage,
|
||||
new StoreAndForwardOptions { RetryTimerInterval = TimeSpan.FromMinutes(10) },
|
||||
NullLogger<StoreAndForwardService>.Instance);
|
||||
|
||||
// Stand in for a BufferAsync increment that landed before StartAsync seeded.
|
||||
fresh.TestOnly_IncrementBufferedCount();
|
||||
|
||||
try
|
||||
{
|
||||
await fresh.StartAsync();
|
||||
// Add(0 seed) over the pre-existing +1 → 1. An Exchange(0) seed would clobber
|
||||
// it to 0, losing the concurrent enqueue — the bug this fix prevents.
|
||||
Assert.Equal(1, ReadQueueDepthGauge());
|
||||
}
|
||||
finally
|
||||
{
|
||||
await fresh.StopAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user