Skip to content

feat(java): add stream commands to Jedis compatibility layer#5289

Open
prashanna-frsh wants to merge 8 commits intovalkey-io:mainfrom
prashanna-frsh:task/add-stream-commands
Open

feat(java): add stream commands to Jedis compatibility layer#5289
prashanna-frsh wants to merge 8 commits intovalkey-io:mainfrom
prashanna-frsh:task/add-stream-commands

Conversation

@prashanna-frsh
Copy link
Contributor

Summary

Add stream command support to the Jedis compatibility layer using the GLIDE Java type-safe API. All stream methods in Jedis.java delegate to GlideClient (no customCommand()). Includes migration guide updates, integration and unit tests, XPENDING null-id handling, and Javadoc fixes for the javadoc task.

Issue link

This Pull Request is linked to issue (URL): [https://github.com//issues/5288]

Features / Behaviour Changes

  • Stream commands: XADD, XLEN, XDEL, XRANGE, XREVRANGE, XREAD, XTRIM, XGROUP CREATE/DESTROY/SETID/CREATECONSUMER/DELCONSUMER, XREADGROUP, XACK, XPENDING, XCLAIM, XAUTOCLAIM, XINFO STREAM/GROUPS/CONSUMERS.
  • Jedis API: Methods return StreamEntryID, List<StreamEntry>, Map<String, List<StreamEntry>>, StreamPendingSummary, List<StreamPendingEntry>, StreamInfo, List<StreamGroupInfo>, List<StreamConsumerInfo> as appropriate.
  • Migration guide: Core Commands section updated to list stream operations and set operations as supported.
  • Not included: XSETID (no GLIDE type-safe API).

Implementation

  • Jedis.java: New stream section with helpers toStreamEntryList() and toStreamReadResponse() to map GLIDE Map<String, String[][]> to Jedis List<StreamEntry> and Map<String, List<StreamEntry>>. Range bounds "-"/"+" map to StreamRange.InfRangeBound.MIN/MAX; other IDs use StreamRange.IdBound.of(id). Options use GLIDE StreamAddOptions, StreamReadOptions, StreamReadGroupOptions, StreamTrimOptions, StreamGroupOptions, StreamPendingOptions, StreamClaimOptions.
  • XPENDING: When server returns null for min/max id (e.g. no pending messages), values are normalized to "0-0" before constructing StreamEntryID to avoid NumberFormatException.
  • XINFO: xinfoStream() returns raw Map<String, Object>; xinfoStreamAsInfo() builds StreamInfo with last-generated-id and first/last entry conversion. xinfoGroups/xinfoConsumers convert raw maps to StreamGroupInfo/StreamConsumerInfo (including last-delivered-idStreamEntryID).
  • Javadoc: Replaced -> with " to " and List<StreamEntry> with "List of StreamEntry" in comments to fix javadoc "bad use of '>'" and unknown tag errors.

Limitations

  • XSETID is not implemented; GLIDE Java does not expose it as a type-safe method. Adding it would require customCommand().
  • Stream commands are synchronous (Jedis-style); no async stream API in this layer.

Testing

  • Unit: JedisMethodsTest.testStreamMethodSignaturesExist and testStreamMethodReturnTypes verify stream method presence and return types. Run: ./gradlew :jedis-compatibility:test --tests 'redis.clients.jedis.JedisMethodsTest.testStream*'
  • Integration: JedisTest.stream_* (10 tests: xadd/xlen/xdel, xrange/xrevrange, xread, xtrim, xgroup create/destroy, xgroup setid/createconsumer/delconsumer, xreadgroup/xack, xpending, xinfo stream/groups, xinfo consumers). Run: ./gradlew :integTest:test --tests 'compatibility.jedis.JedisTest.stream_*'
  • Fix applied: stream_xgroup_create_destroy no longer calls XGROUP CREATE twice (removed second create that caused BUSYGROUP). stream_xpending passes after normalizing null min/max id to "0-0".

Checklist

Before submitting the PR make sure the following are checked:

  • This Pull Request is related to one issue.
  • Commit message has a detailed description of what changed and why.
  • Tests are added or updated.
  • CHANGELOG.md and documentation files are updated.
  • Linters have been run (make *-lint targets) and Prettier has been run (make prettier-fix).
  • Destination branch is correct - main or release
  • Create merge commit if merging release branch into main, squash otherwise.

@prashanna-frsh prashanna-frsh requested a review from a team as a code owner February 2, 2026 10:03
@xShinnRyuu xShinnRyuu linked an issue Feb 5, 2026 that may be closed by this pull request
2 tasks
@xShinnRyuu
Copy link
Collaborator

Hi @prashanna-frsh, it looks like your commits are not verified. We have a policy that all commits needs to have signing and signoff. We can help review your PR after these are being taken care of.

@prashanna-frsh prashanna-frsh force-pushed the task/add-stream-commands branch from 6e5157f to e1aecee Compare February 5, 2026 03:39
@prashanna-frsh
Copy link
Contributor Author

Hi @prashanna-frsh, it looks like your commits are not verified. We have a policy that all commits needs to have signing and signoff. We can help review your PR after these are being taken care of.

added it

Comment on lines 6131 to 6144
if (arr == null || arr.length < 4) {
return new StreamPendingSummary(
0L, new StreamEntryID("0-0"), new StreamEntryID("0-0"), Collections.emptyMap());
}
long total =
arr[0] instanceof Long ? (Long) arr[0] : Long.parseLong(String.valueOf(arr[0]));
String minIdStr = String.valueOf(arr[1]);
String maxIdStr = String.valueOf(arr[2]);
if (minIdStr == null || minIdStr.isEmpty() || "null".equals(minIdStr)) {
minIdStr = "0-0";
}
if (maxIdStr == null || maxIdStr.isEmpty() || "null".equals(maxIdStr)) {
maxIdStr = "0-0";
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should these statements return null instead of "0-0" when no pending messages to stay consistent with Jedis?

See Jedis implementation for StreamEntryID:
https://github.com/redis/jedis/blob/master/src/main/java/redis/clients/jedis/BuilderFactory.java#L1940-L1941
https://github.com/redis/jedis/blob/master/src/main/java/redis/clients/jedis/BuilderFactory.java#L1291-L1293

Copy link
Contributor Author

Choose a reason for hiding this comment

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

addressed it

- ✅ List operations (LPUSH, RPUSH, LPOP, RPOP)
- ⚠️ Set operations (SADD, SREM, SMEMBERS) - **Available via `sendCommand()` only**
- ⚠️ Sorted set operations (ZADD, ZREM, ZRANGE) - **Available via `sendCommand()` only**
- ✅ Stream operations (XADD, XLEN, XDEL, XRANGE, XREVRANGE, XREAD, XTRIM, XGROUP CREATE/DESTROY/SETID, XREADGROUP, XACK, XPENDING, XCLAIM, XAUTOCLAIM, XINFO STREAM/GROUPS/CONSUMERS)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could also mention stream XSETID is not supported (although XGROUP SETID is supported). Perhaps a note after this list of commands.

Also, should we add a Stream Commands section to the README.md, similar to how #5305 added a section for the Scripting Commands?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

agree to this,

As I've few other PR's for different commands, post merge i've planned to write extensive docs for jedis-compatibility layer which will be in separate PR.

* @param hash field-value map
* @return generated entry ID
*/
public StreamEntryID xadd(String key, Map<String, String> hash) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

We're missing the XAddParams parameter. Also this function looks like it's supposed to return byte[].

Copy link
Contributor Author

Choose a reason for hiding this comment

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

addressed it

}

/** Returns the number of entries in the stream. Uses GLIDE xlen. */
public long xlen(String key) {
Copy link
Collaborator

@jduo jduo Feb 13, 2026

Choose a reason for hiding this comment

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

Missing the binary variant of this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added the missing binary methods

@prateek-kumar-improving prateek-kumar-improving removed their request for review February 13, 2026 00:46
Signed-off-by: prashanna-frsh <prashanna.rajendran@freshworks.com>
Signed-off-by: prashanna-frsh <prashanna.rajendran@freshworks.com>
Signed-off-by: prashanna-frsh <prashanna.rajendran@freshworks.com>
Signed-off-by: prashanna-frsh <prashanna.rajendran@freshworks.com>
Signed-off-by: prashanna-frsh <prashanna.rajendran@freshworks.com>
Signed-off-by: prashanna-frsh <prashanna.rajendran@freshworks.com>
@prashanna-frsh prashanna-frsh force-pushed the task/add-stream-commands branch from acddfa5 to a6dcd63 Compare February 16, 2026 04:38
…x errors

Signed-off-by: prashanna-frsh <prashanna.rajendran@freshworks.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@prashanna-frsh prashanna-frsh force-pushed the task/add-stream-commands branch from 7f4211c to 31f804d Compare February 16, 2026 09:54
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.

(jedis-compatibility): Add stream commands via GLIDE type-safe API

4 participants