Skip to content

feat(client): close gRPC API gap — 31 new commands + pub/sub subscriber + vector commands - #304

Merged
kacy merged 6 commits into
mainfrom
feat/client-api-parity
Feb 25, 2026
Merged

feat(client): close gRPC API gap — 31 new commands + pub/sub subscriber + vector commands#304
kacy merged 6 commits into
mainfrom
feat/client-api-parity

Conversation

@kacy

@kacy kacy commented Feb 25, 2026

Copy link
Copy Markdown
Owner

summary

closes the gap between the typed rust client (ember-client) and the server's full command set. before this PR the client exposed 34 commands; afterwards it covers every server-side command except the cluster and migrate commands (which are routing-layer concerns, not application-layer).

PR A — mechanical command additions (3 commits for context; shipped as one PR)

  • 5 new decoders: string_value, float_value, scan_page, slowlog_entries, numsub_pairs
  • 2 new public types: ScanPage, SlowlogEntry
  • 23 new Client methods across strings, keys, hashes, server, slowlog, and pub/sub
  • matching Pipeline builder methods for all new commands

PR B — pub/sub subscriber mode

  • Subscriber type + Message type
  • Client::subscribe and Client::psubscribe consume the connection and return a Subscriber
  • Subscriber::recv waits for the next pushed message, skipping confirmation frames
  • Subscriber::subscribe adds channels without leaving sub mode
  • Subscriber::unsubscribe removes channels and returns the Client for reuse

PR C — vector commands (vector feature flag)

  • feature-gated vector module with SimResult type
  • vadd, vadd_batch, vsim, vrem, vget, vcard, vdim, vinfo
  • vsim always uses WITHSCORES for a consistent return type

what was tested

  • cargo build -p ember-client (default features, no warnings)
  • cargo build -p ember-client --features vector (no warnings)
  • cargo clippy -p ember-client --features vector -- -D warnings (clean)
  • cargo test -p ember-client --features vector (21 unit + 5 doc tests, all pass)
  • cargo build --test integration (no warnings on integration test crate)
  • cargo fmt --all --check (clean)

design notes

  • Subscriber wraps the Client directly rather than owning a raw transport. this keeps TLS support automatic — any Client (TCP or TLS) can become a Subscriber
  • read_response() is now pub(crate) and write_frame() was added so Subscriber can drive the connection without going through send_frame's request-response coupling
  • vector floats are encoded as decimal strings, consistent with how the server decodes them (same as ZSCORE/ZADD)
  • vadd_batch uses DIM text mode (not binary blob mode) to keep the API platform-independent

kacy added 6 commits February 25, 2026 12:39
adds a full typed command API and pipeline builder on top of the existing
raw `send()` method. no new crate — the types layer cleanly on what's there.

commands covered: get/set/set_ex/del/exists/expire/persist/ttl/pttl/
incr/decr/incrby/decrby/append/mget/mset/getdel (strings), lpush/rpush/
lpop/rpop/lrange/llen (lists), hset/hget/hgetall/hdel/hexists/hlen/hkeys/
hvals (hashes), sadd/srem/smembers/sismember/scard (sets), zadd/zrange/
zrange_withscores/zscore/zrank/zrem/zcard (sorted sets), ping/dbsize/flushdb.

`Pipeline` is a chainable builder that writes all frames in a single
syscall and reads responses sequentially, keeping pipelining cost to one
flush per batch.

`ClientError::Server` is new — server-returned errors (`WRONGTYPE`, etc.)
are now distinct from wire-level `Protocol` errors.
closes the gap between the typed rust client and the server's full
command set. mechanical additions, all following existing patterns.

new decoders:
- string_value: simple/bulk → String (TYPE, INFO, ECHO, BGSAVE)
- float_value: bulk float string → f64 (INCRBYFLOAT)
- scan_page: Array([cursor, [keys]]) → ScanPage (SCAN)
- slowlog_entries: Array of entry arrays → Vec<SlowlogEntry> (SLOWLOG GET)
- numsub_pairs: interleaved ch/count array → Vec<(Bytes, i64)> (PUBSUB NUMSUB)

new public types: ScanPage, SlowlogEntry (re-exported from lib.rs)

new Client methods:
- strlen, incr_by_float
- key_type, keys, rename, scan, pexpire
- hmget
- echo, unlink, info, bgsave, bgrewriteaof
- slowlog_get, slowlog_len, slowlog_reset
- publish, pubsub_channels, pubsub_numsub, pubsub_numpat

new Pipeline builder methods for all new commands

integration tests covering all new commands
adds a dedicated subscriber connection type that wraps a Client once it
enters pub/sub mode.  regular request-response commands cannot be issued
on the same connection while subscribed — callers use a separate Client.

new types: Subscriber, Message (re-exported from lib.rs)

new Client methods:
- subscribe(channels) → Subscriber
- psubscribe(patterns) → Subscriber

Subscriber methods:
- recv() — waits for the next message, skips confirmation frames
- subscribe(channels) — add more channels without leaving sub mode
- unsubscribe(channels) → Client — remove channels and reclaim connection

connection.rs: added write_frame() and pub(crate) read_response() so
Subscriber can drive the connection directly

integration tests: subscriber_recv_message, subscriber_multiple_channels,
psubscriber_pattern_match
adds VADD, VADD_BATCH, VSIM, VREM, VGET, VCARD, VDIM, VINFO to the
typed client API, gated behind the new 'vector' cargo feature.

new public type: SimResult { element: Bytes, distance: f32 }

new Client methods (cfg(feature = "vector")):
- vadd(key, element, vector) → bool
- vadd_batch(key, dim, entries) → i64
- vsim(key, query, count) → Vec<SimResult>   (always WITHSCORES)
- vrem(key, element) → bool
- vget(key, element) → Option<Vec<f32>>
- vcard(key) → i64
- vdim(key) → i64
- vinfo(key) → Vec<(Bytes, Bytes)>

floats are encoded as decimal strings in RESP3, matching the server's
wire format. VADD_BATCH uses the text mode (DIM n then element floats);
binary blob mode is not exposed since it's a platform-specific concern.
@kacy
kacy merged commit 34dbc25 into main Feb 25, 2026
4 of 7 checks passed
@kacy
kacy deleted the feat/client-api-parity branch February 25, 2026 18:03
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