From 30e7422407760d0d56361f76b73c5930875a03d3 Mon Sep 17 00:00:00 2001 From: BrennanConroy Date: Tue, 24 Oct 2017 14:30:13 -0700 Subject: [PATCH] Enable reconnect for Redis connection by default (#1037) --- .../Internal/RedisLoggerExtensions.cs | 36 +++++++++++++++++-- .../RedisHubLifetimeManager.cs | 30 ++++++++++++++-- .../RedisOptions.cs | 7 +++- 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.AspNetCore.SignalR.Redis/Internal/RedisLoggerExtensions.cs b/src/Microsoft.AspNetCore.SignalR.Redis/Internal/RedisLoggerExtensions.cs index 4d1871fdcb..2c1e512e2d 100644 --- a/src/Microsoft.AspNetCore.SignalR.Redis/Internal/RedisLoggerExtensions.cs +++ b/src/Microsoft.AspNetCore.SignalR.Redis/Internal/RedisLoggerExtensions.cs @@ -2,7 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Linq; using Microsoft.Extensions.Logging; +using StackExchange.Redis; namespace Microsoft.AspNetCore.SignalR.Redis.Internal { @@ -27,9 +29,24 @@ namespace Microsoft.AspNetCore.SignalR.Redis.Internal private static readonly Action _unsubscribe = LoggerMessage.Define(LogLevel.Trace, new EventId(5, nameof(Unsubscribe)), "Unsubscribing from channel: {channel}."); - public static void ConnectingToEndpoints(this ILogger logger, string endpoints) + private static readonly Action _notConnected = + LoggerMessage.Define(LogLevel.Warning, new EventId(6, nameof(Connected)), "Not connected to Redis."); + + private static readonly Action _connectionRestored = + LoggerMessage.Define(LogLevel.Information, new EventId(7, nameof(ConnectionRestored)), "Connection to Redis restored."); + + private static readonly Action _connectionFailed = + LoggerMessage.Define(LogLevel.Warning, new EventId(8, nameof(ConnectionFailed)), "Connection to Redis failed."); + + public static void ConnectingToEndpoints(this ILogger logger, EndPointCollection endpoints) { - _connectingToEndpoints(logger, endpoints, null); + if (logger.IsEnabled(LogLevel.Information)) + { + if (endpoints.Count > 0) + { + _connectingToEndpoints(logger, string.Join(", ", endpoints.Select(e => EndPointCollection.ToString(e))), null); + } + } } public static void Connected(this ILogger logger) @@ -56,5 +73,20 @@ namespace Microsoft.AspNetCore.SignalR.Redis.Internal { _unsubscribe(logger, channelName, null); } + + public static void NotConnected(this ILogger logger) + { + _notConnected(logger, null); + } + + public static void ConnectionRestored(this ILogger logger) + { + _connectionRestored(logger, null); + } + + public static void ConnectionFailed(this ILogger logger, Exception exception) + { + _connectionFailed(logger, exception); + } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.SignalR.Redis/RedisHubLifetimeManager.cs b/src/Microsoft.AspNetCore.SignalR.Redis/RedisHubLifetimeManager.cs index cd62c986e1..2e714a4606 100644 --- a/src/Microsoft.AspNetCore.SignalR.Redis/RedisHubLifetimeManager.cs +++ b/src/Microsoft.AspNetCore.SignalR.Redis/RedisHubLifetimeManager.cs @@ -51,16 +51,40 @@ namespace Microsoft.AspNetCore.SignalR.Redis _ackHandler = new AckHandler(); var writer = new LoggerTextWriter(logger); - _logger.ConnectingToEndpoints(string.Join(", ", options.Value.Options.EndPoints.Select(e => EndPointCollection.ToString(e)))); + _logger.ConnectingToEndpoints(options.Value.Options.EndPoints); _redisServerConnection = _options.Connect(writer); + + _redisServerConnection.ConnectionRestored += (_, e) => + { + // We use the subscription connection type + // Ignore messages from the interactive connection (avoids duplicates) + if (e.ConnectionType == ConnectionType.Interactive) + { + return; + } + + _logger.ConnectionRestored(); + }; + + _redisServerConnection.ConnectionFailed += (_, e) => + { + // We use the subscription connection type + // Ignore messages from the interactive connection (avoids duplicates) + if (e.ConnectionType == ConnectionType.Interactive) + { + return; + } + + _logger.ConnectionFailed(e.Exception); + }; + if (_redisServerConnection.IsConnected) { _logger.Connected(); } else { - // TODO: We could support reconnecting, like old SignalR does. - throw new InvalidOperationException("Connection to redis failed."); + _logger.NotConnected(); } _bus = _redisServerConnection.GetSubscriber(); diff --git a/src/Microsoft.AspNetCore.SignalR.Redis/RedisOptions.cs b/src/Microsoft.AspNetCore.SignalR.Redis/RedisOptions.cs index 6c25e128b4..89565f40fd 100644 --- a/src/Microsoft.AspNetCore.SignalR.Redis/RedisOptions.cs +++ b/src/Microsoft.AspNetCore.SignalR.Redis/RedisOptions.cs @@ -10,7 +10,11 @@ namespace Microsoft.AspNetCore.SignalR.Redis { public class RedisOptions { - public ConfigurationOptions Options { get; set; } = new ConfigurationOptions(); + public ConfigurationOptions Options { get; set; } = new ConfigurationOptions + { + // Enable reconnecting by default + AbortOnConnectFail = false + }; public Func Factory { get; set; } @@ -25,6 +29,7 @@ namespace Microsoft.AspNetCore.SignalR.Redis Options.EndPoints.Add(IPAddress.Loopback, 0); Options.SetDefaultPorts(); } + return ConnectionMultiplexer.Connect(Options, log); }