Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.

Implement #1157 by adding client timeout for C# client #1165

Merged
merged 13 commits into from
Dec 7, 2017

Conversation

analogrelay
Copy link
Contributor

@analogrelay analogrelay commented Nov 29, 2017

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


public Task Closed { get; }

/// <summary>
/// Gets or sets the server timeout interval for the connection. Changes to this value
Copy link
Member

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
Copy link
Member

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))
Copy link
Member

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)
Copy link
Member

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;
Copy link
Member

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);
Copy link
Member

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

Copy link
Contributor Author

@analogrelay analogrelay Nov 29, 2017

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.

Copy link

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);
Copy link
Member

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.

Copy link
Contributor Author

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)
Copy link
Member

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

Copy link
Contributor Author

@analogrelay analogrelay Dec 4, 2017

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 });
Copy link
Member

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?

Copy link
Contributor Author

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;
Copy link
Member

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;
Copy link
Member

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."));
Copy link

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?

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link

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. :)

Copy link
Contributor Author

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

@analogrelay analogrelay force-pushed the anurse/1157-cs-client-timeout branch from d94a33f to 7808a40 Compare December 4, 2017 18:40
@analogrelay analogrelay force-pushed the anurse/1157-cs-client-timeout branch from 7808a40 to db3b58e Compare December 5, 2017 00:23

public Task Closed { get; }

/// <summary>
/// Gets or sets the server timeout interval for the connection. Changes to this value
Copy link
Member

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);
Copy link
Member

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

Copy link
Contributor Author

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");
Copy link
Member

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();
Copy link
Member

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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OrTimeout :trollface:


hubConnection.ServerTimeout = TimeSpan.FromMilliseconds(100);

await hubConnection.StartAsync();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mOrTimeout

@analogrelay analogrelay merged commit a833006 into dev Dec 7, 2017
@analogrelay analogrelay deleted the anurse/1157-cs-client-timeout branch December 7, 2017 22:54
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants