diff options
-rw-r--r-- | cluster_library.c | 27 | ||||
-rw-r--r-- | cluster_library.h | 7 | ||||
-rw-r--r-- | redis_cluster.c | 3 |
3 files changed, 24 insertions, 13 deletions
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. diff --git a/cluster_library.h b/cluster_library.h index a4b44522..fb6b153e 100644 --- a/cluster_library.h +++ b/cluster_library.h @@ -74,7 +74,8 @@ efree(c->err); \ c->err = NULL; \ c->err_len = 0; \ - } + } \ + c->clusterdown = 0; /* Reset our last single line reply buffer and length */ #define CLUSTER_CLEAR_REPLY(c) \ @@ -195,8 +196,8 @@ typedef struct redisCluster { /* Variable to store MULTI response */ zval *multi_resp; - /* How many failures have we had in a row */ - int failures; + /* Flag for when we get a CLUSTERDOWN error */ + short clusterdown; /* The last ERROR we encountered */ char *err; diff --git a/redis_cluster.c b/redis_cluster.c index d9d115c0..ad175131 100644 --- a/redis_cluster.c +++ b/redis_cluster.c @@ -267,6 +267,9 @@ create_cluster_context(zend_class_entry *class_type TSRMLS_DC) { // We're not currently subscribed anywhere cluster->subscribed_slot = -1; + // Assume we're up initially + cluster->clusterdown = 0; + // Allocate our RedisSock we'll use to store prefix/serialization flags cluster->flags = ecalloc(1, sizeof(RedisSock)); |