protected void OnReceiveMessage(ReceiveMessage message) { ATL.WriteLine($"Subscriber received: {message}"); switch (message.Type) { case ReceiveMessage.SubscribeType: { if (message.Data is SubscriptionMessageData _data && _data.StatusCode == ReceiveMessageStatusCode.Success) { ConfirmSubscribed(_data.Path); } break; } case ReceiveMessage.UnsubscribeType: { if (message.Data is SubscriptionMessageData _data && _data.StatusCode == ReceiveMessageStatusCode.Success) { RemoveSubscribed(_data.Path); } break; } case ReceiveMessage.ChangedType: { if (message.Data is IEnumerable <ConfigKey> _configKeys) { // Raises receive callback. m_ReceiveCallback(_configKeys); } break; } case ReceiveMessage.DeletedType: { if (message.Data is string _path) { RemoveSubscribed(_path); // Raises deleted callback. m_DeletedCallback(_path); } break; } } }
protected async Task ConnectAsync(CancellationToken cancellationToken) { // Creates socket client. var _client = new TSocketClient(); _client.SetRequestHeader(AppIdName, Settings.ApplicationId); // Connects the web socket. await _client.ConnectAsync(GetSubscribeUrl(Settings.ApiUrl), cancellationToken).ConfigureAwait(true); // Try to dispose previous websocket. if (m_Client != null) { m_Client.Dispose(); } m_Client = _client; ATL.WriteLine("Subscriber connected"); }
private async Task Reconnect(CancellationToken cancellationToken) { ATL.WriteLine("Subscriber reconnecting"); await m_SyncRoot.WaitAsync(m_CancellationTokenSource.Token); var _subscribed = m_Subscribed; var _initialized = m_Initialized; try { // Reset internals before reconnect. m_Initialized = false; m_Subscribed = null; foreach (var _item in _subscribed) { if (_item.Confirmed) { await SubscribeAsyncInternal(_item.Path, _item.Properties, cancellationToken); } } ATL.WriteLine("Subscriber reconnected"); } catch (Exception _ex) { ATL.WriteLine("Subscriber reconnect failed"); // Restore internals. m_Initialized = _initialized; m_Subscribed = _subscribed; // Throw connection closed exception to attemp reconnect again. throw new ConnectionClosedException(true, (_ex as WebSocketException)?.ErrorCode ?? 0, _ex); } finally { m_SyncRoot.Release(); } }
private void ReceiveImpl(Task _) { if (Interlocked.CompareExchange(ref m_ReceiveState, m_RECEIVE_STATE_ACTIVE, m_RECEIVE_STATE_NONE) != m_RECEIVE_STATE_NONE) { return; } var _cancellationToken = m_CancellationTokenSource.Token; Task.Run(async() => { var _reconnectCounter = 0; var _reconnect = false; do { try { // Try reconnect if requires. if (_reconnect) { // Delay before reconnect. // Delay time will increase till 5 minutes of end. // Used fot this following formula: initial * (log(counter, increase_factor) + 1) => maximum is 5 minutes, initial is 30 seconds. // To skip increasing delay have to set 0 for ReconnectInitDelay. var _delay = (int)(ReconnectInitDelay * (Math.Log(++_reconnectCounter, 10.88632d) + 1)); if (_delay < 1) { _delay = 1; } Debug.WriteLine($"Reconnects after {_delay / 1000} seconds"); await Task.Delay(_delay, _cancellationToken); // Reconnect the all subscriptions. Debug.WriteLine("Reconnecting"); await Reconnect(_cancellationToken); } while (!_cancellationToken.IsCancellationRequested) { var _memory = new MemoryStream(); try { // Received respose from source. if (await ReceiveAsync(_memory, _cancellationToken)) { // Gets received message. _memory.Seek(0, SeekOrigin.Begin); var _message = JsonSerializer.Deserialize <ReceiveMessage>(_memory); // Invokes implementation of after receive message. OnReceiveMessage(_message); } } catch (ConnectionClosedException _ex) { ATL.WriteLine($"Subscriber closed({_ex.ErrorCode})"); throw; } catch (OperationCanceledException) { throw; } catch (Exception _ex) { Debug.WriteLine($"Occured error: {_ex.Message}"); } } } catch (OperationCanceledException) { Debug.WriteLine("Cancelled"); _reconnect = false; } catch (ConnectionClosedException _ex) { Debug.WriteLine($"Disconnected ({_ex.ErrorCode})"); _reconnect = _ex.Reconnect && Settings.ReconnectSubscriptions; if (!_reconnect) { throw; } } catch (Exception _ex) { Debug.WriteLine($"Occured error: {_ex.Message}"); _reconnect = false; } }while (_reconnect && !_cancellationToken.IsCancellationRequested); }, _cancellationToken); }
protected async Task SendCommandAsync(WsCommand command, CancellationToken cancellationToken) { await m_Client.SendAsync(command.GetBinary(), WebSocketMessageType.Text, true, cancellationToken); ATL.WriteLine($"Subscriber send: {command}"); }