[v1.5] Fix SourceRef.Source and SinkRef.Sink non-idempotent property bug#7907
Merged
Aaronontheweb merged 2 commits intoOct 14, 2025
Conversation
…ug (akkadotnet#7895) Added two tests to demonstrate the bug where ISourceRef<T>.Source property creates a new SourceRefStageImpl instance on every access instead of being idempotent: 1. SourceRef_Source_property_should_be_idempotent_issue_7895 - Verifies that multiple .Source property accesses should return the same instance (currently fails - demonstrates the bug exists) - Tested 25 times with 100% failure rate, proving consistent reproduction 2. SourceRef_multiple_materializations_cause_timeout_issue_7895 - Demonstrates the race condition when multiple SourceRefStageImpl instances try to connect to the same SinkRef - Shows intermittent timeouts and failures due to handshake conflicts These tests will pass once the Source property is made idempotent by caching the created Source instance. Issue: akkadotnet#7895
…kadotnet#7895) Implemented Lazy<T> to make both ISourceRef<T>.Source and ISinkRef<T>.Sink properties idempotent. Previously, these properties created new stage instances on every access, causing race conditions where multiple instances would compete for the same handshake, leading to intermittent subscription timeouts. Changes: - SourceRefImpl<T>: Use Lazy<Source<T, NotUsed>> for thread-safe caching - SinkRefImpl<T>: Use Lazy<Sink<T, NotUsed>> for thread-safe caching - Lazy<T> uses default ExecutionAndPublication mode for thread safety Impact: - Eliminates race conditions from accidental property accesses (debugger, logging, serialization, framework inspection) - Prevents subscription timeouts caused by multiple stage instances - Fixes intermittent ~30% failure rate in production workloads - Double materialization (user error) still fails gracefully at actor protocol level via ObserveAndValidateSender Test Results: - Before fix: Tests failed 25/25 times (100% failure rate) - After fix: Tests passed 10/10 times (100% success rate) Fixes akkadotnet#7895
This was referenced Oct 17, 2025
This was referenced Oct 27, 2025
This was referenced May 21, 2026
Open
Open
Closed
Open
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR backports #7905 from
devtov1.5.This fixes issue #7895 by making both
ISourceRef<T>.SourceandISinkRef<T>.Sinkproperties idempotent usingLazy<T>. Previously, these properties created new stage instances on every access, causing race conditions where multiple instances would compete for the same handshake, leading to intermittent subscription timeouts.Changes
Files Modified:
.Sourceproperty idempotent usingLazy<Source<T, NotUsed>>.Sinkproperty idempotent usingLazy<Sink<T, NotUsed>>Implementation:
Tests Added
1.
SourceRef_Source_property_should_be_idempotent_issue_7895.Sourceproperty accesses return the same instance2.
SourceRef_multiple_materializations_cause_timeout_issue_7895Impact
What This Fixes:
SourceRefStageImplinstancesLazy<T>defaultExecutionAndPublicationmodeWhat Still Fails (As Designed):
ObserveAndValidateSenderTest Results
Technical Notes
Why
Lazy<T>?ExecutionAndPublicationmodeSerialization Compatibility:
Lazy<T>fields are not serialized (transient)InitialPartnerRefis serializedSourceRefImplis created with freshLazy<T>Fixes #7895
Backport of #7905