Skip to content

feat: add PROTO.SCAN and PROTO.FIND commands#341

Merged
kacy merged 1 commit intomainfrom
worktree-linear-scribbling-lark
Feb 28, 2026
Merged

feat: add PROTO.SCAN and PROTO.FIND commands#341
kacy merged 1 commit intomainfrom
worktree-linear-scribbling-lark

Conversation

@kacy
Copy link
Owner

@kacy kacy commented Feb 28, 2026

Summary

Adds two new commands for protobuf key discovery, closing the major usability gap where finding proto keys by type or field value required a full SCAN + per-key PROTO.GETFIELD loop client-side.

PROTO.SCAN cursor [MATCH pattern] [COUNT count] [TYPE typename]

Cursor-based scan over all proto keys. Optional TYPE filter narrows results to keys holding a specific message type. Same cursor encoding as SCAN (shard_id << 48 | position) for consistent multi-shard iteration.

PROTO.FIND cursor field-path value [MATCH pattern] [TYPE typename] [COUNT count]

Cursor-based scan returning proto keys where the given field matches the given value. Dot-separated paths (address.city) traverse nested messages via the existing resolve_field_path logic. Field comparison uses string representation: booleans as "true"/"false", integers/floats as decimal strings, strings verbatim. Non-scalar fields (repeated, map, nested message) are silently skipped.

PROTO.SCAN 0
PROTO.SCAN 0 MATCH user:* COUNT 50
PROTO.SCAN 0 TYPE profiles.v1.UserProfile

PROTO.FIND 0 active true TYPE profiles.v1.UserProfile
PROTO.FIND 0 address.city Seattle MATCH user:* COUNT 20
PROTO.FIND 0 score 100 TYPE leaderboard.v1.Entry

What was tested

  • 9 new integration tests in tests/integration/src/proto.rs:
    • proto_scan_all_keys — full iteration across pages returns all proto keys, excludes non-proto
    • proto_scan_type_filter — TYPE argument excludes keys of different message types
    • proto_scan_match_pattern — MATCH glob filters by key name
    • proto_scan_cursor_consistency — keys added mid-scan don't cause panics or crashes
    • proto_find_scalar_match — bool, int, and string field matching
    • proto_find_nested_path — dot-separated path (address.city) traversal
    • proto_find_type_filter — TYPE + field combo; skips keys of wrong type without error
    • proto_find_no_match — returns [0, []] when nothing matches
    • proto_find_count_pagination — multiple pages aggregate to the full match set

Both commands implemented in sharded and concurrent server modes. Concurrent mode routes to shards (proto values live in shards, not DashMap) using the same multi-shard cursor fan-out.

Design considerations

get_field_str() was added to SchemaRegistry alongside the existing get_field() to avoid stringifying Frame values outside the schema layer. The two comparison targets diverge on booleans: get_field() returns Frame::Integer(0/1) for RESP3 compatibility, while get_field_str() returns "true"/"false" so PROTO.FIND 0 active true works naturally.

Non-scalar field paths are silently skipped rather than returning an error — this keeps scan behavior consistent (a bad path on one key doesn't abort the whole scan).

adds two new commands for protobuf key discovery:

- PROTO.SCAN cursor [MATCH pattern] [COUNT count] [TYPE typename]
  cursor-based scan over all proto keys; optional type filter narrows
  results to keys holding a specific message type; same cursor encoding
  (shard_id << 48 | position) as SCAN

- PROTO.FIND cursor field_path value [MATCH pattern] [TYPE typename] [COUNT count]
  cursor-based scan that returns proto keys where the given field equals
  the given value; dot-separated paths for nested messages; booleans
  compared as "true"/"false", integers and floats as decimal strings

implementation touches:
- ember-protocol: Command::ProtoScan, Command::ProtoFind + parsers + attributes
- ember-core: scan_proto_keys() on Keyspace, scan_proto_find() on Keyspace,
  get_field_str() on SchemaRegistry for comparison, ShardRequest/Response variants
- ember-server: proto_scan/find handlers in exec/protobuf.rs, dispatch arms in
  execute.rs and concurrent_handler.rs
- integration tests: 9 new tests covering full iteration, type filter, pattern
  matching, cursor stability, field matching, nested paths, and pagination
@kacy kacy merged commit cdb8c61 into main Feb 28, 2026
7 of 8 checks passed
@kacy kacy deleted the worktree-linear-scribbling-lark branch February 28, 2026 14:41
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