Skip to content

Add support for XAUTOCLAIM to stream operations. - #3435

Open
big-cir wants to merge 2 commits into
spring-projects:mainfrom
big-cir:issue/3434
Open

big-cir wants to merge 2 commits into
spring-projects:mainfrom
big-cir:issue/3434

Conversation

@big-cir

@big-cir big-cir commented Sep 8, 2026

Copy link
Copy Markdown

Spring Data Redis exposes XCLAIM but not XAUTOCLAIM. Recovering unacknowledged messages from a failed consumer currently requires either issuing XPENDING first and passing the ids to claim, or unwrapping RedisConnection#getNativeConnection() to call the underlying driver directly. The latter ties the recovery logic to a specific driver and bypasses the serializers configured on the template.

Both driver versions declared in pom.xml already support the command, so this change is only about exposing it: Lettuce 7.7.0 through xautoclaim(K, XAutoClaimArgs<K>) returning ClaimedMessages, and Jedis 8.0.1 through xautoclaim and xautoclaimJustId.

XAutoClaimOptions holds the min-idle-time, the start id and an optional COUNT, mirroring how XClaimOptions sits next to xClaim.

Return type

XAUTOCLAIM returns a cursor in addition to the claimed entries, and a cursor of 0-0 is what tells the caller the scan is finished. Returning a bare List or Flux the way claim does would discard that, so the command returns ClaimedRecords (cursor plus records) and ClaimedRecordIds for the JUSTID variant. Both implement Streamable, like PendingMessages. For the same reason the reactive methods return Mono<ClaimedRecords<...>> rather than a Flux of records. This was the open design question in #3434, so feedback on the shape is welcome.

Out of scope

The third reply element added in Redis 7.0, the ids of pending entries that no longer exist in the stream, is not exposed. Neither driver reports it today. The Lettuce side is fixed in redis/lettuce#3901 and ships in 7.8, so I left it out rather than add an accessor that is always empty. ClaimedRecords and ClaimedRecordIds can take the extra list later without changing the existing signatures.

Driver coverage

Both Lettuce and Jedis, imperative and reactive: LettuceStreamCommands, LettuceReactiveStreamCommands, and JedisStreamCommands (inherited by JedisClusterStreamCommands), with conversion handled in the respective StreamConverters. The Jedis converter filters out nil entries, which Redis versions before 7.0 return in place of pending entries whose message was deleted.

Backward compatibility

xAutoClaim and xAutoClaimJustId are declared as abstract methods on RedisStreamCommands, ReactiveStreamCommands and StringRedisConnection, following the pattern set by xAckDel and xDelEx in #3247. Custom implementations of those interfaces will need to implement the new methods.

Documentation and commits

No update to appendix.adoc is necessary, as XAUTOCLAIM is already listed there as supported, which this change makes true.

Split into two commits, the connection contract first and the template API that builds on it second, to make review easier. Each commit carries its own tests and compiles on its own. Happy to squash if you prefer a single commit.

Verification

Verified locally against Redis 8.6.2 via make start across both drivers, standalone and cluster, imperative and reactive, including the pipeline and transaction paths. 3003 tests across DefaultStreamOperationsIntegrationTests, DefaultReactiveStreamOperationsIntegrationTests, LettuceReactiveStreamCommandsIntegrationTests, the AbstractConnectionIntegrationTests subclasses, the converter unit tests and the DefaultStringRedisConnection unit tests.

The two failures observed, xAckDelShouldAcknowledgeAndDeleteEntries and xAckDelWithStringIdsShouldWork, reproduce on unmodified main in the same environment and are unrelated to this change. New tests cover the claim itself, cursor pagination with COUNT across two calls until the cursor returns to 0-0, the JUSTID variant, and the raw reply shapes of both drivers. Since this introduces new API, those tests do not compile before the change rather than failing against it.

Closes #3434


  • You have read the Spring Data contribution guidelines.
  • You use the code formatters provided here and have them applied to your changes. Don’t submit any formatting related changes.
  • You submit test cases (unit or integration tests) that back your changes.
  • You added yourself as author in the headers of the classes you touched. Amend the date range in the Apache license header if needed. For new types, add the license header (copy from another file and set the current year only).

We now expose XAUTOCLAIM through RedisStreamCommands and ReactiveStreamCommands with implementations for both Lettuce and Jedis. XAutoClaimOptions carries the min-idle-time, the start id and an optional COUNT.

Results are returned as ClaimedRecords and ClaimedRecordIds. Both hold the next cursor alongside the claimed records so that callers can resume the scan, a cursor of 0-0 indicating that the pending entries list has been scanned completely. The reactive variants return Mono rather than Flux for the same reason.

The ids of pending entries that no longer exist in the stream, the third reply element added in Redis 7.0, are not exposed. Neither Lettuce 7.7.0 nor Jedis 8.0.1 report them today.

See spring-projects#3434

Signed-off-by: dae won <eodnjs01477@gmail.com>
StreamOperations and ReactiveStreamOperations now offer autoClaim and autoClaimJustId next to the existing claim methods, applying the configured serializers to keys and records the same way.

Closes spring-projects#3434

Signed-off-by: dae won <eodnjs01477@gmail.com>
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Sep 8, 2026

@renechoi renechoi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ran the branch against Redis 8.6.2 with the pinned drivers. The Lettuce comment on xAutoClaimJustId describes something users will hit: the two drivers return different ids once a claimed entry no longer exists in the stream.

3 entries pending for c1, middle one XDELed, then autoclaim to c2:

  • Lettuce 7.7.0 -> [a, c, b], and b is gone from the stream
  • Jedis 8.0.1 -> [a, c]

redis/lettuce#3901 is merged but not in 7.7.0. Both new JUSTID tests use a single entry and no XDEL, so they stay green either way, while getIds() is documented as the ids that were claimed.

@big-cir

big-cir commented Sep 8, 2026

Copy link
Copy Markdown
Author

Ran the branch against Redis 8.6.2 with the pinned drivers. The Lettuce comment on xAutoClaimJustId describes something users will hit: the two drivers return different ids once a claimed entry no longer exists in the stream.

Thanks for running it, I reproduced exactly what you describe. Three entries pending for c1, middle one XDELed, autoclaim to c2:

  • Lettuce 7.7.0: [a, c, b], with b the deleted one
  • Jedis 8.0.1: [a, c]
  • non-JUSTID autoClaim: [a, c] on both

You are right that the tests do not catch it. All four JUSTID tests use a single entry and no XDEL.

This cannot be fixed inside Spring Data Redis. With JUSTID, ClaimedMessagesOutput appends the third reply element to the same list as the claimed ids, so by the time the converter sees it the boundary is gone. Calling the non-JUSTID form and mapping records to ids would return the right ids, but JUSTID is also the variant that does not increment the delivery counter, so that would trade one divergence for another.

redis/lettuce#3901 fixes this along with adding getDeletedIds(), so both this and the deferred deleted ids resolve together once the driver here moves to 7.8. It was merged on 2026-08-25, after the 7.7.0 release, and 7.8 is not out yet.

@mp911de mp911de linked an issue Sep 21, 2026 that may be closed by this pull request
@mp911de mp911de self-assigned this Sep 21, 2026
@mp911de mp911de added type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged labels Sep 21, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: enhancement A general enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for XAUTOCLAIM to stream operations Add support for XAUTOCLAIM to stream operations

4 participants