test(GWC-26): deflake ApplyReconcileBroadcastsAcknowledgeDelta
Seeding the cache with a live Raise transition raced the first reconcile: when the reconcile snapshot populated the cache first, the still-buffered live Raise was applied — and broadcast — after the test's feed subscriber had registered, so the exactly-one-transition assertion saw two. Seed through a reconcile pass instead (forced by a provider-mode probe, as the acked step already did) so no live transition is ever in flight. Verified: 5 consecutive full alarm-monitor runs green, and the test still fails (timeout) with the ApplyReconcile acked-delta branch removed.
This commit is contained in:
@@ -110,15 +110,19 @@ public sealed class GatewayAlarmMonitorAttachOrderTests
|
||||
await monitor.StartAsync(cts.Token);
|
||||
await sessions.WaitForSubscribeStartAsync(WaitTimeout);
|
||||
|
||||
// Seed the cache with an active (unacked) alarm and keep the reconcile snapshot in
|
||||
// agreement, so a periodic reconcile pass cannot clear it out from under the test.
|
||||
// Seed the cache with an active (unacked) alarm through a reconcile rather than a live
|
||||
// transition: a buffered live transition could still be in flight when the cache first
|
||||
// shows the alarm, and would then broadcast to the reader below and pollute the
|
||||
// exactly-one-transition assertion. A provider-mode event forces the reconcile
|
||||
// immediately, so the test never waits on the periodic timer.
|
||||
sessions.SetReconcileSnapshot(Snapshot(AlarmConditionState.Active));
|
||||
sessions.EmitEvent(Transition(1, AlarmTransitionKind.Raise));
|
||||
sessions.EmitEvent(ProviderModeProbe(1));
|
||||
await WaitUntilAsync(
|
||||
() => monitor.CurrentAlarms.Any(alarm => alarm.AlarmFullReference == AlarmReference),
|
||||
() => monitor.CurrentAlarms.Any(alarm => alarm.AlarmFullReference == AlarmReference
|
||||
&& alarm.CurrentState == AlarmConditionState.Active),
|
||||
WaitTimeout);
|
||||
|
||||
// Subscribe AFTER the raise: this reader's snapshot carries the alarm, so every
|
||||
// Subscribe AFTER the seed: this reader's snapshot carries the alarm, so every
|
||||
// transition it observes from here on is a reconcile-derived broadcast.
|
||||
List<AlarmFeedMessage> received = [];
|
||||
TaskCompletionSource snapshotComplete = new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
@@ -129,17 +133,7 @@ public sealed class GatewayAlarmMonitorAttachOrderTests
|
||||
// The worker now reports the same alarm acknowledged. A provider-mode event forces an
|
||||
// immediate reconcile pass so the test does not wait on the periodic timer.
|
||||
sessions.SetReconcileSnapshot(Snapshot(AlarmConditionState.ActiveAcked));
|
||||
sessions.EmitEvent(new MxEvent
|
||||
{
|
||||
Family = MxEventFamily.OnAlarmProviderModeChanged,
|
||||
WorkerSequence = 2,
|
||||
OnAlarmProviderModeChanged = new OnAlarmProviderModeChangedEvent
|
||||
{
|
||||
Mode = AlarmProviderMode.Alarmmgr,
|
||||
Reason = "probe",
|
||||
At = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow),
|
||||
},
|
||||
});
|
||||
sessions.EmitEvent(ProviderModeProbe(2));
|
||||
|
||||
AlarmFeedMessage acknowledge = await WaitForAsync(
|
||||
received,
|
||||
@@ -238,6 +232,20 @@ public sealed class GatewayAlarmMonitorAttachOrderTests
|
||||
},
|
||||
};
|
||||
|
||||
// A no-op provider-mode event. The monitor forces an immediate reconcile after every one,
|
||||
// which is how these tests drive a reconcile pass without waiting on the periodic timer.
|
||||
private static MxEvent ProviderModeProbe(ulong sequence) => new()
|
||||
{
|
||||
Family = MxEventFamily.OnAlarmProviderModeChanged,
|
||||
WorkerSequence = sequence,
|
||||
OnAlarmProviderModeChanged = new OnAlarmProviderModeChangedEvent
|
||||
{
|
||||
Mode = AlarmProviderMode.Alarmmgr,
|
||||
Reason = "probe",
|
||||
At = Timestamp.FromDateTimeOffset(DateTimeOffset.UtcNow),
|
||||
},
|
||||
};
|
||||
|
||||
private static ActiveAlarmSnapshot Snapshot(AlarmConditionState state) => new()
|
||||
{
|
||||
AlarmFullReference = AlarmReference,
|
||||
|
||||
Reference in New Issue
Block a user