fix(galaxy): WatchedPlatforms cannot show a platform before its probe binding is routable (#856)
PerPlatformProbeWatcher records a platform's handle and publishes the probe binding into the driver registry as one step under _syncLock, but WatchedPlatforms read the handle map lock-free - so it could report a platform one step ahead of the registry Upsert. A ScanState event raised in that window was dispatched by the EventPump, missed ResolveSubscribers and was dropped as "stale after unsubscribe", leaving the host status empty. That is the #856 flake: A_fetch_completing_after_init_populates_host_statuses waited for WatchedPlatforms, emitted ScanState, and timed out at 10 s on the final Running wait. Reproduced 11/700 (28 parallel runners x 25 + 14 CPU burners), every failure at that step with the binding present by the time of diagnosis and hostStatuses=[] - i.e. the event was dropped. 0/1400 after. WatchedPlatforms now reads under _syncLock (test seam only; the dispatch path already checks the map after the registry, the safe order). New PerPlatformProbeWatcherVisibilityTests spins a reader on another thread and asserts the registry entry exists the moment the platform is visible (old code: torn in 1691/2000 iterations). WaitUntilAsync gains a describe overload; the #856 test's waits now report elapsed time and the observed seed/binding/pump/host-status chain on timeout. Claude-Session: https://claude.ai/code/session_01GT67AD99zQQqpLCVm3p7xk
This commit is contained in:
@@ -192,8 +192,17 @@ public sealed class PerPlatformProbeWatcher : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Snapshot of platform tag names currently watched.</summary>
|
||||
public IReadOnlyCollection<string> WatchedPlatforms => [.. _itemHandlesByPlatform.Keys];
|
||||
/// <summary>
|
||||
/// Snapshot of platform tag names currently watched. Read under the sync lock so a platform
|
||||
/// is never visible here before <see cref="SubscribeAndRecordAsync"/> has published its probe
|
||||
/// binding into the driver registry (the record and the publish are one locked step): a
|
||||
/// caller that sees the platform and then raises a ScanState event must find it routable,
|
||||
/// not dropped by the pump as "stale after unsubscribe" (#856).
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<string> WatchedPlatforms
|
||||
{
|
||||
get { lock (_syncLock) return [.. _itemHandlesByPlatform.Keys]; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reconcile the watched platform set against <paramref name="platformTagNames"/>.
|
||||
|
||||
Reference in New Issue
Block a user