Skip to content

feat(client): add LMOVEM and BLMOVEM commands - #3340

Merged
nkaradzhov merged 6 commits into
redis:masterfrom
nkaradzhov:move-between-lists
Jul 28, 2026
Merged

feat(client): add LMOVEM and BLMOVEM commands#3340
nkaradzhov merged 6 commits into
redis:masterfrom
nkaradzhov:move-between-lists

Conversation

@nkaradzhov

@nkaradzhov nkaradzhov commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

This pull request adds the LMOVEM and BLMOVEM commands to @redis/client, closing the gap where only a single element could be moved between lists (LMOVE/BLMOVE) while the pop family already moved many.

  • LMOVEM source destination <LEFT|RIGHT> <LEFT|RIGHT> [<COUNT|EXACTLY> count <OBO|BULK>] — moves up to (COUNT) or exactly (EXACTLY) N elements from one end of the source list to one end of the destination; reply is always an array of moved elements (destination order), or null when nothing moved.
  • BLMOVEM — blocking variant, same options plus a timeout (seconds, 0 = forever).

API

Options are modeled as a discriminated union — { COUNT: number, ORDER?: 'OBO' | 'BULK' } XOR { EXACTLY: number, ORDER?: 'OBO' | 'BULK' } — so COUNT/EXACTLY are mutually exclusive at the type level, and ORDER (OBO = stack/reversed, BULK = queue/preserved) only applies when a count is given. Omitting options moves a single element, still as an array reply. Both raw and camelCase aliases are exposed (LMOVEM/lMoveM, BLMOVEM/blMoveM).

Considerations

  • New commands (not options on LMOVE/BLMOVE) so the reply type never changes with arguments.
  • Single-slot multi-key: source and destination must be hash-tag collocated in cluster mode; specs use {tag} prefixes.
  • Commands are unreleased upstream, so behavior tests were authored but not executed locally (no server build exposing LMOVEM); argument serialization is type-checked and asserted via parseArgs.

🤖 Generated with Claude Code


Note

Low Risk
Additive client command definitions and tests only; no changes to existing LMOVE/BLMOVE behavior or shared runtime paths beyond new exports.

Overview
Adds Redis 8.10 list commands LMOVEM and BLMOVEM to @redis/client, so callers can move multiple elements between lists (alongside existing single-element LMOVE / BLMOVE).

LMOVEM parses source/destination keys, list sides, and optional COUNT or EXACTLY plus required OBO / BULK ordering via shared parseLMoveMOptions. Replies are typed as an array of moved elements or null. BLMOVEM mirrors that with a blocking timeout and reuses LMOVEM’s reply handling.

The public API exposes LMOVEM / lMoveM and BLMOVEM / blMoveM on the command index with JSDoc. LMoveMOptions is a discriminated union so COUNT and EXACTLY are mutually exclusive at compile time.

Specs cover argument serialization and integration behavior (empty source, COUNT clamping, EXACTLY no-op, OBO vs BULK, blocking timeout), gated at Redis 8.10 and using hash-tagged keys for cluster.

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

@nkaradzhov
nkaradzhov marked this pull request as ready for review July 14, 2026 13:27
@nkaradzhov
nkaradzhov requested a review from PavelPashov July 14, 2026 13:28

@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

Reviewed by Cursor Bugbot for commit ef8c325. Configure here.

Comment thread packages/client/lib/commands/LMOVEM.spec.ts
nkaradzhov and others added 4 commits July 21, 2026 21:50
Add LMOVEM and its blocking variant BLMOVEM to move multiple elements
between two lists in a single command, closing the gap where only one
element could be moved (LMOVE/BLMOVE) while the pop family already
supported many.

Options are modeled as a discriminated union so COUNT and EXACTLY are
mutually exclusive at the type level, each with an optional OBO|BULK
ordering. Reply is always an array of moved elements (destination
order) or null when nothing moved. Single-slot multi-key: specs use
hash-tag collocated keys for cluster.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add isVersionGreaterThanHook([8, 10]) so behavior tests run only on
Redis 8.10+, and add @SInCE 8.10 to the LMOVEM/BLMOVEM registry JSDoc.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the single-caller parseLMoveMArguments helper; BLMOVEM cannot
reuse it (timeout sits mid-args), so it was dead abstraction.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Extract parseLMoveMOptions helper shared by LMOVEM and BLMOVEM
- Correct BLMOVEM JSDoc blocking-semantics wording (COUNT unblocks at 1)
- Add @see redis.io links to LMOVEM/BLMOVEM entries
- Cover no-options single-element reply, COUNT clamping, EXACTLY-too-few

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@nkaradzhov
nkaradzhov force-pushed the move-between-lists branch from ef8c325 to 29581f7 Compare July 21, 2026 18:51
The spec expected LMOVEM with EXACTLY greater than the source list
length to reject with a server error, but Redis 8.10 replies with null
and moves nothing. Assert a null reply instead and document the null
reply in the EXACTLY option JSDoc.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread packages/client/lib/commands/LMOVEM.ts Outdated
export type LMoveMOptions = {
/** Move up to `COUNT` elements (fewer if the source has fewer). */
COUNT: number;
ORDER?: LMoveMOrder;

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.

Could we make ORDER required in both option variants and always serialize it? Redis requires the complete <COUNT|EXACTLY> count <OBO|BULK> trailer, so omitting ORDER currently produces a syntax error.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

thanks, fixed

Redis needs the full <COUNT|EXACTLY> count <OBO|BULK> trailer; omitting
ORDER when the block is present is a syntax error. Make ORDER required in
both option variants and always serialize it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@nkaradzhov
nkaradzhov merged commit 5e50331 into redis:master Jul 28, 2026
15 checks passed
@nkaradzhov
nkaradzhov deleted the move-between-lists branch July 28, 2026 18:40
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