feat(table): ListCursor for id-keyset pagination#56
Open
klaidliadon wants to merge 2 commits into
Open
Conversation
- add Order.IsValid (strict check) and Order.Sanitize (case/whitespace normalize, unknown -> Asc) so the Order type owns its own rules - Sort.sanitize now delegates direction handling to Order.Sanitize - collapse Page.SetDefaults zero-checks with cmp.Or
- add Table.ListCursor, the forward-only keyset sibling of ListPaged, ordering by IDColumn in a caller-chosen direction (empty -> Asc, any other non-Asc/Desc value is an error via Order.IsValid) - reuse the table's Paginator size settings and EncodeCursor/DecodeCursor; cursor keys on IDColumn via GetID, opaque base64-JSON payload scoped as a local type inside the method - ergonomic layer over CursorPaginator for the common single-id keyset case, so callers skip hand-writing Apply/From/OrderBy
1332d0a to
f8f081c
Compare
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.
CursorPaginator(#55) gives keyset pagination but makes every consumer hand-write aCursortype —Apply/From/OrderBy— even for the overwhelmingly common case of "page by the table's id."ListCursoris the ergonomic sibling ofListPagedfor that case: it keys on the table's ownIDColumnandGetID(), so callers get concurrency-stable, forward-only pagination with one method call and no boilerplate.Two commits: a small
Orderrefactor the feature builds on, then the feature.refactor(page)—Order.IsValid/Order.SanitizeOrder.IsValid()— strict check (exactlyAsc/Desc).Order.Sanitize()— lenient normalize (case + whitespace, unknown →Asc); theOrdertype now owns its own normalization rules.Sort.sanitizedelegates direction handling toOrder.Sanitize()(was an inlineswitch); behavior-identical, still case-insensitive and defaulting.Page.SetDefaultszero-checks collapse tocmp.Or.feat(table)—ListCursorIDColumnin the caller-chosen direction. Emptyorderdefaults toAsc(cmp.Or); any other non-Asc/Descvalue is rejected viaIsValid— a bad direction here is a caller bug, and silently paginating the wrong way is a worse failure than an error.Paginatorsize settings (SetDefaults) andEncodeCursor/DecodeCursor+ErrInvalidCursor.{"id": <value>}) keyed onGetID()— opaque base64-JSON, no new package-level symbol.LIMIT n+1to detectMorewithout a second round-trip, same asPaginator/CursorPaginator.Notes
ListPagedthere's no random page access; in exchange pages never skip or duplicate rows under concurrent writes.IDColumnto be unique — true for a primary key. Deliberately scoped to the id column; ordering by a non-unique column would need a forced tiebreaker, out of scope here.ListCursorrejects an invalidorderwhileSort.sanitizecoerces one — becauseSort's input is often user-facing free text (?sort=-created_at) that must degrade gracefully, whereasListCursor'sorderis a typed developer argument where garbage is a bug.Table, already markedNOTICE: Experimental, so no compatibility ceremony.Test plan
Added
TestTableListCursor(tests/cursor_test.go):LtandGtbranches plusMore/NextCursortransitions).Asc; an invalid order and an undecodable cursor both error (the latter isErrInvalidCursor).make test-all, 0 failures);go build/go vet/gofmt -lclean.