fix(worker-tests): close TOCTOU race in slot-failure broadcast poll
QueueServiceSlotFailureTests's throwing-slot test broke its poll loop the instant the DB read observed Status==Failed, but TaskStateService.FailAsync commits the status flip before calling the broadcaster's TaskUpdated, so the assertion could race ahead of the broadcast landing in hub.Proxy.Calls (~1-in-5 failures in isolation). Wait for both signals before breaking.
This commit is contained in:
@@ -132,13 +132,20 @@ public sealed class QueueServiceSlotFailureTests : IDisposable
|
|||||||
await service.StartAsync(cts.Token);
|
await service.StartAsync(cts.Token);
|
||||||
waker.Wake();
|
waker.Wake();
|
||||||
|
|
||||||
|
// FailAsync (TaskStateService.cs:236-249) commits the DB status flip via
|
||||||
|
// ExecuteUpdateAsync *before* it calls the broadcaster's TaskUpdated — so a poll that
|
||||||
|
// breaks the instant it observes Status==Failed can race ahead of the broadcast still
|
||||||
|
// landing in hub.Proxy.Calls. Wait for both signals together so the assertions below
|
||||||
|
// never sample a genuinely-not-yet-broadcast window as a failure.
|
||||||
TaskEntity? reloaded = null;
|
TaskEntity? reloaded = null;
|
||||||
var deadline = DateTime.UtcNow.AddSeconds(10);
|
var deadline = DateTime.UtcNow.AddSeconds(10);
|
||||||
while (DateTime.UtcNow < deadline)
|
while (DateTime.UtcNow < deadline)
|
||||||
{
|
{
|
||||||
using var verify = _db.CreateContext();
|
using var verify = _db.CreateContext();
|
||||||
reloaded = await new TaskRepository(verify).GetByIdAsync(taskId);
|
reloaded = await new TaskRepository(verify).GetByIdAsync(taskId);
|
||||||
if (reloaded!.Status == TaskStatus.Failed) break;
|
var broadcastSeen = hub.Proxy.Calls.Any(
|
||||||
|
c => c.Method == "TaskUpdated" && (string)c.Args[0]! == taskId);
|
||||||
|
if (reloaded!.Status == TaskStatus.Failed && broadcastSeen) break;
|
||||||
await Task.Delay(25);
|
await Task.Delay(25);
|
||||||
}
|
}
|
||||||
cts.Cancel();
|
cts.Cancel();
|
||||||
|
|||||||
Reference in New Issue
Block a user