diff --git a/src/cluster.c b/src/cluster.c index 4024035e9..a18543e0b 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -5476,8 +5476,8 @@ void readwriteCommand(client *c) { * already "down" but it is fragile to rely on the update of the global state, * so we also handle it here. * - * CLUSTER_REDIR_DOWN_STATE if the cluster is down but the user attempts to - * execute a command that addresses one or more keys. */ + * CLUSTER_REDIR_DOWN_STATE and CLUSTER_REDIR_DOWN_RO_STATE if the cluster is + * down but the user attempts to execute a command that addresses one or more keys. */ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, int argc, int *hashslot, int *error_code) { clusterNode *n = NULL; robj *firstkey = NULL; @@ -5597,12 +5597,17 @@ clusterNode *getNodeByQuery(client *c, struct redisCommand *cmd, robj **argv, in /* 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) && - !(server.cluster_allow_reads_when_down && ((cmd->flags & CMD_READONLY) - || (cmd->proc == evalCommand) || (cmd->proc == evalShaCommand)))) - { - if (error_code) *error_code = CLUSTER_REDIR_DOWN_STATE; - return NULL; + if (server.cluster->state != CLUSTER_OK) { + if (!server.cluster_allow_reads_when_down) { + if (error_code) *error_code = CLUSTER_REDIR_DOWN_STATE; + return NULL; + } + + if (!(cmd->flags & CMD_READONLY) && !(cmd->proc == evalCommand) + && !(cmd->proc == evalShaCommand)) { + if (error_code) *error_code = CLUSTER_REDIR_DOWN_RO_STATE; + return NULL; + } } /* Return the hashslot by reference. */ @@ -5671,6 +5676,8 @@ void clusterRedirectClient(client *c, clusterNode *n, int hashslot, int error_co addReplySds(c,sdsnew("-TRYAGAIN Multiple keys request during rehashing of slot\r\n")); } else if (error_code == CLUSTER_REDIR_DOWN_STATE) { addReplySds(c,sdsnew("-CLUSTERDOWN The cluster is down\r\n")); + } else if (error_code == CLUSTER_REDIR_DOWN_RO_STATE) { + addReplySds(c,sdsnew("-CLUSTERDOWN The cluster is down and only accepts read commands\r\n")); } else if (error_code == CLUSTER_REDIR_DOWN_UNBOUND) { addReplySds(c,sdsnew("-CLUSTERDOWN Hash slot not served\r\n")); } else if (error_code == CLUSTER_REDIR_MOVED || diff --git a/src/cluster.h b/src/cluster.h index 3ba60df6e..35fc0cbfa 100644 --- a/src/cluster.h +++ b/src/cluster.h @@ -29,6 +29,7 @@ #define CLUSTER_REDIR_MOVED 4 /* -MOVED redirection required. */ #define CLUSTER_REDIR_DOWN_STATE 5 /* -CLUSTERDOWN, global state. */ #define CLUSTER_REDIR_DOWN_UNBOUND 6 /* -CLUSTERDOWN, unbound slot. */ +#define CLUSTER_REDIR_DOWN_RO_STATE 7 /* -CLUSTERDOWN, allow reads. */ struct clusterNode; diff --git a/src/module.c b/src/module.c index 31d337b14..a4e7cbe2c 100644 --- a/src/module.c +++ b/src/module.c @@ -3176,6 +3176,7 @@ fmterr: * EPERM: operation in Cluster instance with key in non local slot. * EROFS: operation in Cluster instance when a write command is sent * in a readonly state. + * ENETDOWN: operation in Cluster instance when cluster is down. * * This API is documented here: https://redis.io/topics/modules-intro */ @@ -3240,8 +3241,10 @@ RedisModuleCallReply *RM_Call(RedisModuleCtx *ctx, const char *cmdname, const ch if (getNodeByQuery(c,c->cmd,c->argv,c->argc,NULL,&error_code) != server.cluster->myself) { - if (error_code == CLUSTER_REDIR_DOWN_STATE) { + if (error_code == CLUSTER_REDIR_DOWN_RO_STATE) { errno = EROFS; + } else if (error_code == CLUSTER_REDIR_DOWN_STATE) { + errno = ENETDOWN; } else { errno = EPERM; } diff --git a/src/scripting.c b/src/scripting.c index c627207d5..96eb9681d 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -686,11 +686,15 @@ int luaRedisGenericCommand(lua_State *lua, int raise_error) { if (getNodeByQuery(c,c->cmd,c->argv,c->argc,NULL,&error_code) != server.cluster->myself) { - if (error_code == CLUSTER_REDIR_DOWN_STATE) { + if (error_code == CLUSTER_REDIR_DOWN_RO_STATE) { luaPushError(lua, - "Lua script attempted execute a write command while " + "Lua script attempted to execute a write command while the" + "cluster is down and readonly"); + } else if (error_code == CLUSTER_REDIR_DOWN_STATE) { + luaPushError(lua, + "Lua script attempted to execute a command while the" "cluster is down"); - } else { + } else {} luaPushError(lua, "Lua script attempted to access a non local key in a " "cluster node");