feat: replay prior change notifications via OnEventOrReplay#1013
Conversation
Adds INotificationHandler.OnEventOrReplay, which registers a subscriber and atomically replays any matching ChangeDescription events that fired before the subscription. Enables late-subscriber assertion patterns (e.g. asserting against a MockFileSystem that has already mutated) without bracketing the trigger inside the assertion call. Notification history is recorded by default and can be disabled via MockFileSystemOptions.WithoutNotificationHistory(); when disabled, OnEventOrReplay throws InvalidOperationException so misconfiguration cannot manifest as flaky tests.
There was a problem hiding this comment.
Pull request overview
Adds a new subscription API to the mock file system notification system that can “catch up” late subscribers by replaying prior change notifications, with an opt-out switch to disable history recording.
Changes:
- Introduces
INotificationHandler.OnEventOrReplay(...)to register a callback and replay prior matchingChangeDescriptionevents. - Adds optional notification history recording to
ChangeHandler, enabled by default and disable-able viaMockFileSystemOptions.WithoutNotificationHistory(). - Extends tests to validate replay behavior and the opt-out exception.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| Tests/Testably.Abstractions.Testing.Tests/FileSystem/ChangeHandlerTests.cs | Adds test coverage for replaying prior events, predicate filtering, and opt-out behavior. |
| Source/Testably.Abstractions.Testing/Notification.cs | Adds an internal factory Replay(...) helper used to deliver historical events to a registered callback. |
| Source/Testably.Abstractions.Testing/MockFileSystem.cs | Wires the “record notification history” option into ChangeHandler and adds WithoutNotificationHistory() option. |
| Source/Testably.Abstractions.Testing/FileSystem/INotificationHandler.cs | Adds the new public OnEventOrReplay(...) API with XML docs. |
| Source/Testably.Abstractions.Testing/FileSystem/ChangeHandler.cs | Implements history storage + atomic replay semantics, and throws when history is disabled. |
Test Results 101 files - 1 101 suites - 1 2h 24m 26s ⏱️ -59s For more details on these failures, see this check. Results for commit 5709c92. ± Comparison against base commit a871ca4. |
…se waiter on replay failure Addresses two review issues on OnEventOrReplay: - If a callback throws during replay of buffered changes, the newly registered waiter is now disposed before the exception propagates so it cannot keep receiving future events. - NotifyCompletedChange no longer holds the history lock while invoking user callbacks. The callback set is snapshotted under the lock via SnapshotInvocations and invoked afterward, preserving exactly-once delivery across the live/replay boundary while avoiding callback-induced blocking and deadlock risk. Regenerates the Testably.Abstractions.Testing public API baselines so the ApiChecks task includes the OnEventOrReplay and WithoutNotificationHistory additions.
|
|
This is addressed in release v6.4.0. |



Adds INotificationHandler.OnEventOrReplay, which registers a subscriber and atomically replays any matching ChangeDescription events that fired before the subscription. Enables late-subscriber assertion patterns (e.g. asserting against a MockFileSystem that has already mutated) without bracketing the trigger inside the assertion call.
Notification history is recorded by default and can be disabled via MockFileSystemOptions.WithoutNotificationHistory(); when disabled, OnEventOrReplay throws InvalidOperationException so misconfiguration cannot manifest as flaky tests.