diff options
author | chendianqiang <c.d_q@163.com> | 2022-09-05 21:59:14 +0800 |
---|---|---|
committer | Oran Agra <oran@redislabs.com> | 2022-09-21 22:42:01 +0300 |
commit | 8c702f8ddbcdc8f92728415422c2d986871c0782 (patch) | |
tree | 6cdbca1843095bd888a3752eb2b0a528295c0d6d | |
parent | 63db10ef6f27e915683698ff7d90ea5006a33ed1 (diff) | |
download | redis-8c702f8ddbcdc8f92728415422c2d986871c0782.tar.gz |
Correctly handle scripts with shebang (not read-only) on a cluster replica (#11223)
EVAL scripts are by default not considered `write` commands, so they were allowed on a replica.
But when adding a shebang, they become `write` command (unless the `no-writes` flag is added).
With this change we'll handle them as write commands, and reply with MOVED instead of
READONLY when executed on a redis cluster replica.
Co-authored-by: chendianqiang <chendianqiang@meituan.com>
(cherry picked from commit e42d98ed27364a100d0ba5cb1340bcd7fbcca710)
-rw-r--r-- | src/cluster.c | 7 | ||||
-rw-r--r-- | tests/cluster/tests/16-transactions-on-replica.tcl | 8 |
2 files changed, 12 insertions, 3 deletions
diff --git a/src/cluster.c b/src/cluster.c index 54e58e28b..7cd36c890 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -6716,6 +6716,7 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in * without redirections or errors in all the cases. */ if (n == NULL) return myself; + uint64_t cmd_flags = getCommandFlags(c); /* Cluster is globally down but we got keys? We only serve the request * if it is a read command and when allow_reads_when_down is enabled. */ if (server.cluster->state != CLUSTER_OK) { @@ -6729,7 +6730,7 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in * cluster is down. */ if (error_code) *error_code = CLUSTER_REDIR_DOWN_STATE; return NULL; - } else if (cmd->flags & CMD_WRITE) { + } else if (cmd_flags & CMD_WRITE) { /* The cluster is configured to allow read only commands */ if (error_code) *error_code = CLUSTER_REDIR_DOWN_RO_STATE; return NULL; @@ -6767,7 +6768,7 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in * involves multiple keys and we don't have them all, the only option is * to send a TRYAGAIN error. */ if (importing_slot && - (c->flags & CLIENT_ASKING || cmd->flags & CMD_ASKING)) + (c->flags & CLIENT_ASKING || cmd_flags & CMD_ASKING)) { if (multiple_keys && missing_keys) { if (error_code) *error_code = CLUSTER_REDIR_UNSTABLE; @@ -6780,7 +6781,7 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in /* Handle the read-only client case reading from a slave: if this * node is a slave and the request is about a hash slot our master * is serving, we can reply without redirection. */ - int is_write_command = (c->cmd->flags & CMD_WRITE) || + int is_write_command = (cmd_flags & CMD_WRITE) || (c->cmd->proc == execCommand && (c->mstate.cmd_flags & CMD_WRITE)); if (((c->flags & CLIENT_READONLY) || is_pubsubshard) && !is_write_command && diff --git a/tests/cluster/tests/16-transactions-on-replica.tcl b/tests/cluster/tests/16-transactions-on-replica.tcl index ee9f7c6e6..ec5699c98 100644 --- a/tests/cluster/tests/16-transactions-on-replica.tcl +++ b/tests/cluster/tests/16-transactions-on-replica.tcl @@ -69,3 +69,11 @@ test "read-only blocking operations from replica" { assert {$res eq {foo bar}} $rd close } + +test "reply MOVED when eval from replica for update" { + catch {[$replica eval {#!lua + return redis.call('del','a') + } 1 a + ]} err + assert {[string range $err 0 4] eq {MOVED}} +}
\ No newline at end of file |