diff --git a/src/common/state/redis.c b/src/common/state/redis.c index a3c4dbcfe..c0449b455 100644 --- a/src/common/state/redis.c +++ b/src/common/state/redis.c @@ -2,8 +2,8 @@ #include #include - #include +#include /* Including hiredis here is necessary on Windows for typedefs used in ae.h. */ #include "hiredis/hiredis.h" #include "hiredis/adapters/ae.h" @@ -20,6 +20,11 @@ #include "redis.h" #include "io.h" +#ifndef _WIN32 +/* This function is actually not declared in standard POSIX, so declare it. */ +extern int usleep(useconds_t usec); +#endif + #define CHECK_REDIS_CONNECT(CONTEXT_TYPE, context, M, ...) \ do { \ CONTEXT_TYPE *_context = (context); \ @@ -119,8 +124,21 @@ db_handle *db_connect(const char *address, db_handle *db = malloc(sizeof(db_handle)); /* Sync connection for initial handshake */ redisReply *reply; + int connection_attempts = 0; redisContext *context = redisConnect(address, port); - CHECK_REDIS_CONNECT(redisContext, context, "could not connect to redis %s:%d", + while (context == NULL || context->err) { + if (connection_attempts >= REDIS_DB_CONNECT_RETRIES) { + break; + } + LOG_WARN("Failed to connect to Redis, retrying."); + /* Sleep for a little. */ + usleep(REDIS_DB_CONNECT_WAIT_MS * 1000); + context = redisConnect(address, port); + connection_attempts += 1; + } + CHECK_REDIS_CONNECT(redisContext, context, + "could not establish synchronous connection to redis " + "%s:%d", address, port); /* Enable keyspace events. */ reply = redisCommand(context, "CONFIG SET notify-keyspace-events AKE"); @@ -161,12 +179,16 @@ db_handle *db_connect(const char *address, /* Establish async connection */ db->context = redisAsyncConnect(address, port); CHECK_REDIS_CONNECT(redisAsyncContext, db->context, - "could not connect to redis %s:%d", address, port); + "could not establish asynchronous connection to redis " + "%s:%d", + address, port); db->context->data = (void *) db; /* Establish async connection for subscription */ db->sub_context = redisAsyncConnect(address, port); CHECK_REDIS_CONNECT(redisAsyncContext, db->sub_context, - "could not connect to redis %s:%d", address, port); + "could not establish asynchronous subscription " + "connection to redis %s:%d", + address, port); db->sub_context->data = (void *) db; return db; diff --git a/src/common/state/redis.h b/src/common/state/redis.h index 48f2e0570..b4e831af1 100644 --- a/src/common/state/redis.h +++ b/src/common/state/redis.h @@ -10,6 +10,10 @@ #include "uthash.h" #include "utarray.h" +/* Allow up to 5 seconds for connecting to Redis. */ +#define REDIS_DB_CONNECT_RETRIES 50 +#define REDIS_DB_CONNECT_WAIT_MS 100 + #define LOG_REDIS_ERROR(context, M, ...) \ LOG_ERROR("Redis error %d %s; %s", context->err, context->errstr, M)