Skip to content

[Commands API interface consistency #1] tests and non-breaking fixes - #3865

Open
uglide wants to merge 4 commits into
mainfrom
im/api-consistency-tests
Open

[Commands API interface consistency #1] tests and non-breaking fixes#3865
uglide wants to merge 4 commits into
mainfrom
im/api-consistency-tests

Conversation

@uglide

@uglide uglide commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Introduces a reflection-based unit-test suite that verifies the sync, async, reactive, Kotlin coroutine and cluster node-selection command interfaces stay in lockstep, replacing the consistency-by-regeneration guarantee of the template-based API generators (removal of the generators follows in #3866).

What the suite checks

  • Sync ↔ async — method parity in both directions plus RedisFuture<T> return-type wrapping. This is load-bearing at runtime: the sync API is a dynamic proxy over async (FutureSyncInvocationHandler), so a mismatch previously failed only at call time.
  • Sync ↔ reactive — parity plus the Mono/Flux mapping rules (collections → Flux, forced-Flux, Value<>-wrapped elements) and @Deprecated on streaming-channel variants.
  • Sync ↔ Kotlin coroutines — presence plus suspend/Flow shape (via kotlin-reflect, new test-scope dependency managed by the Kotlin BOM).
  • Node-selectionExecutions/AsyncExecutions wrapping and the exclusion list, with a staleness check on the list itself.
  • AggregatesRedisCommands, RedisClusterCommands, NodeSelectionCommands, RedisClusterCoroutinesCommands etc. extend every command group they must cover, and the methods declared directly on the aggregates (auth, select, the CLUSTER commands, …) are parity-checked against their async/reactive counterparts.
  • Builder coverage — every command has a same-named method on its command builder and every command-producing builder method is reachable from an interface.

Structure: CommandInterfaces (group catalog — the single place to register a new command group), KnownApiDeviations (all intentional irregularities, ported from the generator rule tables), TypeSignatures (shared reflection helpers). Supersedes SyncAsyncApiConvergenceUnitTests.

Deviations found and fixed

Calibrating the suite against the committed interfaces surfaced real drift, fixed in the second commit:

  • RedisCoroutinesCommands did not extend RediSearchCoroutinesCommands (the impl already delegated to it)
  • Kotlin coroutine API was missing bitopDiff/bitopDiff1/bitopAndor/bitopOne, hgetex(key, fields), hsetex(key, map) and the xackdel/xdelex stream commands
  • reactive hgetdel/hgetex streaming-channel variants were missing @Deprecated

Deviations found and deferred

The node-selection aggregate wiring drift (missing ACL/Array groups; NodeSelectionAsyncCommands extending the sync NodeSelectionStreamCommands) is not fixed here — correcting it changes return types on AsyncNodeSelection and is therefore a breaking change. It is exempted via KnownApiDeviations.NODE_SELECTION_AGGREGATE_PENDING (with a documenting comment) and fixed in #3867, targeted for the 8.0.0 release.

Note: the first commit intentionally fails the new tests (it demonstrates the drift); the second commit makes the suite green.

Make sure that:

  • You have read the contribution guidelines.
  • You have created a feature request first to discuss your contribution intent. Please reference the feature request ticket number in the pull request.
  • You applied code formatting rules using the mvn formatter:format target. Don't submit any formatting related changes.
  • You submit test cases (unit or integration tests) that back your changes.

🤖 Generated with Claude Code


Note

Medium Risk
Touches many public command interfaces and cluster/coroutine aggregates; mistakes could break compile-time API contracts, though changes are additive or deprecation-only with heavy reflection test coverage.

Overview
Adds a reflection-based unit test suite under io.lettuce.core.api.consistency that keeps sync, async, reactive, Kotlin coroutines, cluster aggregates, node-selection, and command builders aligned—replacing the old SyncAsyncApiConvergenceUnitTests and the generator-era guarantee. Shared scaffolding includes CommandInterfaces, KnownApiDeviations, and TypeSignatures; kotlin-reflect is added as a test dependency.

Interface fixes surfaced by the new tests: RedisCoroutinesCommands and RedisClusterCoroutinesCommands now extend RediSearch (and cluster coroutines also wire Function, JSON, VectorSet, Array); Kotlin coroutines gain 7.7 APIs (bitopDiff/Diff1/Andor/One, simplified hsetex/hgetex, xackdel/xdelex); reactive hgetex/hgetdel streaming-channel overloads are marked @Deprecated; missing @Deprecated on cluster masters() and reactive keysLegacy is restored.

Generator/test maintenance: KotlinCompilationUnitFactory FLOW_METHODS updated for new streaming commands; coroutine integration tests cover hash expiry, bitops, and stream deletion. Known node-selection aggregate gaps stay exempt via NODE_SELECTION_AGGREGATE_PENDING (deferred to 8.0).

Reviewed by Cursor Bugbot for commit 4edb596. Bugbot is set up for automated code reviews on this repo. Configure here.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f29cddcb82

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/test/java/io/lettuce/core/api/consistency/CommandInterfaces.java Outdated
Comment thread src/main/java/io/lettuce/core/cluster/api/async/NodeSelectionAsyncCommands.java Outdated
@uglide
uglide force-pushed the im/api-consistency-tests branch from f29cddc to 2b19668 Compare July 28, 2026 16:22
@uglide uglide changed the title Commands API interface consistency tests [Commands API interface consistency #1] tests and non-breaking fixes Jul 28, 2026
@uglide
uglide force-pushed the im/api-consistency-tests branch from 2b19668 to 7d09bed Compare July 28, 2026 16:33
Introduce reflection-based unit tests that verify the sync, async,
reactive, Kotlin coroutine and cluster node-selection command
interfaces stay in lockstep, replacing the consistency-by-regeneration
guarantee of the template-based API generators:

- CommandInterfaces: catalog of all command groups and their flavors
- KnownApiDeviations: single registry of intentional deviations,
  ported from the generator rule tables
- TypeSignatures: shared reflection and type-normalization helpers
- SyncAsync/SyncReactive/NodeSelection/AggregateInterface/
  CommandBuilderCoverage/KotlinCoroutines consistency tests

The suite checks method parity in both directions, the per-flavor
return-type mapping (RedisFuture, Mono/Flux, suspend/Flow,
Executions), aggregate interface wiring and interface-to-command-
builder coverage. Sync/async parity is load-bearing at runtime: the
sync API is a dynamic proxy over async (FutureSyncInvocationHandler).

Supersedes SyncAsyncApiConvergenceUnitTests. Adds kotlin-reflect as a
test dependency.

Note: at this commit the suite documents real drift in the committed
interfaces — several tests fail intentionally; the deviations are
fixed in the follow-up commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@uglide
uglide force-pushed the im/api-consistency-tests branch from 7d09bed to fddac9d Compare July 28, 2026 16:38

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fddac9d. Configure here.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fddac9d08f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/main/java/io/lettuce/core/api/reactive/RedisHashReactiveCommands.java Outdated
uglide and others added 2 commits July 28, 2026 18:57
Real drift found by the new consistency tests, accumulated while the
API generators were out of use:

- RedisCoroutinesCommands did not extend RediSearchCoroutinesCommands
  (the implementation already delegated to it)
- Kotlin coroutine API was missing bitopDiff/bitopDiff1/bitopAndor/
  bitopOne, hgetex(key, fields), hsetex(key, map) and the
  xackdel/xdelex stream commands
- reactive hgetdel/hgetex streaming-channel variants were missing
  their @deprecated marker

The node-selection aggregate wiring drift (missing ACL/Array groups,
async aggregate extending the sync Stream interface) is exempted via
KnownApiDeviations.NODE_SELECTION_AGGREGATE_PENDING — fixing it is a
breaking change scheduled for the 8.0 release.

Makes the API consistency test suite pass.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- verify the methods declared directly on the aggregate interfaces
  (auth, select, the CLUSTER commands, ...) against their async and
  reactive counterparts, restoring coverage the removed
  SyncAsyncApiConvergenceUnitTests had via RedisCommands.getMethods()
- include RedisClusterCoroutinesCommands in the aggregate wiring check
  and add its missing FUNCTION/JSON/VECTOR_SET/ARRAY/SEARCH groups
  (experimental API; the impl already delegates per group)
- keep the Kotlin generator's FLOW_METHODS in sync with the hand-added
  Flow methods for as long as the generators still exist
- add behavioral coroutine integration tests for the new
  hash-field-expiry, BITOP and stream-deletion commands

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@uglide
uglide force-pushed the im/api-consistency-tests branch from 16eebdb to 622d675 Compare July 28, 2026 16:57

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 622d6750ad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Erased-parameter matching alone would accept flavors whose generic
parameter signatures diverge (e.g. Map<K, V> vs Map<V, K>), and
nothing compared @deprecated across the Java flavors. The suite now
verifies both for sync/async, sync/reactive, node-selection and the
aggregate-declared methods. The reactive dispatch parameter mutation
(CommandOutput<K, V, ?>) and the intentional deprecation of the
CommandOutput-based node-selection dispatch overloads are recorded in
KnownApiDeviations.

Fixes surfaced by the new checks: RedisAdvancedClusterReactiveCommands
.keysLegacy and RedisAdvancedClusterAsyncCommands.masters carried a
@deprecated tag without the matching @deprecated annotation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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