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