user4388759
user4388759

Reputation: 111

StackExchange.Redis ConnectionMultiplexer - handling disconnects

What is the correct way to handle socket failure in a ConnectionMultiplexer? I know it will try again silently in the background, but is there any accepted canonical way to handle the time between such disconnects? Since I wrap this up in our own client anyway, I was thinking something like the following:

  private async Task<IDatabase> GetDb(int dbToGet)
    { 
        int numberOfRetries = 0;
        while (!multiplexer.IsConnected && numberOfRetries < MAX_RETRIES)
        {
                await Task.Delay(20);
                numberOfRetries++;
        }
        if (!multiplexer.IsConnected)
        {
                 // Panic, die, etc.
        }

       // Continue as though connected here
    }

It seems a bit clumsy, though, so I'm wondering if there's a better way to handle this.

(This is all in version 1.0.414 of StackExchange.Redis, the latest version from NuGet)

Upvotes: 4

Views: 1926

Answers (1)

Tal Laitner
Tal Laitner

Reputation: 141

I just wrapped multiplexer, by default it has auto reconnect definition, the real problem is that you have subscribe/Psubscribe to Redis with current socket connection, therefore I used the ConnectionRestored Event to re-Register the subscribe patterns to the relevant channels/actions.

Class Example:

public class RedisInstanceManager
{
    public RedisInstanceCredentials m_redisInstanceCredentials { get; set; }
    public DateTime? m_lastUpdatedDate { get; set; }
    public ConnectionMultiplexer redisClientsFactory { get; set; }
    public Timer _ConnectedTimer;
    public Action _reconnectAction; 
    public RedisInstanceManager(ConnectionMultiplexer redisClients, Action _reconnectActionIncoming)
    {
        string host,port;
        string[] splitArray  = redisClients.Configuration.Split(':');
        host =  splitArray[0];
        port = splitArray[1];

        this.redisClientsFactory = redisClients;
        this.m_redisInstanceCredentials = new RedisInstanceCredentials(host, port);
        this.m_lastUpdatedDate = null;
        _ConnectedTimer = new Timer(connectedTimer, null, 1500, 1500);
        _reconnectAction = _reconnectActionIncoming;
        this.redisClientsFactory.ConnectionRestored += redisClientsFactory_ConnectionRestored;
    }

    private void connectedTimer(object o)
    {
        _ConnectedTimer.Change(Timeout.Infinite, Timeout.Infinite);
        if (!this.redisClientsFactory.IsConnected)
        {
            Console.WriteLine("redis dissconnected");
        }
        _ConnectedTimer.Change(1500,1500);
    }

    void redisClientsFactory_ConnectionRestored(object sender, ConnectionFailedEventArgs e)
    {
        Console.WriteLine("Redis Connected again");
        if (_reconnectAction != null)
            _reconnectAction();
    }

    public ConnectionMultiplexer GetClient()
    {
        return this.redisClientsFactory;
    }
}

Upvotes: 1

Related Questions