fix: db() reflects owned-state commits (read-your-writes)#1385
Open
bplatz wants to merge 1 commit into
Open
Conversation
The owned-state API (`insert`/`update`/`transact(ledger, ...)` and the `transact(...).execute()` builder) committed and published to the nameservice but returned a new `LedgerState` without writing it back to the `LedgerManager` cache. A subsequent `fluree.db()` / `ledger_cached()` on a warm cache then served the pre-commit view — a read-your-writes violation (issue #1330). Add `Fluree::finalize_owned_commit`, a shared tail for the owned-state commit methods that writes the committed state back into the cache (monotonic, only when already cached) before computing indexing status and triggering background indexing. This also consolidates six duplicated post-commit tails. The guarded builder path is unaffected — it already updates the cache via `finalize_commit` under the write lock, which is why the server transaction path was never affected. - `LedgerManager::get_loaded_handle`: fetch a cached handle without forcing a load from the nameservice. - Drop the `db_at_t` workarounds in `it_cyclic_bgp_probe` and `it_join_batched_overlay`; add `it_read_your_writes` regression test. - `it_notify_incremental` now creates a genuine cross-writer gap via a peer `LedgerManager` (in-process commits no longer leave the writer's own cache stale — that's the fix). - `it_query_sparql_indexed`: head-with-novelty views now take the production overlay fast path, which renders a decimal AVG as a string. Closes #1330
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.
Problem
Closes #1330
Calling
fluree.db(ledger_id)after committing through the owned-state API could return a previously cachedGraphDbview that predates those commits — a read-your-writes violation.The owned-state API (
insert/update/transact(ledger, ...)and thetransact(...).execute()builder) consumes a caller-suppliedLedgerState, commits, and publishes to the nameservice, then returns a newLedgerState— but it never wrote that state back into theLedgerManagercache. A subsequentdb()/ledger_cached()on a warm cache therefore served the pre-commit view.The guarded builder path (
fluree.stage(&handle).execute()) was never affected: it holds the ledger write lock across stage + commit and replaces the cached state viafinalize_commit. The server transaction path (LocalCommitter) uses that guarded path, so server-side read-your-writes was already correct — this only affected the embedded owned-state API.Fix
Fluree::finalize_owned_commit, a shared post-commit tail for the owned-state methods that writes the committed state back into the cache (viasync_owned_commit_to_cache) before computing the indexing status and triggering background indexing. This also consolidates six duplicated post-commit tails into one.sync_owned_commit_to_cacheis monotonic (skips when the cache has advanced past the new state) and only touches an already-cached handle — an uncached ledger loads fresh from the nameservice head on next access. On arefresh_indexfailure it evicts the entry so the next access reloads rather than serving stale state.LedgerManager::get_loaded_handleto fetch a cached handle without forcing a load.Tests
db_at_tworkarounds init_cyclic_bgp_probeandit_join_batched_overlay(the sites the issue called out).it_read_your_writesas a direct regression test.it_notify_incremental: in-process commits no longer leave the writer's own cache stale, so these now create a genuine cross-writer gap via a peerLedgerManager(the realistic scenarionotifycatch-up exists for).it_query_sparql_indexed: head-with-novelty views now take the production overlay fast path, which renders a decimalAVGas a precision-preserving string.Verification
fluree-db-apisuite (2253 tests) +fluree-db-server/fluree-db-consensustests pass.cargo fmt --all --checkandcargo clippy --all --all-features --all-targets -- -D warningsclean.Docs
Updated
docs/getting-started/rust-api.mdanddocs/concepts/time-travel.mdto state that a writer reads its own writes in-process, with eventual consistency remaining a cross-process concern.