Skip to content

feat: Value Commands for Lettuce backend#4

Open
vchomakov wants to merge 2 commits into
lettuce-proxy-infrastructurefrom
lettuce-value-commands
Open

feat: Value Commands for Lettuce backend#4
vchomakov wants to merge 2 commits into
lettuce-proxy-infrastructurefrom
lettuce-value-commands

Conversation

@vchomakov

Copy link
Copy Markdown
Collaborator

Summary

Adds the ValueCommands / ReactiveValueCommands implementation on the Lettuce backend, building on the proxy infrastructure already in place.

This is the first command group to land on Lettuce. The patterns established here — converter registry usage, reactive-to-async bridging via LettuceResult.toUni, blocking-over-reactive timeout wrapping — will be reused by every subsequent command group (Hash, List, Set, SortedSet, …).

What's included

Production code

  • AbstractLettuceCommands<K, V> — shared base class for Lettuce-backed reactive command groups. Holds the RedisAsyncCommands<K, V> handle obtained from StatefulRedisConnection#async(). Mirrors the role of AbstractRedisCommands on the Vert.x side.

  • LettuceReactiveValueCommandsImpl<K, V> — implements all 27 methods of ReactiveValueCommands<K, V>. Each method validates arguments, looks up any structured argument converter in LettuceConverterRegistry, invokes the matching Lettuce async command, and adapts the resulting CompletionStage<T> to Uni<T>. Registers the Value-Commands converters in a static initializer on first class load.

  • LettuceBlockingValueCommandsImpl<K, V> — implements ValueCommands<K, V> by delegating to the reactive impl and awaiting each result with .await().atMost(timeout). Parallels BlockingStringCommandsImpl on the Vert.x side.

  • LettuceValueCommandsConverters — translates Quarkus SetArgs / GetExArgs to their Lettuce counterparts. Parses the wire-format token list returned by toArgs() (the Quarkus arg classes expose no getters). Self-registers with LettuceConverterRegistry via an idempotent, thread-safe register().

Tests

  • LettuceValueCommandsConvertersTest — 16 pure-JVM unit tests. For each SetArgs / GetExArgs flag combination (EX, EXAT, PX, PXAT, NX, XX, KEEPTTL, GET, PERSIST, combined, empty), builds the Quarkus object, converts it, renders the Lettuce args to wire tokens via CommandArgs#toCommandString(), and asserts they match the original Quarkus toArgs() output. Verifies semantic round-trip without needing a Redis instance.

  • LettuceValueCommandsIntegrationTest — 16 tests against a real Redis 7 container via Testcontainers. Exercises both reactive and blocking implementations end-to-end:

    • GET/SET round-trip; SET with NX/XX/EX
    • SETEX / PSETEX / SETNX TTL behavior
    • SETGET (legacy and modern)
    • INCR / DECR / INCRBY / DECRBY / INCRBYFLOAT
    • APPEND / STRLEN
    • MGET (including a missing key mapped to null) / MSET / MSETNX (all-or-nothing semantics)
    • GETEX with EX and PERSIST
    • GETDEL / GETRANGE / SETRANGE
    • Reactive API smoke test
    • getDataSource() accessor pass-through

Each test calls flushdb() in @BeforeEach for isolation.

Notes on LCS / lcsLength

Lettuce 6.5.x exposes only stralgoLcs, which emits the deprecated STRALGO LCS command — removed in Redis 7.0. Rather than shipping a broken code path, both methods fail with a clear UnsupportedOperationException:

LCS is not supported on the Lettuce backend with Lettuce 6.5.x: the only available API emits the deprecated STRALGO command, which was removed in Redis 7.0. Native LCS support will be enabled with the Quarkus 4 / Lettuce 7 upgrade.

When the Lettuce 7 upgrade lands, enabling LCS is a mechanical one-line replacement in each method; the helper constructing this exception gets deleted. Two integration tests lock in the current behavior.

Out of scope

  • Wiring into @Inject RedisDataSource / @Inject ReactiveRedisDataSource — backend selection is a separate follow-up PR
  • Other command groups (Key, Hash, List, Set, SortedSet, …) — each follows the same template and lands as its own PR
  • Transactions, pipelining, pub/sub on Lettuce
  • Native-image support

Verification

  • extensions/redis-client/runtime full test suite — all tests passing, no regressions
  • New tests: 32/32 green (16 unit + 16 integration)

Dependency chain

This branch depends on the proxy infrastructure branch (lettuce-proxy-infrastructure). Once that merges, this rebases cleanly on top.

@vchomakov vchomakov self-assigned this May 13, 2026
@vchomakov vchomakov requested review from Dgramada and tishun May 26, 2026 09:44
@vchomakov vchomakov force-pushed the lettuce-proxy-infrastructure branch from 25d3e35 to 8b6ecd1 Compare July 2, 2026 13:14
vchomakov added 2 commits July 3, 2026 18:44
Implements reactive and blocking Value Commands (GET/SET/INCR/DECR/MGET/MSET/APPEND/STRLEN/GETEX/GETDEL/GETRANGE/SETRANGE/...) on the Lettuce backend via the proxy infrastructure.

- AbstractLettuceCommands: shared base for Lettuce reactive command groups
- LettuceReactiveValueCommandsImpl: async Lettuce -> Mutiny Uni adaptation
- LettuceBlockingValueCommandsImpl: wraps the reactive impl with timeout
- LettuceValueCommandsConverters: SetArgs / GetExArgs -> Lettuce equivalents, registered with LettuceConverterRegistry on first use

LCS / LCSLEN: not supported on Lettuce 6.5.x (only exposes the deprecated STRALGO form, removed in Redis 7.0); enabled with the Lettuce 7 upgrade.

Tests: 16 converter unit tests + 16 integration tests against Redis 7.
- Register argument converters in a static initializer instead of a
  volatile flag with double-checked locking; register() remains as an
  explicit class-initialization trigger.
- Rework the SetArgs/GetExArgs token loops to arrow-style switches over
  an iterator, with a helper that consumes and validates keyword values,
  replacing the tokens.get(++i) side effect.
- Hardcode the "map" parameter name in requireNonEmpty and drop the
  redundant @SuppressWarnings("deprecation") on getset.
@vchomakov vchomakov force-pushed the lettuce-value-commands branch from 2159dca to 020084c Compare July 3, 2026 15:45
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.

2 participants