private async Task ConnectCore() { ConnectStatus = Status.Connecting; var now = DateTimeOffset.UtcNow; if (now - _lastAuthTime > AuthExpire) { (string url, string accessToken) = await GetAuth(); if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(accessToken)) { throw new ArgumentNullException("url or accesstoken is null"); } if (Connection != null) { Connection.Closed -= OnClosed; // 1. dispose the old connection first await Connection.DisposeAsync(); Connection = null; } var connection = new HubConnectionBuilder() .WithUrl(url, options => //.WithUrl("http://localhost:8080/client?hub=gamehub", options => { options.AccessTokenProvider = () => Task.FromResult(accessToken); options.CloseTimeout = TimeSpan.FromSeconds(15); options.Transports = HttpTransportType.WebSockets; options.SkipNegotiation = true; }) //.AddMessagePackProtocol() .Build(); connection.Closed += OnClosed; connection.On("Connected", () => { ConnectStatus = Status.Connected; Interlocked.Increment(ref ConnectStats.SuccessCount); var elapsed = ConnectStats.SetElapsed(_lastConnectTime); }); connection.On <MessageBody>("PerformanceTest", message => { Interlocked.Increment(ref SendMessageStats.ReceivedCount); SendMessageStats.SetElapsed(message.CreatedTime); }); // set the auth time after the connection is built _lastAuthTime = DateTime.UtcNow; Connection = connection; } _lastConnectTime = DateTime.UtcNow; Interlocked.Increment(ref ConnectStats.TotalCount); await Connection.StartAsync(); }
public async Task Connect() { if (IsConnected || IsConnecting) { return; } IsConnecting = true; await Task.Yield(); _lastAuthTime = DateTime.Now; (string url, string accessToken) = GetAuth(); if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(accessToken)) { throw new ArgumentNullException("url or accesstoken is null"); } connection = new HubConnectionBuilder() .WithUrl(url, options => { options.AccessTokenProvider = () => Task.FromResult(accessToken); options.CloseTimeout = TimeSpan.FromSeconds(15); options.Transports = HttpTransportType.WebSockets; options.SkipNegotiation = true; }) //.AddMessagePackProtocol() .Build(); connection.Closed += ex => { IsConnected = false; IsConnecting = false; return(RetryConnect(ex)); }; connection.On("Connected", () => { Interlocked.Increment(ref ConnectStats.SuccessCount); var elapsed = ConnectStats.SetElapsed(lastConnectTime); IsConnected = true; IsConnecting = false; }); connection.On <MessageBody>("PerformanceTest", message => { Interlocked.Increment(ref SendMessageStats.ReceivedCount); SendMessageStats.SetElapsed(message.CreatedTime); }); await ConnectCore(); }
private async Task RetryConnect(Exception ex) { if (!_connectLock.Wait(0)) { // someone is already connecting return; } try { if (ex != null) { ConnectStats.AddException(ex); Interlocked.Increment(ref ConnectStats.ErrorCount); } var reconnectNow = DateTime.UtcNow; while (true) { try { // delay a random value < 3s await Task.Delay(new Random((int)Stopwatch.GetTimestamp()).Next(MinReconnectWaitMilliseconds, MaxReconnectWaitMilliseconds)); await ConnectCore(); RecoverStats.SetElapsed(reconnectNow); Interlocked.Increment(ref RecoverStats.SuccessCount); break; } catch (Exception e) { RecoverStats.AddException(e); Interlocked.Increment(ref RecoverStats.ErrorCount); Interlocked.Increment(ref ConnectStats.ErrorCount); } } } finally { _connectLock.Release(); } }
private async Task RetryConnect(Exception ex) { ConnectStats.AddException(ex); Interlocked.Increment(ref ConnectStats.ErrorCount); var reconnectNow = DateTime.Now; while (true) { try { await Task.Delay(new Random((int)Stopwatch.GetTimestamp()).Next(300, 20000)); if (DateTime.Now > _lastAuthTime.AddMinutes(50)) { // Reauth await Connect(); } else { // direct connect await ConnectCore(); } RecoverStats.SetElapsed(reconnectNow); Interlocked.Increment(ref RecoverStats.SuccessCount); break; } catch (Exception e) { RecoverStats.AddException(e); Interlocked.Increment(ref RecoverStats.ErrorCount); Interlocked.Increment(ref ConnectStats.NotSentCount); // another round after 300 } } }