Skip to content

Add additive staleness to @FollowerRead and fail fast on negative - #3

Merged
felipeg48 merged 1 commit into
mainfrom
fix/7-follower-reads
Oct 28, 2026
Merged

felipeg48 merged 1 commit into
mainfrom
fix/7-follower-reads

Conversation

@felipeg48

Copy link
Copy Markdown
Contributor

PR: Add staleness controls to @FollowerRead + fail-fast (core)

Repo: cockroachlabs/cockroachdb-java-library
Branch: fix/7-follower-reads → main
Suggested tag after merge: v0.1.2 (additive)

Summary

Ports the follower-read contract from the Spring Boot starter to the core
annotation: @FollowerRead can now target a specific staleness and rejects
invalid values instead of silently reading current data.

What changed

  • @FollowerRead gains hoursAgo, minutesAgo, secondsAgo (long, default 0).
    They add up and compose to AS OF SYSTEM TIME '-Ns'; nothing set keeps
    follower_read_timestamp().
  • CrdbDispatcher resolves staleness through a new package-private
    followerReadStaleness(...) (overflow-safe Math.addExact/multiplyExact;
    only validated integers are inlined into SQL). When any part is set, the composed
    interval takes precedence over the default staleness string.
  • Negative part → IllegalStateException at annotation-processing time (parity with
    the Spring starter's asOfExpression).

Breaking vs additive

Fully additive. staleness is retained; existing @FollowerRead and
@FollowerRead(staleness=...) behave exactly as before. No change to
CrdbContext/CrdbContextValues/TransactionTemplate.

Testing (verified locally)

  • ./gradlew :core:test → BUILD SUCCESSFUL; 10 new FollowerReadStalenessTest
    cases (default, additive composition, raw-staleness fallback, parts-beat-raw,
    negative → throws, plus end-to-end through the proxy into CrdbContext).
  • Full ./gradlew test → BUILD SUCCESSFUL across all modules against a local
    cockroachdb/cockroach:v26.3.3 node.

Known limitation

The core @FollowerRead only emits AS OF SYSTEM TIME when the annotated method
runs inside a TransactionTemplate. Opening a dedicated read-only transaction for a
bare @FollowerRead is the Spring Boot starter's responsibility (core = primitive,
starter = framework glue). Worth a sentence in the core Javadoc.

Note for reviewers

Running the full suite against a cluster surfaced a pre-existing :ai
VectorStoreIT setup gap — its JDBC URL names database parity_java, which must
exist on the target cluster. Unrelated to this PR; flagging for test-harness
follow-up.

- hoursAgo/minutesAgo/secondsAgo compose to AS OF SYSTEM TIME '-Ns'; default follower_read_timestamp()
- CrdbDispatcher resolves staleness; parts override staleness; IllegalStateException on negative
- Add CHANGELOG and update README annotations/follower-reads
@felipeg48
felipeg48 merged commit e3650d2 into main Oct 28, 2026
1 check passed
@felipeg48
felipeg48 deleted the fix/7-follower-reads branch October 28, 2026 13:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant