fix: populate startAt cursor for getListFromDB pagination - #419
Draft
sinnaj-r wants to merge 1 commit into
Draft
Conversation
When `getListFromDB` is called with `orderBy: null` and a `startAfterDocument`, `getQuery` builds `Cursor(values: [], before: false)` because cursor values are mapped from the (empty) orderBy list. Firestore then treats the cursor as "past the end" and returns zero records, so callers can never advance beyond the first page. Extract the effective orderBy computation into a static helper and use it in `getListFromDB` when `startAfterDocument != null`. Mirrors the pattern already used by `_getListLazyChunked`: - if the caller passed no orderBy but there are inequality filters, seed orderBy from those filter fields (Firestore requires inequality fields to appear first in orderBy anyway). - always append `__name__` as a stable tiebreaker so the cursor has a document reference to anchor on. Behavior is unchanged when `startAfterDocument == null`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
sinnaj-r
force-pushed
the
fix-getlistfromdb-cursor-pagination
branch
from
July 3, 2026 18:47
50772fc to
f7493ab
Compare
2 tasks
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
getListFromDB(the Dart-REST implementation used by all Cloud Run services) breaks Firestore pagination when the caller passesorderBy: nulltogether with astartAfterDocument. The generatedrunQueryrequest containsstartAt: Cursor(values: [], before: false)— Firestore treats the empty cursor as "past the end" and returns zero rows.Root cause:
getQuerybuilds cursor values by mapping over the (missing)orderBy._getListLazyChunkedalready works around this by appending__name__to the orderBy;getListFromDBdid not.Fix
Extract a static helper
computeEffectiveOrderByForPaginationthat mirrors the pattern from_getListLazyChunked:orderBybut there are inequality filters (>,>=,<,<=,!=,not-in), seedorderByfrom those filter fields. (Firestore requires inequality fields to appear first inorderBy; this is what the chunked path already does.)YustOrderBy(field: '__name__')as a stable tiebreaker so the cursor has a document reference to anchor on.getListFromDBnow applies this helper only whenstartAfterDocument != null— behavior for non-paginated callers is unchanged.Reproduction
The bug surfaced when a Univelop customer tried to page through 3000+ ticket records via
/api/v2/workspaces/…/records/tickets?filters=[…]&limit=200. Page 1 returned 200 records and aNext-Pageheader; following theNext-PageURL returned zero rows. Verified against production Firestore that the empty cursor is the culprit.Test plan
test/yust_database_service_dart_test.dartcovering:[__name__][__name__][<field>, __name__]>=and<=) → single field +__name____name____name__→ not appended twice__name__dart analyzecleanRelease
Draft PR while the paired Univelop change (
record_api_service.dartcursor index + classifier) is validated end-to-end. Ready to merge + release as3.33.3once the Univelop side is green.🤖 Generated with Claude Code