-
Notifications
You must be signed in to change notification settings - Fork 448
Implement #1157 by adding client timeout for C# client #1165
Conversation
|
||
public Task Closed { get; } | ||
|
||
/// <summary> | ||
/// Gets or sets the server timeout interval for the connection. Changes to this value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Changes to this value are ignored after StartAsync is called"
False, ResetTimeoutTimer
is called in the OnDataReceivedAsync
callback
_logger.AbortingClient(ex, _connectionId); | ||
|
||
// Immediately fault the close task. When the transport shuts down, | ||
// it will trigger the close task to be completed, so we want to it be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"we want to it be" more gramrar
@@ -506,6 +509,14 @@ public static void SendingMessage(this ILogger logger, string connectionId) | |||
} | |||
} | |||
|
|||
public static void AbortingClient(this ILogger logger, Exception ex, string connectionId) | |||
{ | |||
if (logger.IsEnabled(LogLevel.Information)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error error
@@ -506,6 +509,14 @@ public static void SendingMessage(this ILogger logger, string connectionId) | |||
} | |||
} | |||
|
|||
public static void AbortingClient(this ILogger logger, Exception ex, string connectionId) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer Exception and connectionId swtiched
@@ -12,6 +12,7 @@ | |||
using Microsoft.AspNetCore.Sockets.Client.Internal; | |||
using Microsoft.Extensions.Logging; | |||
using Microsoft.Extensions.Logging.Abstractions; | |||
using Microsoft.AspNetCore.Sockets.Features; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
stro
@@ -13,6 +13,7 @@ public interface IConnection | |||
Task StartAsync(); | |||
Task SendAsync(byte[] data, CancellationToken cancellationToken); | |||
Task DisposeAsync(); | |||
Task AbortAsync(Exception ex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a sign we should unify the client and sever connection objects. This will turn into ConnectionContext
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, but I don't want to block this PR on that right now since I don't need to unify them to implement this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#1177 to track that
@@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Sockets.Client | |||
{ | |||
public interface ITransport | |||
{ | |||
Task StartAsync(Uri url, Channel<byte[], SendMessage> application, TransferMode requestedTransferMode, string connectionId); | |||
Task StartAsync(Uri url, Channel<byte[], SendMessage> application, TransferMode requestedTransferMode, string connectionId, IConnection connection); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't very clean. We shouldn't need to pass the IConnection here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How else should transports add features? I actually think it makes sense, it's much like how it works on the server.
{ | ||
await hubConnection.DisposeAsync().OrTimeout(); | ||
} | ||
catch (TimeoutException) when (transportType != TransportType.LongPolling) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is this exception coming from? Doesn't seem right
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DisposeAsync also throws the exception because it re-awaits Closed. I can move the assert to that though.
|
||
try | ||
{ | ||
await connection.ReceiveJsonMessage(new { type = 6 }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an enum for this value anywhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, but there are constants... It's internal but I suppose we could make them pubternal.
@@ -16,6 +16,7 @@ | |||
using Moq; | |||
using Moq.Protected; | |||
using Xunit; | |||
using Microsoft.AspNetCore.SignalR.Client.Tests; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sort
@@ -12,6 +12,7 @@ | |||
using Microsoft.Extensions.Logging.Testing; | |||
using Xunit; | |||
using Xunit.Abstractions; | |||
using Moq; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sort
@@ -78,6 +92,20 @@ public HubConnection(IConnection connection, IHubProtocol protocol, ILoggerFacto | |||
} | |||
} | |||
|
|||
private void TimeoutElapsed() | |||
{ | |||
_connection.AbortAsync(new TimeoutException("Server timeout elapsed without receiving a message from the server.")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be useful to call out what the timeout was in the exception message?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most other systems don't. We could, I suppose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A lot of those are simply converting error codes to strings though so they don't have the timeout value :). I should be able to add that in easily.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is not common elsewhere, let's not complicate this more then. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Meh, it's easy and done. It'd be more work to remove it now :P
d94a33f
to
7808a40
Compare
7808a40
to
db3b58e
Compare
|
||
public Task Closed { get; } | ||
|
||
/// <summary> | ||
/// Gets or sets the server timeout interval for the connection. Changes to this value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Changes to this value are ignored after StartAsync is called"
False, ResetTimeoutTimer
is called in the OnDataReceivedAsync
callback
@@ -64,6 +74,9 @@ public HubConnection(IConnection connection, IHubProtocol protocol, ILoggerFacto | |||
Shutdown(task.Exception); | |||
return task; | |||
}).Unwrap(); | |||
|
|||
// Create the timer for timeout, but disabled by default (we enable it when started). | |||
_timeoutTimer = new Timer(state => ((HubConnection)state).TimeoutElapsed(), this, Timeout.Infinite, Timeout.Infinite); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just be aware that we'll need to set the timer to disabled in StopAsync
when Pawel's PR goes in
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep
@@ -85,6 +85,9 @@ internal static class SignalRClientLoggerExtensions | |||
private static readonly Action<ILogger, string, string, string, int, Exception> _preparingStreamingInvocation = | |||
LoggerMessage.Define<string, string, string, int>(LogLevel.Trace, new EventId(24, nameof(PreparingStreamingInvocation)), "Preparing streaming invocation '{invocationId}' of '{target}', with return type '{returnType}' and {argumentCount} argument(s)."); | |||
|
|||
private static readonly Action<ILogger, Exception> _resettingKeepAliveTimer = | |||
LoggerMessage.Define(LogLevel.Trace, new EventId(25, nameof(ResettingKeepAliveTimer)), "Resetting keep-alive timer, received a message from the server"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
period at the end
|
||
hubConnection.ServerTimeout = TimeSpan.FromMilliseconds(100); | ||
|
||
await hubConnection.StartAsync(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OrTimeout
try | ||
{ | ||
await connection.ReceiveJsonMessage(new { type = HubProtocolConstants.PingMessageType }); | ||
await Task.Delay(50); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OrTimeout
|
||
hubConnection.ServerTimeout = TimeSpan.FromMilliseconds(100); | ||
|
||
await hubConnection.StartAsync(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mOrTimeout
Add client timeout to C# client. It is configurable via an option and defaults to 30 seconds (the server ping rate defaults to 15 seconds, so this is effectively 2 server ping intervals).
NOTE: Should not be merged until #1161 is merged since it will immediately break any connection that goes idle for 30 seconds :).
Fixes #1157