diff --git a/src/cluster.c b/src/cluster.c index 80cd770188024fbcfc1269bfc18b42efc760b8b0..178ce9b750440655dcf19dff3889c12fbfda9e0d 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -4690,7 +4690,12 @@ void readwriteCommand(redisClient *c) { * * REDIS_CLUSTER_REDIR_UNSTABLE if the request contains mutliple keys * belonging to the same slot, but the slot is not stable (in migration or - * importing state, likely because a resharding is in progress). */ + * importing state, likely because a resharding is in progress). + * + * REDIS_CLUSTER_REDIR_DOWN if the request addresses a slot which is not + * bound to any node. In this case the cluster global state should be already + * "down" but it is fragile to rely on the update of the global state, so + * we also handle it here. */ clusterNode *getNodeByQuery(redisClient *c, struct redisCommand *cmd, robj **argv, int argc, int *hashslot, int *error_code) { clusterNode *n = NULL; robj *firstkey = NULL; @@ -4744,7 +4749,18 @@ clusterNode *getNodeByQuery(redisClient *c, struct redisCommand *cmd, robj **arg firstkey = thiskey; slot = thisslot; n = server.cluster->slots[slot]; - redisAssertWithInfo(c,firstkey,n != NULL); + + /* Error: If a slot is not served, we are in "cluster down" + * state. However the state is yet to be updated, so this was + * not trapped earlier in processCommand(). Report the same + * error to the client. */ + if (n == NULL) { + getKeysFreeResult(keyindex); + if (error_code) + *error_code = REDIS_CLUSTER_REDIR_DOWN; + return NULL; + } + /* If we are migrating or importing this slot, we need to check * if we have all the keys in the request (the only way we * can safely serve the request, otherwise we return a TRYAGAIN diff --git a/src/cluster.h b/src/cluster.h index ef5caf0d6e6544e9530fef120b9af7a4025aa807..8eaa0ab9816a8e693369cf13abe092733eea3bd3 100644 --- a/src/cluster.h +++ b/src/cluster.h @@ -30,6 +30,7 @@ #define REDIS_CLUSTER_REDIR_UNSTABLE 2 /* Keys in slot resharding. */ #define REDIS_CLUSTER_REDIR_ASK 3 /* -ASK redirection required. */ #define REDIS_CLUSTER_REDIR_MOVED 4 /* -MOVED redirection required. */ +#define REDIS_CLUSTER_REDIR_DOWN 5 /* -CLUSTERDOWN error. */ struct clusterNode; diff --git a/src/redis.c b/src/redis.c index 3ffc62d0293d17b876f3b6d24f9676674d7c529b..918cae1e730e7f747dcc765ba06ead99559a8636 100644 --- a/src/redis.c +++ b/src/redis.c @@ -2178,6 +2178,8 @@ int processCommand(redisClient *c) { * but the slot is not "stable" currently as there is * a migration or import in progress. */ addReplySds(c,sdsnew("-TRYAGAIN Multiple keys request during rehashing of slot\r\n")); + } else if (error_code == REDIS_CLUSTER_REDIR_DOWN) { + addReplySds(c,sdsnew("-CLUSTERDOWN The cluster is down. Hash slot is unbound\r\n")); } else { redisPanic("getNodeByQuery() unknown error."); }