Skip to content

Serialize Optional initialization with source notifications - #1190

Open
dwcullop wants to merge 2 commits into
mainfrom
u/dacullop/main/optional-initialization-ordering
Open

dwcullop wants to merge 2 commits into
mainfrom
u/dacullop/main/optional-initialization-ordering

Conversation

@dwcullop

Copy link
Copy Markdown
Member

Problem

ToObservableOptional(key, initialOptionalWhenMissing: true) decided whether to emit the synthetic initial None using a seenValue flag written by Do on the source and read by an inner Defer on the merged second source. That read/write pair is not serialized with the source's notifications: Merge subscribes to its inputs sequentially, but an already-subscribed asynchronous source can deliver a value while the second input is still being subscribed. The Defer factory could then observe a stale false, and the synthetic None would be delivered after a real Some, clobbering the current value with a spurious None.

Fix

Initial-value selection is now serialized with source notifications rather than racing them. Values and the initialization marker are merged into a single notification stream, and the first-notification state is inspected and updated after Merge has already ordered them. The synthetic None is emitted only when it wins that serialized order, so it can only ever be the first notification; any later None comes from a genuine source removal. State remains per-subscription, and error propagation, completion, and disposal stay owned by the Rx operators.

Validation

Focused concurrency tests for this behavior were added and passed during prior validation of this change (ToObservableOptionalFixture.InitialValue.cs). No unrelated fixes are included in this PR.

Docs

Updated the cache operator reference for ToObservableOptional and the Rx guidance on distinguishing subscription order from notification order, using this operator as the worked example.

Fixes #1178

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: ToObservableOptional can emit an initial None after a concurrently delivered Some

1 participant