docs(GWC-26): record alarm feed repairs as at-least-once; share the channel worker fake
Code-review follow-up on fix/gwc-26-27-alarm-attach. ApplyReconcile's snapshot-derived feed repairs are at-least-once, not exactly-once: a reconcile reads the worker's current state while the matching live transition may still be buffered in the monitor's lease, so both broadcast and the duplicates are indistinguishable on the alarm feed. This pre-dates the acked-state delta — the Raise/Clear presence repair has always had it, since nothing serializes a reconcile pass against the in-flight live stream — so closing it (serialization or timestamp dedup) stays out of scope for a P2 fix. Documented instead, with the consumer contract stated explicitly (apply transitions idempotently, never as an increment or toggle): - ApplyReconcile gains a "Delivery semantics" comment. - gateway.md softens the "defense in depth" prose to state the semantics. - docs/Sessions.md carries the same caveat on the alarm-feed description. - Tracker change-log records it as a known pre-existing characteristic and a candidate finding for the next review cycle. Also hoists the ChannelWorkerClient fake — duplicated across the three alarm test files — into TestSupport/, dropping the usings it took with it.
This commit is contained in:
@@ -201,6 +201,8 @@ The single worker event channel has exactly one direct reader: the `SessionEvent
|
||||
|
||||
The monitor takes that lease **before** it issues `SubscribeAlarms`, so no transition window is missed: the pump has been running since `MarkReady` started the dashboard mirror, and the distributor only fans to subscribers registered at fan-out time, so a lease taken after the subscribe + first-reconcile round trips would lose every transition raised inside that window. Transitions arriving while the monitor subscribes and reconciles buffer in the lease's bounded channel and are applied after the reconcile, which is order-safe because a live transition can update an alarm the reconciled snapshot already holds.
|
||||
|
||||
The repair transitions the monitor's reconcile broadcasts on the alarm feed (Raise/Clear presence deltas and the acked-state delta) are **at-least-once**: a reconcile reads the worker's current state while the matching live transition may still be buffered in the lease, so both can be broadcast and the duplicates are indistinguishable — alarm-feed consumers must apply transitions idempotently. This is a property of the reconcile design, not of the buffering above.
|
||||
|
||||
`AttachInternalEventSubscriber` enforces the same readiness gate as `AttachEventSubscriber` — a session (or worker) that is not `Ready` throws `SessionNotReady` *before* the distributor is constructed. A premature attach would otherwise start the pump against a source that throws, completing every subscriber with that error and latching the distributor for the session's whole lifetime.
|
||||
|
||||
Sessions open with `MxGateway:Sessions:DefaultLeaseSeconds` (default 1800) added to the open timestamp. Unary client activity refreshes the lease by the same duration. `ExtendLease` and `IsLeaseExpired` cooperate with `SessionManager.CloseExpiredLeasesAsync`, which iterates a registry snapshot and closes any session whose lease has expired with `LeaseExpiredReason`. `SessionLeaseMonitorHostedService` runs that sweep every `MxGateway:Sessions:LeaseSweepIntervalSeconds` seconds (default 30).
|
||||
|
||||
Reference in New Issue
Block a user