fix(db): preserve optimistic collection order - #1839
KyleAMathews wants to merge 1 commit into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (6)
Included review availability: Your plan provides up to 8 included reviews per hour; 2 remain after this review. 📝 WalkthroughWalkthroughThe collection now merges optimistic rows with synced rows using the configured comparator. Key comparison resolves comparator ties. Tests cover visible iteration surfaces, rollback, rejection, confirmation, and unchanged public layouts. ChangesOptimistic collection ordering
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~25 minutes Change: Bug fix · Severity of issue fixed: Medium Sequence Diagram(s)sequenceDiagram
participant Transaction
participant CollectionStateManager
participant Collection
participant Persistence
Transaction->>CollectionStateManager: apply optimistic mutation
CollectionStateManager->>Collection: expose comparator-ordered rows
Collection->>Transaction: return ordered iteration surfaces
Transaction->>Persistence: await write result
Persistence->>CollectionStateManager: confirm, rollback, or reject
CollectionStateManager->>Collection: update the visible ordered view
Merge Risk: ⚪ Minimal · up to The optimistic overlay preserves configured collection ordering across authoritative and pending rows. No concrete merge-blocking issue remains. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
More templates
@tanstack/angular-db
@tanstack/browser-db-sqlite-persistence
@tanstack/capacitor-db-sqlite-persistence
@tanstack/cloudflare-durable-objects-db-sqlite-persistence
@tanstack/db
@tanstack/db-ivm
@tanstack/db-sqlite-persistence-core
@tanstack/electric-db-collection
@tanstack/electron-db-sqlite-persistence
@tanstack/expo-db-sqlite-persistence
@tanstack/node-db-sqlite-persistence
@tanstack/offline-transactions
@tanstack/powersync-db-collection
@tanstack/query-db-collection
@tanstack/react-db
@tanstack/react-native-db-sqlite-persistence
@tanstack/react-router-with-db
@tanstack/rxdb-db-collection
@tanstack/solid-db
@tanstack/svelte-db
@tanstack/tauri-db-sqlite-persistence
@tanstack/trailbase-db-collection
@tanstack/vue-db
commit: |
|
Size Change: +251 B (+0.15%) Total Size: 165 kB 📦 View Changed
ℹ️ View Unchanged
|
|
Size Change: 0 B Total Size: 7.34 kB ℹ️ View Unchanged
|
|
Closing after scope/value review. This changes optimistic ordering for direct iteration of sorted Collections, but it does not affect normal live-query ordering or the offline-transactions executor. The use case is too narrow to justify adding this behavior and maintenance surface now. The branch is retained if concrete demand appears later. |
Important
This is stacked on #1835. Its base must remain
codex/wave1-core-reconciliationat7a21b713eaa17fc555db98fe20dcccf27bb520eeuntil that PR lands; do not merge this PR first.Preserves a Collection's configured order while optimistic inserts or updates are visible. Every existing Collection iteration surface now observes the same correctly ordered optimistic overlay, with no new API or scheduling behavior.
Root cause
CollectionStateManager.keys()yielded all authoritative keys first and appended optimistic-only keys afterward. Becausevalues(),entries(), the iterator,state,toArray, andcurrentStateAsChanges()derive their order fromkeys(), a pending row could appear out of the Collection's declared comparator order. Optimistic updates also shadowed their authoritative row without moving to the position of their visible optimistic value.Approach
compareKeysordering only for0,-0, orNaNties.This is
O(S + U log U)time withO(U)temporary space forSsynced rows andUoptimistic upserts.Key invariants
Non-goals
Trade-offs and shipped weight
A full visible-state sort would be shorter but would sort all
S + Urows and allocate the complete visible state on every ordered read. The local two-way merge retains the authoritative structure's existing order and limits sorting/allocation to pending upserts. Throwing was rejected because #1792 is an existing-contract defect with a deterministic repair.Exact comparison against the stacked base
7a21b713:-9 -n)-9 -n)The oracle, documentation, and test-only cleanup add exactly 0 B of production JavaScript. Registering the oracle adds 46 raw bytes to the shipped
package.json; that manifest change is included in the package totals above.Verification
On exact base
7a21b713, the permanent same-path oracle deterministically produced expected[a,b,c], actual[a,c,b], first divergence index 1, while its path and declared-order checker controls stayed green.On final head
82d443c3:test:oraclesregistration: the selected campaign executes the new oracle successfully.-7/+11, optimistic-delete placeholder, full visible-state sort, missing optimistic-side sort, quadratic optimistic comparisons, and duplicate merged keys.The two ignored React Native examples still emit the baseline-only missing
expo/tsconfig.basewarning; tests and builds complete successfully.Files changed
packages/db/src/collection/state.ts: ordered optimistic-overlay merge.packages/db/tests/collection-visible-order-oracle.test.ts: public-surface law, tie cases, complexity checks, and hostile-control witnesses.packages/db/tests/collection-sync-reentrancy.test.ts: existing reentrant publication expectation aligned with visible order.packages/db/package.json: register the dedicated oracle intest:oracles.docs/contributing/oracle-coverage.md: document the declared-order law and explicit limits..changeset/fix-optimistic-collection-order.md: patch release note.Provenance and credit
@averypelle) supplied the minimal[a,c,b]pending-overlay witness.autofix-ci[bot], with Kevin De Porre's review.No material code was copied from an unmerged proposal, so no additional coauthor trailer is warranted.
Fixes #1792
Summary by CodeRabbit
Bug Fixes
Tests