|
1 | 1 | package adapter |
2 | 2 |
|
3 | | -// redis_command_info.go holds the static metadata table consumed by the |
4 | | -// Redis `COMMAND` handler. It is intentionally a single, grep-able file so |
5 | | -// that adding a new command is a one-liner: |
6 | | -// |
7 | | -// 1) Register the new handler in RedisServer.route (redis.go). |
8 | | -// 2) Add an argsLen entry (redis.go). |
9 | | -// 3) Add a row below. Forgetting step 3 is NOT fatal — the COMMAND |
10 | | -// handler falls back to a zero-metadata entry and emits one warning |
11 | | -// log per command name so the omission is discoverable — but you |
12 | | -// should do step 3 anyway. |
13 | | -// |
14 | | -// The table is the source of truth for `COMMAND`, `COMMAND INFO`, |
15 | | -// `COMMAND COUNT`, `COMMAND LIST`, `COMMAND DOCS`, and `COMMAND GETKEYS`. |
| 3 | +// redis_command_info.go holds the COMMAND-family helpers. The metadata |
| 4 | +// table itself (redisCommandTable) and the routed-set source of truth |
| 5 | +// (argsLen) both live in adapter/redis_command_specs.go and are derived |
| 6 | +// from the canonical redisCommandSpecs slice — adding a new command is |
| 7 | +// a single row there, with no risk of drifting between r.route / |
| 8 | +// argsLen / redisCommandTable the way HELLO did when it was added to |
| 9 | +// the route + arity check but missed the metadata table. |
16 | 10 | // |
17 | 11 | // Shape notes (Redis reference): |
18 | 12 | // - arity: exact positive arity, or negative meaning "at least |arity|" |
@@ -53,97 +47,6 @@ type redisCommandMeta struct { |
53 | 47 | Step int |
54 | 48 | } |
55 | 49 |
|
56 | | -// redisCommandTable maps UPPERCASE command name -> metadata. Every entry |
57 | | -// routed by RedisServer.route should appear here. Entries are listed in |
58 | | -// alphabetical order to keep diffs small when adding new commands. |
59 | | -// |
60 | | -//nolint:mnd // magic numbers here are literal Redis metadata (arity, key positions) |
61 | | -var redisCommandTable = map[string]redisCommandMeta{ |
62 | | - "BZPOPMIN": {Name: "bzpopmin", Arity: -3, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: -2, Step: 1}, |
63 | | - "CLIENT": {Name: "client", Arity: -2, Flags: []string{redisCmdFlagAdmin}, FirstKey: 0, LastKey: 0, Step: 0}, |
64 | | - "COMMAND": {Name: "command", Arity: -1, Flags: []string{redisCmdFlagAdmin}, FirstKey: 0, LastKey: 0, Step: 0}, |
65 | | - "DBSIZE": {Name: "dbsize", Arity: 1, Flags: []string{redisCmdFlagReadonly}, FirstKey: 0, LastKey: 0, Step: 0}, |
66 | | - "DEL": {Name: "del", Arity: -2, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: -1, Step: 1}, |
67 | | - "DISCARD": {Name: "discard", Arity: 1, Flags: []string{redisCmdFlagAdmin}, FirstKey: 0, LastKey: 0, Step: 0}, |
68 | | - "EVAL": {Name: "eval", Arity: -3, Flags: []string{redisCmdFlagWrite}, FirstKey: 0, LastKey: 0, Step: 0}, |
69 | | - "EVALSHA": {Name: "evalsha", Arity: -3, Flags: []string{redisCmdFlagWrite}, FirstKey: 0, LastKey: 0, Step: 0}, |
70 | | - "EXEC": {Name: "exec", Arity: 1, Flags: []string{redisCmdFlagAdmin}, FirstKey: 0, LastKey: 0, Step: 0}, |
71 | | - "EXISTS": {Name: "exists", Arity: -2, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: -1, Step: 1}, |
72 | | - "EXPIRE": {Name: "expire", Arity: -3, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
73 | | - "FLUSHALL": {Name: "flushall", Arity: 1, Flags: []string{redisCmdFlagWrite}, FirstKey: 0, LastKey: 0, Step: 0}, |
74 | | - "FLUSHDB": {Name: "flushdb", Arity: 1, Flags: []string{redisCmdFlagWrite}, FirstKey: 0, LastKey: 0, Step: 0}, |
75 | | - // FLUSHLEGACY is an elastickv-internal alias; mirror FLUSHDB metadata. |
76 | | - "FLUSHLEGACY": {Name: "flushlegacy", Arity: 1, Flags: []string{redisCmdFlagWrite}, FirstKey: 0, LastKey: 0, Step: 0}, |
77 | | - "GET": {Name: "get", Arity: 2, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
78 | | - "GETDEL": {Name: "getdel", Arity: 2, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
79 | | - "HDEL": {Name: "hdel", Arity: -3, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
80 | | - "HEXISTS": {Name: "hexists", Arity: 3, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
81 | | - "HGET": {Name: "hget", Arity: 3, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
82 | | - "HGETALL": {Name: "hgetall", Arity: 2, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
83 | | - "HINCRBY": {Name: "hincrby", Arity: 4, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
84 | | - "HLEN": {Name: "hlen", Arity: 2, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
85 | | - "HMGET": {Name: "hmget", Arity: -3, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
86 | | - "HMSET": {Name: "hmset", Arity: -4, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
87 | | - "HSET": {Name: "hset", Arity: -4, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
88 | | - "INCR": {Name: "incr", Arity: 2, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
89 | | - "INFO": {Name: "info", Arity: -1, Flags: []string{redisCmdFlagAdmin}, FirstKey: 0, LastKey: 0, Step: 0}, |
90 | | - "KEYS": {Name: "keys", Arity: 2, Flags: []string{redisCmdFlagReadonly}, FirstKey: 0, LastKey: 0, Step: 0}, |
91 | | - "LINDEX": {Name: "lindex", Arity: 3, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
92 | | - "LLEN": {Name: "llen", Arity: 2, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
93 | | - "LPOP": {Name: "lpop", Arity: 2, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
94 | | - "LPOS": {Name: "lpos", Arity: -3, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
95 | | - "LPUSH": {Name: "lpush", Arity: -3, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
96 | | - "LRANGE": {Name: "lrange", Arity: 4, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
97 | | - "LREM": {Name: "lrem", Arity: 4, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
98 | | - "LSET": {Name: "lset", Arity: 4, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
99 | | - "LTRIM": {Name: "ltrim", Arity: 4, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
100 | | - "MULTI": {Name: "multi", Arity: 1, Flags: []string{redisCmdFlagAdmin}, FirstKey: 0, LastKey: 0, Step: 0}, |
101 | | - "PEXPIRE": {Name: "pexpire", Arity: -3, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
102 | | - "PFADD": {Name: "pfadd", Arity: -3, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
103 | | - "PFCOUNT": {Name: "pfcount", Arity: -2, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: -1, Step: 1}, |
104 | | - "PING": {Name: "ping", Arity: -1, Flags: []string{redisCmdFlagAdmin}, FirstKey: 0, LastKey: 0, Step: 0}, |
105 | | - "PTTL": {Name: "pttl", Arity: 2, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
106 | | - "PUBLISH": {Name: "publish", Arity: 3, Flags: []string{redisCmdFlagAdmin}, FirstKey: 0, LastKey: 0, Step: 0}, |
107 | | - "PUBSUB": {Name: "pubsub", Arity: -2, Flags: []string{redisCmdFlagAdmin}, FirstKey: 0, LastKey: 0, Step: 0}, |
108 | | - "QUIT": {Name: "quit", Arity: 1, Flags: []string{redisCmdFlagAdmin}, FirstKey: 0, LastKey: 0, Step: 0}, |
109 | | - "RENAME": {Name: "rename", Arity: 3, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 2, Step: 1}, |
110 | | - "RPOP": {Name: "rpop", Arity: 2, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
111 | | - "RPOPLPUSH": {Name: "rpoplpush", Arity: 3, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 2, Step: 1}, |
112 | | - "RPUSH": {Name: "rpush", Arity: -3, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
113 | | - "SADD": {Name: "sadd", Arity: -3, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
114 | | - "SCAN": {Name: "scan", Arity: -2, Flags: []string{redisCmdFlagReadonly}, FirstKey: 0, LastKey: 0, Step: 0}, |
115 | | - "SCARD": {Name: "scard", Arity: 2, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
116 | | - "SELECT": {Name: "select", Arity: 2, Flags: []string{redisCmdFlagAdmin}, FirstKey: 0, LastKey: 0, Step: 0}, |
117 | | - "SET": {Name: "set", Arity: -3, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
118 | | - "SETEX": {Name: "setex", Arity: 4, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
119 | | - "SETNX": {Name: "setnx", Arity: 3, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
120 | | - "SISMEMBER": {Name: "sismember", Arity: 3, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
121 | | - "SMEMBERS": {Name: "smembers", Arity: 2, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
122 | | - "SREM": {Name: "srem", Arity: -3, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
123 | | - "SUBSCRIBE": {Name: "subscribe", Arity: -2, Flags: []string{redisCmdFlagAdmin}, FirstKey: 0, LastKey: 0, Step: 0}, |
124 | | - "TTL": {Name: "ttl", Arity: 2, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
125 | | - "TYPE": {Name: "type", Arity: 2, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
126 | | - "XADD": {Name: "xadd", Arity: -5, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
127 | | - "XLEN": {Name: "xlen", Arity: 2, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
128 | | - "XRANGE": {Name: "xrange", Arity: -4, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
129 | | - "XREAD": {Name: "xread", Arity: -4, Flags: []string{redisCmdFlagReadonly}, FirstKey: 0, LastKey: 0, Step: 0}, |
130 | | - "XREVRANGE": {Name: "xrevrange", Arity: -4, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
131 | | - "XTRIM": {Name: "xtrim", Arity: -4, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
132 | | - "ZADD": {Name: "zadd", Arity: -4, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
133 | | - "ZCARD": {Name: "zcard", Arity: 2, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
134 | | - "ZCOUNT": {Name: "zcount", Arity: 4, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
135 | | - "ZINCRBY": {Name: "zincrby", Arity: 4, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
136 | | - "ZPOPMIN": {Name: "zpopmin", Arity: -2, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
137 | | - "ZRANGE": {Name: "zrange", Arity: -4, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
138 | | - "ZRANGEBYSCORE": {Name: "zrangebyscore", Arity: -4, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
139 | | - "ZREM": {Name: "zrem", Arity: -3, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
140 | | - "ZREMRANGEBYRANK": {Name: "zremrangebyrank", Arity: 4, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
141 | | - "ZREMRANGEBYSCORE": {Name: "zremrangebyscore", Arity: 4, Flags: []string{redisCmdFlagWrite}, FirstKey: 1, LastKey: 1, Step: 1}, |
142 | | - "ZREVRANGE": {Name: "zrevrange", Arity: -4, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
143 | | - "ZREVRANGEBYSCORE": {Name: "zrevrangebyscore", Arity: -4, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
144 | | - "ZSCORE": {Name: "zscore", Arity: 3, Flags: []string{redisCmdFlagReadonly}, FirstKey: 1, LastKey: 1, Step: 1}, |
145 | | -} |
146 | | - |
147 | 50 | // redisCommandFallbackWarnedOnce deduplicates the "missing metadata" log so |
148 | 51 | // that a hostile or buggy client probing the same unknown-but-routed name |
149 | 52 | // cannot generate unbounded log spam. The fallback is a safety net for |
|
0 commit comments