fix(worker): StaWaitHelper regression tests + full-drain contract notes; consolidate wait P/Invoke

This commit is contained in:
Joseph Doherty
2026-08-15 17:17:10 -04:00
parent 896d81e286
commit 7c9add3d73
10 changed files with 466 additions and 66 deletions
@@ -113,25 +113,33 @@ public sealed class MxAccessWriteCompletionCacheTests
}
/// <summary>
/// Verifies the wait is message/signal-driven rather than sleep-polled:
/// with a poll interval far longer than the deadline, a completion
/// recorded from another thread still wakes the wait and is returned well
/// inside the deadline. The sleep-polled loop this replaced would have sat
/// blind for the whole 10 s interval — on the STA that means 10 s with no
/// Verifies the wait slice stays bounded no matter what poll interval the
/// caller asks for: with a 10 s interval and a 3 s deadline, a completion
/// recorded 50 ms in is still returned in time, because every slice is
/// capped at the 50 ms fallback tick. The blind <c>Thread.Sleep</c> this
/// replaced would have slept the full interval — on the STA, 10 s with no
/// Windows messages dispatched — and then reported a timeout.
/// </summary>
/// <remarks>
/// Scope: this proves the cadence bound, not the signal path. The clamp
/// alone would satisfy it, so it stays green if the <c>Record</c>-side
/// <c>Set()</c> is deleted. <c>StaWaitHelperTests</c> owns the signal
/// path, where a five-second wait with no clamp in play makes the handle
/// the only thing that can end it early.
/// </remarks>
/// <returns>A task that represents the asynchronous operation.</returns>
[Fact]
public void TryWaitForCompletion_WakesOnCrossThreadRecord_DespiteLongPollInterval()
public async Task TryWaitForCompletion_CompletesWithinDeadline_WhenPollIntervalExceedsTheFallbackTick()
{
MxAccessWriteCompletionCache cache = new();
using ManualResetEventSlim waitEntered = new(false);
Task recorder = Task.Run(() =>
Task recorder = Task.Run(async () =>
{
// Handshake so the completion cannot land before the wait starts —
// otherwise the first check would satisfy it and prove nothing.
waitEntered.Wait(TimeSpan.FromSeconds(5));
Thread.Sleep(50);
await Task.Delay(50, CancellationToken.None);
cache.Record(7, 21, BuildStatuses(detail: 8080));
});
@@ -145,13 +153,13 @@ public sealed class MxAccessWriteCompletionCacheTests
out RepeatedField<MxStatusProxy> statuses,
pollIntervalMs: 10_000);
elapsed.Stop();
recorder.Wait(TimeSpan.FromSeconds(5));
await recorder;
Assert.True(found);
Assert.Equal(8080, Assert.Single(statuses).Detail);
Assert.True(
elapsed.Elapsed < TimeSpan.FromSeconds(2),
$"The wait should have woken on the recorded completion, not slept out the poll interval; took {elapsed.ElapsedMilliseconds} ms.");
$"The wait should have re-checked within the fallback tick, not slept out the poll interval; took {elapsed.ElapsedMilliseconds} ms.");
}
/// <summary>Verifies that Record stores an independent clone of the caller's rows.</summary>