Commit e055e98
authored
feat(redis): implement COMMAND (INFO / COUNT / LIST / DOCS / GETKEYS) (#607)
## Motivation
`COMMAND` is issued at connect time by ~every modern Redis client
(go-redis, redis-py >= 4, ioredis, node-redis) for capability probing
and key-routing inference. elastickv previously rejected it as
`unsupported command`, inflating the "unknown" error bucket and
breaking client initialization in strict libraries that actually
consult `COMMAND INFO` output.
Companion to #594 (bounded unsupported-command metric) and #601
(`HELLO`). After this + `HELLO` land, those two commands should cover
>95% of the previously-"unknown" error traffic.
## Subcommand matrix
Implemented:
- `COMMAND` — flat array of per-command info (6-element shape)
- `COMMAND COUNT` — integer count of routed commands
- `COMMAND LIST` — flat array of command names
- `COMMAND INFO [name ...]` — per-command info array, `nil` per unknown
- `COMMAND DOCS [name ...]` — minimal map-shaped doc entry per command
- `COMMAND GETKEYS <command> <args>` — positional key extraction via
per-command first_key/last_key/step
Explicitly rejected (returns `ERR unsupported`):
- `COMMAND GETKEYSANDFLAGS` — Redis 7 key-specs shape we do not emit
- `COMMAND LIST FILTERBY MODULE|ACLCAT|PATTERN` — elastickv has no
modules and no ACL categories
## Metadata table
Single source of truth: `adapter/redis_command_info.go`. One row per
routed command holding `(arity, flags, first_key, last_key, step)`.
Adding a new command handler now takes three steps:
1. Register the handler in `RedisServer.route` (`adapter/redis.go`).
2. Add an `argsLen` entry (`adapter/redis.go`).
3. Add a row to `redisCommandTable` in `redis_command_info.go`.
Forgetting step 3 is caught at CI time by
`TestCommand_RouteMatchesTable`. In production the runtime falls
through to a zero-metadata row and emits a single deduplicated log
warning per missing command name, so the command still appears in
`COMMAND` output (degraded) rather than vanishing entirely.
Flags follow a three-value taxonomy: `readonly` / `write` / `admin`.
`denyoom` / `pubsub` / `stale` etc. are intentionally not emitted —
no real client consults them for routing decisions.
Wire count, LIST length, and the bare-`COMMAND` reply are driven off
`argsLen` (the 1:1 route-keyed set) rather than the table, so the
three subcommands stay mutually consistent even during the brief
window when a new route has been added but the table row is pending.
## Test plan
- [x] `COMMAND COUNT` returns `len(argsLen)` and equals
`len(redisCommandTable)`
- [x] `COMMAND` (no args) returns an array of that length
- [x] `COMMAND INFO GET` — name/arity/flags/positions match spec
- [x] `COMMAND INFO SET` — arity=-3, flags contain "write"
- [x] `COMMAND INFO nosuchcommand` — nil entry, not an error
- [x] `COMMAND INFO GET NOSUCH SET` — 3 entries, middle is nil
- [x] `COMMAND GETKEYS SET foo bar` → `["foo"]`
- [x] `COMMAND GETKEYS DEL k1 k2 k3` → `["k1","k2","k3"]`
- [x] `redisCommandGetKeys` MSET-shape helper test (step=2)
- [x] `COMMAND GETKEYS NOSUCH` → error
- [x] `COMMAND LIST` — sorted names, length = count
- [x] `COMMAND LIST FILTERBY MODULE foo` — rejected
- [x] `COMMAND DOCS GET` — 4-element map-shaped entry
- [x] `COMMAND BADSUB` — "Unknown COMMAND subcommand"
- [x] `COMMAND GETKEYSANDFLAGS` — rejected
- [x] Route-wiring test confirms `COMMAND` dispatches to the handler
- [x] `TestCommand_RouteMatchesTable` — invariant that every routed
command has a metadata row
- [x] `golangci-lint run ./adapter/... ./monitoring/...` is clean
- [x] `go test -race -run 'TestCommand|TestRedisCommand' ./adapter/...
./monitoring/...` passes6 files changed
Lines changed: 1102 additions & 169 deletions
File tree
- adapter
- monitoring
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
33 | 34 | | |
34 | 35 | | |
35 | 36 | | |
| |||
164 | 165 | | |
165 | 166 | | |
166 | 167 | | |
167 | | - | |
168 | | - | |
169 | | - | |
170 | | - | |
171 | | - | |
172 | | - | |
173 | | - | |
174 | | - | |
175 | | - | |
176 | | - | |
177 | | - | |
178 | | - | |
179 | | - | |
180 | | - | |
181 | | - | |
182 | | - | |
183 | | - | |
184 | | - | |
185 | | - | |
186 | | - | |
187 | | - | |
188 | | - | |
189 | | - | |
190 | | - | |
191 | | - | |
192 | | - | |
193 | | - | |
194 | | - | |
195 | | - | |
196 | | - | |
197 | | - | |
198 | | - | |
199 | | - | |
200 | | - | |
201 | | - | |
202 | | - | |
203 | | - | |
204 | | - | |
205 | | - | |
206 | | - | |
207 | | - | |
208 | | - | |
209 | | - | |
210 | | - | |
211 | | - | |
212 | | - | |
213 | | - | |
214 | | - | |
215 | | - | |
216 | | - | |
217 | | - | |
218 | | - | |
219 | | - | |
220 | | - | |
221 | | - | |
222 | | - | |
223 | | - | |
224 | | - | |
225 | | - | |
226 | | - | |
227 | | - | |
228 | | - | |
229 | | - | |
230 | | - | |
231 | | - | |
232 | | - | |
233 | | - | |
234 | | - | |
235 | | - | |
236 | | - | |
237 | | - | |
238 | | - | |
239 | | - | |
240 | | - | |
241 | | - | |
242 | | - | |
243 | | - | |
244 | | - | |
245 | | - | |
246 | | - | |
247 | | - | |
248 | | - | |
249 | | - | |
250 | | - | |
251 | | - | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
252 | 171 | | |
253 | 172 | | |
254 | 173 | | |
| |||
432 | 351 | | |
433 | 352 | | |
434 | 353 | | |
435 | | - | |
436 | | - | |
437 | | - | |
438 | | - | |
439 | | - | |
440 | | - | |
441 | | - | |
442 | | - | |
443 | | - | |
444 | | - | |
445 | | - | |
446 | | - | |
447 | | - | |
448 | | - | |
449 | | - | |
450 | | - | |
451 | | - | |
452 | | - | |
453 | | - | |
454 | | - | |
455 | | - | |
456 | | - | |
457 | | - | |
458 | | - | |
459 | | - | |
460 | | - | |
461 | | - | |
462 | | - | |
463 | | - | |
464 | | - | |
465 | | - | |
466 | | - | |
467 | | - | |
468 | | - | |
469 | | - | |
470 | | - | |
471 | | - | |
472 | | - | |
473 | | - | |
474 | | - | |
475 | | - | |
476 | | - | |
477 | | - | |
478 | | - | |
479 | | - | |
480 | | - | |
481 | | - | |
482 | | - | |
483 | | - | |
484 | | - | |
485 | | - | |
486 | | - | |
487 | | - | |
488 | | - | |
489 | | - | |
490 | | - | |
491 | | - | |
492 | | - | |
493 | | - | |
494 | | - | |
495 | | - | |
496 | | - | |
497 | | - | |
498 | | - | |
499 | | - | |
500 | | - | |
501 | | - | |
502 | | - | |
503 | | - | |
504 | | - | |
505 | | - | |
506 | | - | |
507 | | - | |
508 | | - | |
509 | | - | |
510 | | - | |
511 | | - | |
512 | | - | |
513 | | - | |
514 | | - | |
515 | | - | |
516 | | - | |
517 | | - | |
518 | | - | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
519 | 359 | | |
520 | 360 | | |
521 | 361 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
0 commit comments