fix(firestore): preserve atomic membership reads - #11342
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The updated ReadAll retry test no longer asserts that returned ETags match the final committed snapshot, reducing coverage for a key part of the atomic-view contract.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
Open (1)
What changed in this PR
This PR fixes a Firestore membership-table consistency issue where ReadAllAsync could observe a torn view (rows and cluster version from different commits) when RunQuery streaming overlapped with concurrent updates, by executing full membership reads inside a Firestore transaction to bind the read to a single serializable snapshot.
Changes:
- Run
FirestoreMembershipTable.ReadAllAsyncinside a Firestore transaction to guarantee atomic, snapshot-consistent full-table reads (with SDK retry on read-set changes). - Update the protocol-level tests to assert transactional query selectors, commit/transaction correlation, and retry behavior during streamed changes and error scenarios.
| File | Description |
|---|---|
| src/Google/Orleans.Clustering.Firestore/FirestoreMembershipTable.cs | Wraps ReadAllAsync in a Firestore transaction so version + rows are read from one serializable snapshot (with automatic retry on contention). |
| test/Extensions/Orleans.Clustering.Firestore.Tests/FirestoreMembershipHeartbeatTests.cs | Adjusts protocol-level assertions to validate transactional reads/commits and retry behavior for ReadAllAsync while keeping ReadRowAsync non-transactional. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
It changes the runtime consistency mechanism for cluster membership reads (introducing transactional reads and retry semantics), which warrants final human review despite strong targeted test updates.
Review effort: Lite
Findings: None
Resolved since last review (1)
Code coverage
Report-only conclusion: current-main baseline stale. The newest successful coverage run tested a68e9ed, not current main 8bc9fd2. Coverage combines every CI test matrix job, including providers, CodeGen, .NET 8/10, Linux, Windows, and macOS, using canonical physical source and branch identities. The comparison remains report-only while normal line and branch variance is calibrated. Coverage details |

Firestore
ReadAllAsynccould return a torn membership view when a concurrent update landed while the emulator was streamingRunQueryresponses. This surfaced as the table version and membership row status coming from different committed states inConcurrentReadAll_ReturnsOnlyAtomicCommittedViews.Execute full membership reads inside a Firestore transaction so every streamed row and the version document are bound to one serializable snapshot. If a concurrent write changes the transaction's read set, the Firestore SDK retries the read rather than returning a mixed view.
The protocol-level coverage now verifies the transaction selector, commit association, retry behavior, failure propagation, and cancellation behavior for full-table reads.
Microsoft Reviewers: Open in CodeFlow