Commit 1e78a2a4 authored by DeepakVerma's avatar DeepakVerma

supporting status for being able to retry, if command was never sent over the wire.

parent b8a98e44
...@@ -64,6 +64,7 @@ public void AuthenticationFailureError() ...@@ -64,6 +64,7 @@ public void AuthenticationFailureError()
}; };
var ex = Assert.Throws<RedisConnectionException>(() => muxer.GetDatabase().Ping()); var ex = Assert.Throws<RedisConnectionException>(() => muxer.GetDatabase().Ping());
var rde = (RedisConnectionException)ex.InnerException; var rde = (RedisConnectionException)ex.InnerException;
Assert.That(ex.CommandStatus, Is.EqualTo(CommandStatus.WaitingToBeSent));
Assert.That(rde.FailureType, Is.EqualTo(ConnectionFailureType.AuthenticationFailure)); Assert.That(rde.FailureType, Is.EqualTo(ConnectionFailureType.AuthenticationFailure));
Assert.That(rde.InnerException.Message, Is.EqualTo("Error: NOAUTH Authentication required. Verify if the Redis password provided is correct.")); Assert.That(rde.InnerException.Message, Is.EqualTo("Error: NOAUTH Authentication required. Verify if the Redis password provided is correct."));
//wait for a second for connectionfailed event to fire //wait for a second for connectionfailed event to fire
......
namespace StackExchange.Redis
{
/// <summary>
/// track status of a command while communicating with Redis
/// </summary>
public enum CommandStatus
{
/// <summary>
/// command status unknown
/// </summary>
Unknown,
/// <summary>
/// ConnectionMultiplexer has not yet started writing this command to redis
/// </summary>
WaitingToBeSent,
/// <summary>
/// command has been sent to Redis
/// </summary>
Sent,
}
}
...@@ -12,7 +12,8 @@ internal static class ExceptionFactory ...@@ -12,7 +12,8 @@ internal static class ExceptionFactory
DataServerEndpoint = "server-endpoint", DataServerEndpoint = "server-endpoint",
DataConnectionState = "connection-state", DataConnectionState = "connection-state",
DataLastFailure = "last-failure", DataLastFailure = "last-failure",
DataLastInnerException = "last-innerexception"; DataLastInnerException = "last-innerexception",
DataSentStatusKey = "request-sent-status";
internal static Exception AdminModeNotEnabled(bool includeDetail, RedisCommand command, Message message, ServerEndPoint server) internal static Exception AdminModeNotEnabled(bool includeDetail, RedisCommand command, Message message, ServerEndPoint server)
...@@ -118,7 +119,7 @@ internal static Exception NoConnectionAvailable(bool includeDetail, RedisCommand ...@@ -118,7 +119,7 @@ internal static Exception NoConnectionAvailable(bool includeDetail, RedisCommand
} }
#endif #endif
var ex = new RedisConnectionException(ConnectionFailureType.UnableToResolvePhysicalConnection, exceptionmessage.ToString(), innerException); var ex = new RedisConnectionException(ConnectionFailureType.UnableToResolvePhysicalConnection, exceptionmessage.ToString(), innerException, message?.Status ?? CommandStatus.Unknown);
if (includeDetail) if (includeDetail)
{ {
...@@ -173,7 +174,7 @@ internal static Exception NoCursor(RedisCommand command) ...@@ -173,7 +174,7 @@ internal static Exception NoCursor(RedisCommand command)
internal static Exception Timeout(bool includeDetail, string errorMessage, Message message, ServerEndPoint server) internal static Exception Timeout(bool includeDetail, string errorMessage, Message message, ServerEndPoint server)
{ {
var ex = new TimeoutException(errorMessage); var ex = new RedisTimeoutException(errorMessage, message?.Status ?? CommandStatus.Unknown);
if (includeDetail) AddDetail(ex, message, server, null); if (includeDetail) AddDetail(ex, message, server, null);
return ex; return ex;
} }
...@@ -182,7 +183,11 @@ private static void AddDetail(Exception exception, Message message, ServerEndPoi ...@@ -182,7 +183,11 @@ private static void AddDetail(Exception exception, Message message, ServerEndPoi
{ {
if (exception != null) if (exception != null)
{ {
if (message != null) exception.Data.Add(DataCommandKey, message.CommandAndKey); if (message != null)
{
exception.Data.Add(DataCommandKey, message.CommandAndKey);
exception.Data.Add(DataSentStatusKey, message.Status);
}
else if (label != null) exception.Data.Add(DataCommandKey, label); else if (label != null) exception.Data.Add(DataCommandKey, label);
if (server != null) exception.Data.Add(DataServerKey, Format.ToString(server.EndPoint)); if (server != null) exception.Data.Add(DataServerKey, Format.ToString(server.EndPoint));
......
...@@ -27,6 +27,40 @@ public sealed class RedisCommandException : Exception ...@@ -27,6 +27,40 @@ public sealed class RedisCommandException : Exception
} }
/// <summary>
/// Indicates the time allotted for a command or operation has expired.
/// </summary>
#if FEATURE_SERIALIZATION
[Serializable]
#endif
public sealed class RedisTimeoutException : TimeoutException
{
#if FEATURE_SERIALIZATION
private RedisTimeoutException(SerializationInfo info, StreamingContext ctx) : base(info, ctx)
{
Commandstatus = (CommandStatus) info.GetValue("commandStatus", typeof(CommandStatus));
}
/// <summary>
/// Serialization implementation; not intended for general usage
/// </summary>
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("commandStatus", Commandstatus);
}
#endif
internal RedisTimeoutException(string message, CommandStatus commandStatus) : base(message)
{
Commandstatus = commandStatus;
}
/// <summary>
/// status of the command while communicating with Redis
/// </summary>
public CommandStatus Commandstatus { get; }
}
/// <summary> /// <summary>
/// Indicates a connection fault when communicating with redis /// Indicates a connection fault when communicating with redis
...@@ -40,6 +74,7 @@ public sealed class RedisConnectionException : RedisException ...@@ -40,6 +74,7 @@ public sealed class RedisConnectionException : RedisException
private RedisConnectionException(SerializationInfo info, StreamingContext ctx) : base(info, ctx) private RedisConnectionException(SerializationInfo info, StreamingContext ctx) : base(info, ctx)
{ {
FailureType = (ConnectionFailureType)info.GetInt32("failureType"); FailureType = (ConnectionFailureType)info.GetInt32("failureType");
CommandStatus = (CommandStatus)info.GetValue("commandStatus", typeof(CommandStatus));
} }
/// <summary> /// <summary>
/// Serialization implementation; not intended for general usage /// Serialization implementation; not intended for general usage
...@@ -48,22 +83,33 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont ...@@ -48,22 +83,33 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont
{ {
base.GetObjectData(info, context); base.GetObjectData(info, context);
info.AddValue("failureType", (int)FailureType); info.AddValue("failureType", (int)FailureType);
info.AddValue("commandStatus", CommandStatus);
} }
#endif #endif
internal RedisConnectionException(ConnectionFailureType failureType, string message) : base(message) internal RedisConnectionException(ConnectionFailureType failureType, string message) : this(failureType, message, null, CommandStatus.Unknown)
{ {
FailureType = failureType;
} }
internal RedisConnectionException(ConnectionFailureType failureType, string message, Exception innerException) : base(message, innerException)
internal RedisConnectionException(ConnectionFailureType failureType, string message, Exception innerException) : this(failureType, message, innerException, CommandStatus.Unknown)
{
}
internal RedisConnectionException(ConnectionFailureType failureType, string message, Exception innerException, CommandStatus commandStatus) : base(message, innerException)
{ {
FailureType = failureType; FailureType = failureType;
CommandStatus = commandStatus;
} }
/// <summary> /// <summary>
/// The type of connection failure /// The type of connection failure
/// </summary> /// </summary>
public ConnectionFailureType FailureType { get; } public ConnectionFailureType FailureType { get; }
/// <summary>
/// status of the command while communicating with Redis
/// </summary>
public CommandStatus CommandStatus { get; }
} }
/// <summary> /// <summary>
...@@ -193,6 +239,7 @@ protected Message(int db, CommandFlags flags, RedisCommand command) ...@@ -193,6 +239,7 @@ protected Message(int db, CommandFlags flags, RedisCommand command)
createdDateTime = DateTime.UtcNow; createdDateTime = DateTime.UtcNow;
createdTimestamp = System.Diagnostics.Stopwatch.GetTimestamp(); createdTimestamp = System.Diagnostics.Stopwatch.GetTimestamp();
Status = CommandStatus.WaitingToBeSent;
} }
internal void SetMasterOnly() internal void SetMasterOnly()
...@@ -231,8 +278,11 @@ internal void PrepareToResend(ServerEndPoint resendTo, bool isMoved) ...@@ -231,8 +278,11 @@ internal void PrepareToResend(ServerEndPoint resendTo, bool isMoved)
createdTimestamp = System.Diagnostics.Stopwatch.GetTimestamp(); createdTimestamp = System.Diagnostics.Stopwatch.GetTimestamp();
performance = ProfileStorage.NewAttachedToSameContext(oldPerformance, resendTo, isMoved); performance = ProfileStorage.NewAttachedToSameContext(oldPerformance, resendTo, isMoved);
performance.SetMessage(this); performance.SetMessage(this);
Status = CommandStatus.WaitingToBeSent;
} }
internal CommandStatus Status { get; private set; }
public RedisCommand Command => command; public RedisCommand Command => command;
public virtual string CommandAndKey => Command.ToString(); public virtual string CommandAndKey => Command.ToString();
...@@ -678,6 +728,7 @@ internal void SetEnqueued() ...@@ -678,6 +728,7 @@ internal void SetEnqueued()
internal void SetRequestSent() internal void SetRequestSent()
{ {
Status = CommandStatus.Sent;
performance?.SetRequestSent(); performance?.SetRequestSent();
} }
......
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