feat: add easy-paging-keyset-demo (cursor pagination example)#4
Merged
Conversation
Second demo. Showcases @KeysetPaginate — the cursor pagination path of easy-paging-spring-boot-starter (0.4.0) — which is the strategy you want for unbounded time-series streams (logs, audit events, location pings) where OFFSET slows with depth and COUNT(*) is wasted work. Companion to easy-paging-demo (offset pagination); same H2 in-memory DB and same independent-Gradle-build layout, but different annotation, return type, and WHERE-clause pattern. Domain & seed: - Location entity: (id, workerId UUID, time, lat, lng) - 300 GPS pings for a fixed worker UUID, 1 minute apart, applied via data.sql on startup. Schema includes the covering index (worker_id, time DESC, id DESC) that a real PG/MySQL deployment wants for cursor pagination to stay O(log N) per page. The interesting bits: - Composite keyset on (time, id) — the id tiebreaker is what makes the walk stable when two pings share a timestamp. - Service does the "size + 1" mapper fetch so KeysetPage.build can set hasNext correctly. - application.yml leaves easy-paging.keyset.cursor-secret blank for demo inspectability, with a README note explaining why a missing secret is a vulnerability in production (and how to override via env var for a "production-like" run). The smoke test (LocationControllerTest.walkingNextCursorCoversEveryRowExactlyOnce) walks the entire cursor chain (4 pages of 80) and asserts the no-overlap / no-gaps invariant — the property keyset pagination has to guarantee and the one that breaks first when the WHERE-clause tiebreaker is wrong. Top-level README updated to list this demo alongside the offset one.
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
Second demo in this repo. Showcases `@KeysetPaginate` — the cursor pagination path of `easy-paging-spring-boot-starter` (0.4.0) — which is the strategy you want for unbounded time-series streams (logs, audit events, location pings) where `OFFSET` slows with depth and `COUNT(*)` is wasted work.
Companion to `easy-paging-demo` (offset pagination); same H2 in-memory DB and same independent-Gradle-build layout, but different annotation, return type, and `WHERE`-clause pattern.
Domain & seed
The interesting bits
Verification
CI expectation
The `detect` job from #1 (with #3's fix applied) should:
`easy-paging-demo` should not rebuild — its files weren't touched.
What's next (not in this PR)
Per the agreed roadmap, the remaining easy-paging demos to add (each as its own PR):
Custom `PageResponseFactory` will be folded into the offset demo's README as an "advanced" section rather than getting its own dedicated demo.
Test plan