Commit 5fb3279a authored by Marc Gravell's avatar Marc Gravell

add `isInitialConnect` override to make sure we record failure in the initial connect

parent 3cd098b4
using System; using System;
using System.Security.Authentication;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Xunit; using Xunit;
...@@ -32,10 +33,16 @@ public async Task SSLCertificateValidationError(bool isCertValidationSucceeded) ...@@ -32,10 +33,16 @@ public async Task SSLCertificateValidationError(bool isCertValidationSucceeded)
if (!isCertValidationSucceeded) if (!isCertValidationSucceeded)
{ {
//validate that in this case it throws an certificatevalidation exception //validate that in this case it throws an certificatevalidation exception
var ex = Assert.Throws<RedisConnectionException>(() => connection.GetDatabase().Ping()); var outer = Assert.Throws<RedisConnectionException>(() => connection.GetDatabase().Ping());
var rde = (RedisConnectionException)ex.InnerException; Assert.Equal(ConnectionFailureType.UnableToResolvePhysicalConnection, outer.FailureType);
Assert.Equal(ConnectionFailureType.AuthenticationFailure, rde.FailureType);
Assert.Equal("The remote certificate is invalid according to the validation procedure.", rde.InnerException.Message); Assert.NotNull(outer.InnerException);
var inner = Assert.IsType<RedisConnectionException>(outer.InnerException);
Assert.Equal(ConnectionFailureType.AuthenticationFailure, inner.FailureType);
Assert.NotNull(inner.InnerException);
var innerMost = Assert.IsType<AuthenticationException>(inner.InnerException);
Assert.Equal("The remote certificate is invalid according to the validation procedure.", innerMost.Message);
} }
else else
{ {
...@@ -80,15 +87,20 @@ public void SocketFailureError() ...@@ -80,15 +87,20 @@ public void SocketFailureError()
options.Ssl = true; options.Ssl = true;
options.Password = ""; options.Password = "";
options.AbortOnConnectFail = false; options.AbortOnConnectFail = false;
var ex = Assert.Throws<RedisConnectionException>(() => options.ConnectTimeout = 1000;
var outer = Assert.Throws<RedisConnectionException>(() =>
{ {
using (var muxer = ConnectionMultiplexer.Connect(options)) using (var muxer = ConnectionMultiplexer.Connect(options))
{ {
muxer.GetDatabase().Ping(); muxer.GetDatabase().Ping();
} }
}); });
var rde = (RedisConnectionException)ex.InnerException; Assert.Equal(ConnectionFailureType.UnableToResolvePhysicalConnection, outer.FailureType);
Assert.Equal(ConnectionFailureType.SocketFailure, rde.FailureType);
Assert.NotNull(outer.InnerException);
var inner = Assert.IsType<RedisConnectionException>(outer.InnerException);
Assert.Equal(ConnectionFailureType.UnableToConnect, inner.FailureType);
} }
#if DEBUG // needs AllowConnect, which is DEBUG only #if DEBUG // needs AllowConnect, which is DEBUG only
[Fact] [Fact]
......
...@@ -159,7 +159,7 @@ internal async void BeginConnectAsync(TextWriter log) ...@@ -159,7 +159,7 @@ internal async void BeginConnectAsync(TextWriter log)
catch (ObjectDisposedException) catch (ObjectDisposedException)
{ {
bridge.Multiplexer.LogLocked(log, "(socket shutdown)"); bridge.Multiplexer.LogLocked(log, "(socket shutdown)");
try { Error(); } try { RecordConnectionFailed(ConnectionFailureType.UnableToConnect, isInitialConnect: true); }
catch (Exception inner) catch (Exception inner)
{ {
ConnectionMultiplexer.TraceWithoutContext(inner.Message); ConnectionMultiplexer.TraceWithoutContext(inner.Message);
...@@ -168,7 +168,7 @@ internal async void BeginConnectAsync(TextWriter log) ...@@ -168,7 +168,7 @@ internal async void BeginConnectAsync(TextWriter log)
catch (Exception outer) catch (Exception outer)
{ {
ConnectionMultiplexer.TraceWithoutContext(outer.Message); ConnectionMultiplexer.TraceWithoutContext(outer.Message);
try { Error(); } try { RecordConnectionFailed(ConnectionFailureType.UnableToConnect, isInitialConnect: true); }
catch (Exception inner) catch (Exception inner)
{ {
ConnectionMultiplexer.TraceWithoutContext(inner.Message); ConnectionMultiplexer.TraceWithoutContext(inner.Message);
...@@ -290,13 +290,13 @@ public Task FlushAsync() ...@@ -290,13 +290,13 @@ public Task FlushAsync()
return Task.CompletedTask; return Task.CompletedTask;
} }
public void RecordConnectionFailed(ConnectionFailureType failureType, Exception innerException = null, [CallerMemberName] string origin = null) public void RecordConnectionFailed(ConnectionFailureType failureType, Exception innerException = null, [CallerMemberName] string origin = null, bool isInitialConnect = false)
{ {
Exception outerException = innerException; Exception outerException = innerException;
IdentifyFailureType(innerException, ref failureType); IdentifyFailureType(innerException, ref failureType);
if (_ioPipe != null) // if *we* didn't burn the pipe: flag it if (_ioPipe != null || isInitialConnect) // if *we* didn't burn the pipe: flag it
{ {
if (failureType == ConnectionFailureType.InternalFailure) OnInternalError(innerException, origin); if (failureType == ConnectionFailureType.InternalFailure) OnInternalError(innerException, origin);
...@@ -1133,7 +1133,7 @@ internal async ValueTask<bool> ConnectedAsync(Socket socket, TextWriter log, Soc ...@@ -1133,7 +1133,7 @@ internal async ValueTask<bool> ConnectedAsync(Socket socket, TextWriter log, Soc
} }
catch (AuthenticationException authexception) catch (AuthenticationException authexception)
{ {
RecordConnectionFailed(ConnectionFailureType.AuthenticationFailure, authexception); RecordConnectionFailed(ConnectionFailureType.AuthenticationFailure, authexception, isInitialConnect: true);
bridge.Multiplexer.Trace("Encryption failure"); bridge.Multiplexer.Trace("Encryption failure");
return false; return false;
} }
...@@ -1154,17 +1154,12 @@ internal async ValueTask<bool> ConnectedAsync(Socket socket, TextWriter log, Soc ...@@ -1154,17 +1154,12 @@ internal async ValueTask<bool> ConnectedAsync(Socket socket, TextWriter log, Soc
} }
catch (Exception ex) catch (Exception ex)
{ {
RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex); // includes a bridge.OnDisconnected RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex, isInitialConnect: true); // includes a bridge.OnDisconnected
bridge.Multiplexer.Trace("Could not connect: " + ex.Message, physicalName); bridge.Multiplexer.Trace("Could not connect: " + ex.Message, physicalName);
return false; return false;
} }
} }
internal void Error()
{
RecordConnectionFailed(ConnectionFailureType.SocketFailure);
}
private void MatchResult(RawResult result) private void MatchResult(RawResult result)
{ {
var muxer = BridgeCouldBeNull?.Multiplexer; var muxer = BridgeCouldBeNull?.Multiplexer;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment