From a65301bc2e9b678896675584e3a8e3219aa221f7 Mon Sep 17 00:00:00 2001 From: michael-grunder Date: Wed, 16 Jul 2014 16:57:25 -0700 Subject: Update redirection logic to throw on CLUSTERDOWN When Redis Cluster responds with a CLUSTERDOWN error, we should throw an exception. It seems that in the current state of cluster (during slave election), it will enter a CLUSTERDOWN state for a short period of time. This allows clients to trap the exception and then either wait and try again, or do something else. --- cluster_library.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'cluster_library.c') diff --git a/cluster_library.c b/cluster_library.c index 16f02d0f..155f026b 100644 --- a/cluster_library.c +++ b/cluster_library.c @@ -372,6 +372,13 @@ void cluster_multi_fini(clusterMultiCmd *mc) { static void cluster_set_err(redisCluster *c, char *err, int err_len) { if(err && err_len>0) { + if(err_len >= sizeof("CLUSTERDOWN")-1 && + !memcmp(err, "CLUSTERDOWN", sizeof("CLUSTERDOWN")-1)) + { + c->clusterdown = 1; + return; + } + if(c->err == NULL) { c->err = emalloc(err_len+1); } else if(err_len > c->err_len) { @@ -380,8 +387,6 @@ static void cluster_set_err(redisCluster *c, char *err, int err_len) memcpy(c->err,err,err_len); c->err[err_len]='\0'; c->err_len = err_len; -php_printf("Set error to: %s\n", c->err); - } else { if(c->err) efree(c->err); c->err = NULL; @@ -1280,13 +1285,8 @@ PHPAPI short cluster_send_command(redisCluster *c, short slot, const char *cmd, // Check the response from the slot we ended up querying. resp = cluster_check_response(c, slot, &c->reply_type TSRMLS_CC); - // If we're getting an error condition, impose a slight delay before - // we try again (e.g. server went down, election in process). If the - // data has been moved, update node configuration, and if ASK has been - // encountered, we'll just try again at that slot. - if(resp == -1) { - sleep(1); - } else if(resp == 1) { + /* Handle MOVED or ASKING redirection */ + if(resp == 1) { // If we get a MOVED response inside of a transaction, we have to // abort, because the transaction would be invalid. if(c->flags->mode == MULTI) { @@ -1302,7 +1302,14 @@ PHPAPI short cluster_send_command(redisCluster *c, short slot, const char *cmd, } slot = c->redir_slot; } - } while(resp != 0); + } while(resp != 0 && !c->clusterdown); + + // If we've detected the cluster is down, throw an exception + if(c->clusterdown) { + zend_throw_exception(redis_cluster_exception_ce, + "The Redis Cluster is down (CLUSTERDOWN)", 0 TSRMLS_CC); + return -1; + } // Inform the cluster where to read the rest of our response, // and clear out redirection flag. -- cgit v1.2.3