Search code examples
asynchronoustcpredishiredis

Setting the TCP keepalive interval on the Hiredis async context


I'm writing a wrapper around hiredis to enable publish / subscribe functionality with reconnects should a redis node go down.

I'm using the asynchronous redis API.

So I have a test harness that sets up a publisher and subscriber. The harness then shuts down the slave VM from which the subscriber is reading.

However, the disconnect callback isn't called until much later (when I'm destructing the Subscription object that contains the corresponding redisAsyncContext.

I thought that the solution to this might be using tcp keepalive.

So I found that there's a suitable redis function in net.h:

int redisKeepAlive (redisContext* c, int interval);

However, the following appears to show that the redisKeepAlive function has been omitted from the library on purpose:

$ nm libhiredis.a --demangle | grep redisKeepAlive
0000000000000030 T redisKeepAlive
                 U redisKeepAlive

$ nm libhiredis.a -u --demangle | grep redisKeepAlive
             U redisKeepAlive

Certainly when I try to use the call, the linker complains:

Subscription.cpp:167: undefined reference to `redisKeepAlive(redisContext*, int)'
collect2: error: ld returned 1 exit status

Am I out of luck - is there a way to set the TCP keepalive interval on the Hiredis async context?

Update I've found this:

int redisEnableKeepAlive(redisContext *c);

But setting this on the asyncContext->c and adjusting REDIS_KEEPALIVE_INTERVAL seems to have no effect.


Solution

  • I found that the implementation of redisKeepAlive contains code that shows how to get direct access to the underlying socket descriptor:

    int redisKeepAlive(redisContext *c, int interval) {
    int val = 1;
    int fd = c->fd;
    
    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){
        __redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
        return REDIS_ERR;
    

    }

    Maybe this'll help someone..