test(galaxy): de-flake writer-lane and supervisor tests; align EffectiveTimeout doc

The writer concurrency fake parks on its release signal (the 300 ms delay could release the
gate early on a starved pool), the supervisor test's cross-thread hold flag is Volatile, and
the EffectiveTimeout doc now states the 1 s floor the code and tests implement.

Refs #735

Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
This commit is contained in:
Joseph Doherty
2026-10-22 13:29:11 -04:00
parent 3456756cd1
commit 77ca10aa37
3 changed files with 9 additions and 5 deletions
@@ -165,7 +165,9 @@ public sealed class GalaxyDriverProbe : IDriverProbe
/// config's <see cref="GalaxyDriverOptions.ProbeTimeoutSeconds"/> when that is positive and
/// shorter. The knob was authored by the AdminUI and parsed by the factory but consumed by
/// nothing — the probe always ran on the caller's budget alone. A non-positive caller budget
/// is treated as the config value (or 1 s when that is unset too), as before.
/// is floored to 1 s before the comparison (the same floor <see cref="BuildProbeClientOptions"/>
/// applies to the gRPC call budget), so the probe runs briefly rather than cancelling before
/// it starts; a longer config value never raises it above that floor.
/// </summary>
/// <param name="callerTimeout">The budget the host handed the probe.</param>
/// <param name="configuredSeconds">The config's <c>ProbeTimeoutSeconds</c>; ignored when not positive.</param>
@@ -51,7 +51,9 @@ public sealed class GatewayGalaxyDataWriterConcurrencyTests
int seen;
do { seen = Volatile.Read(ref _peak); } while (now > seen && Interlocked.CompareExchange(ref _peak, now, seen) != seen);
if (now >= ReleaseAt) _release.TrySetResult();
await Task.WhenAny(_release.Task, Task.Delay(300, ct));
// Park on the signal; the delay is only a safety net against a wedged test (a starved
// pool must not release the gate early and turn the peak assertion flaky).
await Task.WhenAny(_release.Task, Task.Delay(WaitMs, ct));
Interlocked.Decrement(ref _inFlight);
return _handles.GetOrAdd(fullRef, r => HandleFor?.Invoke(r) ?? Interlocked.Increment(ref _nextHandle));
}
@@ -23,11 +23,11 @@ public sealed class ReconnectSupervisorCycleCtsTests
{
var holdReopen = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
var reopenEntered = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
var hold = false;
var hold = new[] { false }; // read on the recovery loop's thread, written here — Volatile both ways
using var sup = new ReconnectSupervisor(
reopen: async _ =>
{
if (hold)
if (Volatile.Read(ref hold[0]))
{
reopenEntered.TrySetResult();
await holdReopen.Task;
@@ -45,7 +45,7 @@ public sealed class ReconnectSupervisorCycleCtsTests
sup.CyclesStarted.ShouldBe(3);
// Positive control: a cycle parked inside reopen still holds its CTS.
hold = true;
Volatile.Write(ref hold[0], true);
sup.ReportTransportFailure(new IOException("drop 3"));
(await Task.WhenAny(reopenEntered.Task, Task.Delay(WaitMs))).ShouldBe(reopenEntered.Task);
sup.CyclesStarted.ShouldBe(4);