Commit 8e5ba355 authored by Marc Gravell's avatar Marc Gravell

Improve detection and error message when bad auth; still need to see why it...

Improve detection and error message when bad auth; still need to see why it takes 5s to timeout in my shell, though
parent b49d9bdb
...@@ -88,7 +88,7 @@ public async Task ConnectWithWrongPassword(string password) ...@@ -88,7 +88,7 @@ public async Task ConnectWithWrongPassword(string password)
} }
}).ConfigureAwait(false); }).ConfigureAwait(false);
Output.WriteLine("Exception: " + ex.Message); Output.WriteLine("Exception: " + ex.Message);
Assert.Equal("It was not possible to connect to the redis server(s); to create a disconnected multiplexer, disable AbortOnConnectFail. AuthenticationFailure on PING", ex.Message); Assert.Equal("It was not possible to connect to the redis server(s). There was an authentication failure; check that passwords (or client certificates) are configured correctly.", ex.Message);
} }
} }
} }
...@@ -571,6 +571,9 @@ private static bool WaitAllIgnoreErrors(Task[] tasks, int timeout) ...@@ -571,6 +571,9 @@ private static bool WaitAllIgnoreErrors(Task[] tasks, int timeout)
return false; return false;
} }
internal bool AuthSuspect { get; private set; }
internal void SetAuthSuspect() => AuthSuspect = true;
private void LogLockedWithThreadPoolStats(TextWriter log, string message, out int busyWorkerCount) private void LogLockedWithThreadPoolStats(TextWriter log, string message, out int busyWorkerCount)
{ {
busyWorkerCount = 0; busyWorkerCount = 0;
...@@ -735,7 +738,7 @@ public static async Task<ConnectionMultiplexer> ConnectAsync(string configuratio ...@@ -735,7 +738,7 @@ public static async Task<ConnectionMultiplexer> ConnectAsync(string configuratio
bool configured = await muxer.ReconfigureAsync(true, false, log, null, "connect").ObserveErrors().ForAwait(); bool configured = await muxer.ReconfigureAsync(true, false, log, null, "connect").ObserveErrors().ForAwait();
if (!configured) if (!configured)
{ {
throw ExceptionFactory.UnableToConnect(muxer.RawConfig.AbortOnConnectFail, muxer.failureMessage); throw ExceptionFactory.UnableToConnect(muxer, muxer.failureMessage);
} }
killMe = null; killMe = null;
return muxer; return muxer;
...@@ -761,7 +764,7 @@ public static async Task<ConnectionMultiplexer> ConnectAsync(ConfigurationOption ...@@ -761,7 +764,7 @@ public static async Task<ConnectionMultiplexer> ConnectAsync(ConfigurationOption
bool configured = await muxer.ReconfigureAsync(true, false, log, null, "connect").ObserveErrors().ForAwait(); bool configured = await muxer.ReconfigureAsync(true, false, log, null, "connect").ObserveErrors().ForAwait();
if (!configured) if (!configured)
{ {
throw ExceptionFactory.UnableToConnect(muxer.RawConfig.AbortOnConnectFail, muxer.failureMessage); throw ExceptionFactory.UnableToConnect(muxer, muxer.failureMessage);
} }
killMe = null; killMe = null;
return muxer; return muxer;
...@@ -828,14 +831,14 @@ private static ConnectionMultiplexer ConnectImpl(Func<ConnectionMultiplexer> mul ...@@ -828,14 +831,14 @@ private static ConnectionMultiplexer ConnectImpl(Func<ConnectionMultiplexer> mul
task.ObserveErrors(); task.ObserveErrors();
if (muxer.RawConfig.AbortOnConnectFail) if (muxer.RawConfig.AbortOnConnectFail)
{ {
throw ExceptionFactory.UnableToConnect(muxer.RawConfig.AbortOnConnectFail, "ConnectTimeout"); throw ExceptionFactory.UnableToConnect(muxer, "ConnectTimeout");
} }
else else
{ {
muxer.LastException = ExceptionFactory.UnableToConnect(muxer.RawConfig.AbortOnConnectFail, "ConnectTimeout"); muxer.LastException = ExceptionFactory.UnableToConnect(muxer, "ConnectTimeout");
} }
} }
if (!task.Result) throw ExceptionFactory.UnableToConnect(muxer.RawConfig.AbortOnConnectFail, muxer.failureMessage); if (!task.Result) throw ExceptionFactory.UnableToConnect(muxer, muxer.failureMessage);
killMe = null; killMe = null;
return muxer; return muxer;
} }
......
...@@ -216,12 +216,17 @@ private static string GetLabel(bool includeDetail, string command, Message messa ...@@ -216,12 +216,17 @@ private static string GetLabel(bool includeDetail, string command, Message messa
{ {
return message == null ? command : (includeDetail ? message.CommandAndKey : message.Command.ToString()); return message == null ? command : (includeDetail ? message.CommandAndKey : message.Command.ToString());
} }
internal static Exception UnableToConnect(ConnectionMultiplexer muxer, string failureMessage=null)
internal static Exception UnableToConnect(bool abortOnConnect, string failureMessage=null) {
var sb = new StringBuilder("It was not possible to connect to the redis server(s).");
if (muxer != null)
{ {
var abortOnConnectionFailure = abortOnConnect ? "to create a disconnected multiplexer, disable AbortOnConnectFail. " : ""; if (muxer.AuthSuspect) sb.Append(" There was an authentication failure; check that passwords (or client certificates) are configured correctly.");
return new RedisConnectionException(ConnectionFailureType.UnableToConnect, else if (!muxer.RawConfig.AbortOnConnectFail) sb.Append(" To create a disconnected multiplexer, disable AbortOnConnectFail.");
string.Format("It was not possible to connect to the redis server(s); {0}{1}", abortOnConnectionFailure, failureMessage)); }
if (!string.IsNullOrWhiteSpace(failureMessage)) sb.Append(" ").Append(failureMessage.Trim());
return new RedisConnectionException(ConnectionFailureType.UnableToConnect, sb.ToString());
} }
internal static Exception BeganProfilingWithDuplicateContext(object forContext) internal static Exception BeganProfilingWithDuplicateContext(object forContext)
......
...@@ -574,9 +574,9 @@ internal static CommandFlags SetMasterSlaveFlags(CommandFlags everything, Comman ...@@ -574,9 +574,9 @@ internal static CommandFlags SetMasterSlaveFlags(CommandFlags everything, Comman
| masterSlave; | masterSlave;
} }
internal void Cancel() internal void Cancel(Exception ex = null)
{ {
resultProcessor?.SetException(this, new TaskCanceledException()); resultProcessor?.SetException(this, ex ?? new TaskCanceledException());
} }
// true if ready to be completed (i.e. false if re-issued to another server) // true if ready to be completed (i.e. false if re-issued to another server)
......
...@@ -45,7 +45,9 @@ internal sealed partial class PhysicalBridge : IDisposable ...@@ -45,7 +45,9 @@ internal sealed partial class PhysicalBridge : IDisposable
private long profileLastLog; private long profileLastLog;
private int profileLogIndex; private int profileLogIndex;
private volatile bool reportNextFailure = true, reconfigureNextFailure = false; private volatile bool reportNextFailure = true, reconfigureNextFailure = false;
private volatile int state = (int)State.Disconnected; private volatile int state = (int)State.Disconnected;
public PhysicalBridge(ServerEndPoint serverEndPoint, ConnectionType type) public PhysicalBridge(ServerEndPoint serverEndPoint, ConnectionType type)
...@@ -275,6 +277,7 @@ internal void ResetNonConnected() ...@@ -275,6 +277,7 @@ internal void ResetNonConnected()
internal void OnConnectionFailed(PhysicalConnection connection, ConnectionFailureType failureType, Exception innerException) internal void OnConnectionFailed(PhysicalConnection connection, ConnectionFailureType failureType, Exception innerException)
{ {
AbandonPendingBacklog(innerException);
if (reportNextFailure) if (reportNextFailure)
{ {
LastException = innerException; LastException = innerException;
...@@ -329,6 +332,15 @@ void WritePendingBacklog(PhysicalConnection connection) ...@@ -329,6 +332,15 @@ void WritePendingBacklog(PhysicalConnection connection)
} while (next != null); } while (next != null);
} }
} }
void AbandonPendingBacklog(Exception ex)
{
Message next;
do
{
next = DequeueNextPendingBacklog();
next.Cancel(ex);
} while (next != null);
}
internal void OnFullyEstablished(PhysicalConnection connection) internal void OnFullyEstablished(PhysicalConnection connection)
{ {
Trace("OnFullyEstablished"); Trace("OnFullyEstablished");
...@@ -372,7 +384,7 @@ internal void OnHeartbeat(bool ifConnectedOnly) ...@@ -372,7 +384,7 @@ internal void OnHeartbeat(bool ifConnectedOnly)
if (shouldRetry) if (shouldRetry)
{ {
Interlocked.Increment(ref connectTimeoutRetryCount); Interlocked.Increment(ref connectTimeoutRetryCount);
LastException = ExceptionFactory.UnableToConnect(Multiplexer.RawConfig.AbortOnConnectFail, "ConnectTimeout"); LastException = ExceptionFactory.UnableToConnect(Multiplexer, "ConnectTimeout");
Trace("Aborting connect"); Trace("Aborting connect");
// abort and reconnect // abort and reconnect
var snapshot = physical; var snapshot = physical;
......
...@@ -107,7 +107,10 @@ public static readonly TimeSpanProcessor ...@@ -107,7 +107,10 @@ public static readonly TimeSpanProcessor
TimeSpanFromSeconds = new TimeSpanProcessor(false); TimeSpanFromSeconds = new TimeSpanProcessor(false);
public static readonly HashEntryArrayProcessor public static readonly HashEntryArrayProcessor
HashEntryArray = new HashEntryArrayProcessor(); HashEntryArray = new HashEntryArrayProcessor();
private static readonly byte[] MOVED = Encoding.UTF8.GetBytes("MOVED "), ASK = Encoding.UTF8.GetBytes("ASK "); private static readonly byte[]
MOVED = Encoding.UTF8.GetBytes("MOVED "),
ASK = Encoding.UTF8.GetBytes("ASK "),
NOAUTH = Encoding.UTF8.GetBytes("NOAUTH ");
public void ConnectionFail(Message message, ConnectionFailureType fail, Exception innerException) public void ConnectionFail(Message message, ConnectionFailureType fail, Exception innerException)
{ {
...@@ -147,6 +150,7 @@ public virtual bool SetResult(PhysicalConnection connection, Message message, Ra ...@@ -147,6 +150,7 @@ public virtual bool SetResult(PhysicalConnection connection, Message message, Ra
} }
if (result.IsError) if (result.IsError)
{ {
if (result.AssertStarts(NOAUTH)) connection?.Multiplexer?.SetAuthSuspect();
var bridge = connection.Bridge; var bridge = connection.Bridge;
var server = bridge.ServerEndPoint; var server = bridge.ServerEndPoint;
bool log = !message.IsInternalCall; bool log = !message.IsInternalCall;
...@@ -891,6 +895,7 @@ protected override bool SetResultCore(PhysicalConnection connection, Message mes ...@@ -891,6 +895,7 @@ protected override bool SetResultCore(PhysicalConnection connection, Message mes
SetResult(message, true); SetResult(message, true);
return true; return true;
} }
if(message.Command == RedisCommand.AUTH) connection?.Multiplexer?.SetAuthSuspect();
return false; return false;
} }
} }
......
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Linq; using System.Linq;
...@@ -9,7 +10,8 @@ class Program ...@@ -9,7 +10,8 @@ class Program
{ {
static int Main() static int Main()
{ {
//var s = new StringWriter(); var s = new StringWriter();
var watch = Stopwatch.StartNew();
try try
{ {
#if DEBUG #if DEBUG
...@@ -18,10 +20,11 @@ static int Main() ...@@ -18,10 +20,11 @@ static int Main()
var config = new ConfigurationOptions var config = new ConfigurationOptions
{ {
ConnectRetry = 0,
EndPoints = { "127.0.0.1:6381" }, EndPoints = { "127.0.0.1:6381" },
Password = "abc", Password = "abc",
}; };
using (var conn = ConnectionMultiplexer.Connect(config, log: Console.Out)) using (var conn = ConnectionMultiplexer.Connect(config, log: s))
{ {
Execute(conn); Execute(conn);
} }
...@@ -35,9 +38,14 @@ static int Main() ...@@ -35,9 +38,14 @@ static int Main()
} }
finally finally
{ {
watch.Stop();
Console.WriteLine(); Console.WriteLine();
Console.WriteLine($"{watch.ElapsedMilliseconds}ms");
Console.WriteLine();
//Console.WriteLine(s); //Console.WriteLine(s);
Console.ReadKey(); Console.ReadKey();
} }
} }
......
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