You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(db,electric,query): separate cursor expressions for flexible pagination (#960)
* feat(db,electric,query): separate cursor expressions from where clause in loadSubset
- Add CursorExpressions type with whereFrom, whereCurrent, and lastKey
- LoadSubsetOptions.where no longer includes cursor - passed separately via cursor property
- Add offset to LoadSubsetOptions for offset-based pagination support
- Electric sync layer makes two parallel requestSnapshot calls when cursor present
- Query collection serialization includes offset for query key generation
This allows sync layers to choose between cursor-based or offset-based pagination,
and Electric can efficiently handle tie-breaking with targeted requests.
test(react-db): update useLiveInfiniteQuery test mock to handle cursor expressions
The test mock's loadSubset handler now handles the new cursor property
in LoadSubsetOptions by combining whereCurrent (ties) and whereFrom (next page)
data, deduplicating by id, and re-sorting.
fix(electric): make cursor requestSnapshot calls sequential
Changed parallel requestSnapshot calls to sequential to avoid potential
issues with concurrent snapshot requests that may cause timeouts in CI.
fix(electric): combine cursor expressions into single requestSnapshot
Instead of making two separate requestSnapshot calls (one for whereFrom,
one for whereCurrent), combine them using OR into a single request.
This avoids potential issues with multiple sequential snapshot requests
that were causing timeouts in CI.
The combined expression (whereFrom OR whereCurrent) matches the original
behavior where cursor was combined with the where clause.
wip
working?
update changeset
fix query test
* update docs
* ci: apply automated fixes
* fixups
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Enhanced LoadSubsetOptions with separate cursor expressions and offset for flexible pagination.
8
+
9
+
**⚠️ Breaking Change for Custom Sync Layers / Query Collections:**
10
+
11
+
`LoadSubsetOptions.where` no longer includes cursor expressions for pagination. If you have a custom sync layer or query collection that implements `loadSubset`, you must now handle pagination separately:
12
+
13
+
-**Cursor-based pagination:** Use the new `cursor` property (`cursor.whereFrom` and `cursor.whereCurrent`) and combine them with `where` yourself
14
+
-**Offset-based pagination:** Use the new `offset` property
15
+
16
+
Previously, cursor expressions were baked into the `where` clause. Now they are passed separately so sync layers can choose their preferred pagination strategy.
17
+
18
+
**Changes:**
19
+
20
+
- Added `CursorExpressions` type with `whereFrom`, `whereCurrent`, and optional `lastKey` properties
21
+
- Added `cursor` to `LoadSubsetOptions` for cursor-based pagination (separate from `where`)
22
+
- Added `offset` to `LoadSubsetOptions` for offset-based pagination support
23
+
- Electric sync layer now makes two parallel `requestSnapshot` calls when cursor is present:
24
+
- One for `whereCurrent` (all ties at boundary, no limit)
25
+
- One for `whereFrom` (rows after cursor, with limit)
26
+
- Query collection serialization now includes `offset` for query key generation
27
+
- Added `truncate` event to collections, emitted when synced data is truncated (e.g., after `must-refetch`)
28
+
- Fixed `setWindow` pagination: cursor expressions are now correctly built when paging through results
29
+
- Fixed offset tracking: `loadNextItems` now passes the correct window offset to prevent incorrect deduplication
30
+
-`CollectionSubscriber` now listens for `truncate` events to reset cursor tracking state
31
+
32
+
**Benefits:**
33
+
34
+
- Sync layers can choose between cursor-based or offset-based pagination strategies
35
+
- Electric can efficiently handle tie-breaking with two targeted requests
36
+
- Better separation of concerns between filtering (`where`) and pagination (`cursor`/`offset`)
37
+
-`setWindow` correctly triggers backend loading for subsequent pages in multi-column orderBy queries
38
+
- Cursor state is properly reset after truncation, preventing stale cursor data from being used
Copy file name to clipboardExpand all lines: docs/collections/query-collection.md
+15-4Lines changed: 15 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -521,7 +521,7 @@ All direct write methods are available on `collection.utils`:
521
521
522
522
## QueryFn and Predicate Push-Down
523
523
524
-
When using `syncMode: 'on-demand'`, the collection automatically pushes down query predicates (where clauses, orderBy, and limit) to your `queryFn`. This allows you to fetch only the data needed for each specific query, rather than fetching the entire dataset.
524
+
When using `syncMode: 'on-demand'`, the collection automatically pushes down query predicates (where clauses, orderBy, limit, and offset) to your `queryFn`. This allows you to fetch only the data needed for each specific query, rather than fetching the entire dataset.
525
525
526
526
### How LoadSubsetOptions Are Passed
527
527
@@ -530,9 +530,13 @@ LoadSubsetOptions are passed to your `queryFn` via the query context's `meta` pr
0 commit comments