public SyncService(IDomainWebsocketClient client)
        {
            // -- websockets
            this.websocketClient                    = client;
            this.websocketClient.OnMessage         += HandleMessage;
            this.websocketClient.OnConnectionError += OnConnectionError;

            // -- push/poll
            this.push = new PushService(this.websocketClient);
            this.push.OnSendFailed += PushOnOnSendFailed;
            this.poll = new PollService();

            // -- state machine
            this.stateMachine = new StateMachine <State, Trigger>(State.Idle, FiringMode.Queued);
            this.stateMachine.OnTransitioned(OnTransitioned);
            this.stateMachine.OnUnhandledTrigger((state, trigger) =>
            {
                Logger.Debug($"Unhandled trigger: {trigger} [{state}]");
            });

            this.VersionFetcher = new HttpVersionFetcher();

            InitStateMachine();
            this.scheduleStopWatch.Start();
        }
        private async Task <bool> InternalAssertConnected(CancellationToken cancellationToken)
        {
            if (this.client != null &&
                this.wsClient != null &&
                this.wsClient.IsConnected &&
                !this.receiveMessagesCts.IsCancellationRequested)
            {
                Logger.Trace("Already connected");
                return(false);
            }

            var retryCount = 0;

            do
            {
                try
                {
                    this.receiveMessagesCts.Cancel();
                    await this.messageLoopTask;
                    Logger.Trace("Message loop task finished");
                    this.receiveMessagesCts = new CancellationTokenSource();

                    this.client   = new WebSocketClient(this.options);
                    this.wsClient = await this.client.ConnectAsync(this.Endpoint, cancellationToken);

                    this.messageLoopTask = Task.Run(() => ReceiveMessagesLoop(this.receiveMessagesCts.Token), cancellationToken);

                    Logger.Log("Connected to server");
                    return(true);
                }
                catch (OperationCanceledException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    Logger.Warn($"Connection failed, retry {++retryCount}/10");
                    Logger.Debug($"{ex}");
                    await Task.Delay(2000, cancellationToken);
                }
            } while (retryCount < 10);

            throw new WebsocketConnectionFailedException();
        }