The 98-test integration suite runs against each backend, in every mode
combination (backend-sharding, reply-cache), with full cluster
teardown/recreate between versions; it includes a live slot migration
(CLUSTER SETSLOT MIGRATING/IMPORTING + MIGRATE) under multi-key commands
and, on Redis 8.4+ and Valkey 9, an atomic slot migration (CLUSTER
MIGRATION IMPORT / CLUSTER MIGRATESLOTS) moved back and forth under a
single-key write stream, which must see no error and lose no increment:
| backend | server version | result |
|---|---|---|
| redis:6.2 | 6.2.24 | pass |
| redis:7.4 | 7.4.11 | pass |
| redis:8.2 | 8.2.9 | pass |
| redis:8.10 | 8.10.1 | pass |
| valkey/valkey:9.1 | 9.1.2 | pass |
| redis-stable (source) | 8.10.1 | pass |
Clients verified: redis-py (cluster and standalone mode), redis-cli, memtier_benchmark, redis-benchmark.
+@all -@dangerous removes ACL SETUSER and CONFIG SET; +cmd|sub
and -cmd|sub both work). Not supported: selectors, ACL LOAD/SAVE (no
ACL file), the sanitize-payload flags, and CONFIG SET requirepass
at runtime. ACL GETUSER and ACL LOG use the Redis 6.2 reply shapes;
GETUSER renders command rules in canonical form (-@all +@cat...
+cmd... +cmd|sub).cluster-databases) binds the session to connections
that selected that database; the reply cache serves database 0 only, and
SWAPDB and MOVE across databases are the servers’ own affair per node.loglevel, acl-pubsub-default, acllog-max-len
and the two slowlog-* keys; CONFIG SET rejects every other parameter.NOSCRIPT covers scripts the proxy loaded itself,
redirected or not, and only while nothing later from the same session is
in flight (a pipelined EVALSHA gets the NOSCRIPT and the client’s own
EVAL fallback applies). FUNCTION
commands reach the masters that own slots; a node needs its libraries
loaded before slots move to it, as with any client.TRYAGAIN is retried whole once the handoff settles (2 ms, doubling,
up to six waits), so under an atomic migration it stays atomic; only a
legacy migration whose keys really sit on two nodes still executes it as
independent single-key commands, which a concurrent reader can observe
half applied. A redirect that outlasts the waits ends it with TRYAGAIN.READONLY; the proxy then refreshes the
topology and resends it to the new master of that shard only, up to six
times with short waits, and only a refresh slower than that leaves the
client the READONLY. The session waits for the outcome before it runs
the client’s next command.The mt-proxy functional suite exercises a proxy-specific surface that mithril does not reproduce; each returns unknown-command or an unsupported CONFIG parameter, never a silent approximation:
local_cache_* INFO fields (the reply cache is reply-cache yes,
reported as cache_*);redis-user / redis-pass: backend credentials come from the
config file (backend-auth-user, backend-auth-pass);worker-threads, proxy-redis-conn, proxy-slave-mode,
readonly, protected-mode, maxclients, requirepass, timeout,
tcp-backlog, tcp-keepalive, client-query-buffer-limit at runtime;