Skip to content

feat: add Redis 6.2+ commands (LMOVE, GETDEL, GETEX, ZDIFF, ZINTER, ZUNION) - #299

Merged
kacy merged 6 commits into
mainfrom
feat/redis-62-commands
Feb 25, 2026
Merged

feat: add Redis 6.2+ commands (LMOVE, GETDEL, GETEX, ZDIFF, ZINTER, ZUNION)#299
kacy merged 6 commits into
mainfrom
feat/redis-62-commands

Conversation

@kacy

@kacy kacy commented Feb 25, 2026

Copy link
Copy Markdown
Owner

summary

adds six commands introduced in Redis 6.2 that cover atomic list movement, conditional expiry updates, and set algebra on sorted sets. these are commonly used in real-world caching patterns (e.g. queue rotation with LMOVE, touch-and-expire with GETEX, leaderboard diffing with ZDIFF).

LMOVE source dest LEFT|RIGHT LEFT|RIGHT — atomically pops from one end of a source list and pushes to one end of a destination list. handles the source == destination rotation case without a double-pop.

GETDEL key — returns the string value and removes the key in one operation. useful for one-time-use tokens.

GETEX key [EX s | PX ms | EXAT ts | PXAT ts-ms | PERSIST] — returns the value and optionally updates (or clears) the TTL. extends SetExpire with ExAt and PxAt absolute-timestamp variants, which also fixes the SET command to support those options end-to-end.

ZDIFF / ZINTER / ZUNION numkeys key [key ...] [WITHSCORES] — sorted set algebra. ZDIFF returns members only in the first key; ZINTER returns members present in all keys with scores summed; ZUNION returns all members across all keys with scores summed. all three support the WITHSCORES flag.

all six commands have full AOF persistence for write operations, shard routing, and RESP serialization.

what was tested

  • 17 new unit tests in the keyspace layer covering cross-key moves, same-key rotation, missing/wrong-type keys, atomic delete, TTL persist/clear/set, set difference, intersection with score aggregation, and union across multiple keys
  • full test suite: cargo test -p emberkv-core -p ember-protocol — 524 tests, all passing
  • cargo build -p ember-server succeeds with no warnings

design considerations

GetEx carries expire: Option<Option<u64>> through the shard layer where None = no change, Some(None) = persist, Some(Some(ms)) = new TTL. this three-state encoding avoids separate command variants and keeps the dispatch path clean.

ZDIFF/ZINTER/ZUNION operate on a snapshot of each key taken at dispatch time; no cross-shard fan-out is needed since they accept multiple keys routed by their primary key. for large key sets the caller is expected to co-locate keys on the same shard (standard Redis pattern).

kacy added 6 commits February 25, 2026 10:49
…TER, ZUNION

adds six new keyspace primitives:
- lmove: atomic pop-from-source / push-to-destination for lists
- getdel: get-and-delete string atomically
- getex: get with optional ttl update (set/persist/no-op)
- zdiff: sorted set difference (first key minus all others)
- zinter: sorted set intersection with summed scores
- zunion: sorted set union with summed scores

all methods handle expiry, type-checking, and memory accounting
following existing keyspace conventions.
… ZINTER, ZUNION

extends SetExpire with ExAt(u64) and PxAt(u64) for absolute timestamp
expiry. adds six new Command variants with their attribute methods:
command_name, is_write, acl_categories, and primary_key.
…ZINTER, ZUNION

adds dispatch arms in from_frame and parser functions:
- parse_lmove: validates LEFT/RIGHT direction args
- parse_getdel: single-key, no options
- parse_getex: EX/PX/EXAT/PXAT/PERSIST option parsing
- parse_zset_multi: handles ZDIFF/ZINTER/ZUNION numkeys + WITHSCORES
adds ShardRequest variants (LMove, GetDel, GetEx, ZDiff, ZInter, ZUnion),
dispatch arms in the main shard loop, and AOF records:
- lmove: persisted as lpop + lpush pair
- getdel: persisted as del
- getex: persisted as pexpire or persist depending on option
- zdiff/zinter/zunion: read-only, no aof record needed
adds execute dispatch for LMOVE, GETDEL, GETEX, ZDIFF, ZINTER, ZUNION.
introduces set_expire_to_duration() helper to convert SetExpire to Duration,
handling EX/PX/EXAT/PXAT. fixes non-exhaustive match errors in dispatch.rs
and concurrent_handler.rs from the new ExAt/PxAt SetExpire variants.
…union

covers key behaviors: cross-key moves, same-key rotation, missing source,
wrong-type errors, atomic delete, ttl persist/clear/set, set difference,
intersection with score aggregation, and union across multiple keys.
@kacy
kacy merged commit 639a322 into main Feb 25, 2026
@kacy
kacy deleted the feat/redis-62-commands branch February 25, 2026 15:59
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