Example #1
0
        private async Task ProccessSubscription(TaskCompletionSource <object> successfullyConnected)
        {
            try
            {
                _proccessingCts.Token.ThrowIfCancellationRequested();
                using (var context = new JsonOperationContext(4096, 1024))
                {
                    using (var tcpStream = await ConnectToServer().ConfigureAwait(false))
                        using (var parser = context.ParseMultiFrom(tcpStream))
                        {
                            _proccessingCts.Token.ThrowIfCancellationRequested();
                            var readObjectTask = ReadNextObject(parser);
                            var done           = await Task.WhenAny(readObjectTask, _disposedTask.Task).ConfigureAwait(false);

                            if (done == _disposedTask.Task)
                            {
                                return;
                            }
                            var connectionStatus = await readObjectTask.ConfigureAwait(false);

                            if (_proccessingCts.IsCancellationRequested)
                            {
                                return;
                            }

                            AssertConnectionState(connectionStatus);

#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
                            Task.Run(() => successfullyConnected.TrySetResult(null));
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed

                            readObjectTask = ReadNextObject(parser);

                            if (_proccessingCts.IsCancellationRequested)
                            {
                                return;
                            }

                            var  incomingBatch    = new List <BlittableJsonReaderObject>();
                            long lastReceivedEtag = 0;

                            while (_proccessingCts.IsCancellationRequested == false)
                            {
                                BeforeBatch();
                                bool endOfBatch = false;
                                while (endOfBatch == false && _proccessingCts.IsCancellationRequested == false)
                                {
                                    done = await Task.WhenAny(readObjectTask, _disposedTask.Task).ConfigureAwait(false);

                                    if (done == _disposedTask.Task)
                                    {
                                        break;
                                    }
                                    var receivedMessage = await readObjectTask.ConfigureAwait(false);

                                    if (_proccessingCts.IsCancellationRequested)
                                    {
                                        break;
                                    }

                                    readObjectTask = ReadNextObject(parser);

                                    if (_proccessingCts.IsCancellationRequested)
                                    {
                                        break;
                                    }

                                    switch (receivedMessage.Type)
                                    {
                                    case SubscriptionConnectionServerMessage.MessageType.Data:
                                        incomingBatch.Add(receivedMessage.Data);
                                        break;

                                    case SubscriptionConnectionServerMessage.MessageType.EndOfBatch:
                                        endOfBatch = true;
                                        break;

                                    case SubscriptionConnectionServerMessage.MessageType.Confirm:
                                        AfterAcknowledgment();
                                        AfterBatch(incomingBatch.Count);
                                        incomingBatch.Clear();
                                        break;

                                    case SubscriptionConnectionServerMessage.MessageType.Error:
                                        switch (receivedMessage.Status)
                                        {
                                        case SubscriptionConnectionServerMessage.ConnectionStatus.Closed:
                                            throw new SubscriptionClosedException(receivedMessage.Exception ??
                                                                                  string.Empty);

                                        default:
                                            throw new Exception(
                                                      $"Connection terminated by server. Exception: {receivedMessage.Exception ?? "None"}");
                                        }

                                    default:
                                        throw new ArgumentException(
                                                  $"Unrecognized message '{receivedMessage.Type}' type received from server");
                                    }
                                }

                                foreach (var curDoc in incomingBatch)
                                {
                                    NotifySubscribers(curDoc, out lastReceivedEtag);
                                }

                                SendAck(lastReceivedEtag, tcpStream);
                            }
                        }
                }
            }
            catch (OperationCanceledException)
            {
            }
            catch (Exception ex)
            {
                if (_proccessingCts.Token.IsCancellationRequested == false)
                {
                    InformSubscribersOnError(ex);
                }
                throw;
            }
        }