예제 #1
0
        private async Task ReadPipeAsync()
        {
            Exception shutdownReason  = null;
            Exception unexpectedError = null;

            try
            {
                await ProcessMessagesAsync();
            }
            catch (Exception ex)
                when((ex is SocketException socketEx && IsConnectionAbortError(socketEx.SocketErrorCode)) ||
                     ex is ObjectDisposedException)
                {
                    // This should always be ignored since Shutdown() must have already been called by Abort().
                    shutdownReason = ex;
                }
            catch (Exception ex)
            {
                shutdownReason  = ex;
                unexpectedError = ex;
                _logger.LogTrace(unexpectedError);
            }
            finally
            {
                Shutdown(shutdownReason);

                // Complete the output after disposing the socket
                ReaderPipe.Complete(unexpectedError);

                // Cancel any pending flushes so that the input loop is un-paused
                ReceiverPipe.CancelPendingFlush();
            }
        }
예제 #2
0
        private async Task ProcessMessagesAsync()
        {
            while (true)
            {
                var result = await ReaderPipe.ReadAsync();

                if (result.IsCanceled)
                {
                    break;
                }

                var buffer = result.Buffer;

                var end = buffer.End;

                var isCompleted = result.IsCompleted;

                if (!buffer.IsEmpty)
                {
                    //SequenceReader is not allowed in async methods :(
                    foreach (var seg in buffer)
                    {
                        if (!seg.IsEmpty)
                        {
                            await _handlerMapper.HandleAsync(seg);
                        }
                    }
                }

                ReaderPipe.AdvanceTo(end);

                if (isCompleted)
                {
                    break;
                }
            }
        }
예제 #3
0
        public static async Task Replicate(
            IEventReader reader,
            SinkPipeOptions sinkPipeOptions,
            PreparePipelineOptions preparePipeOptions,
            ICheckpointStore checkpointStore,
            CancellationToken stoppingToken,
            bool restartWhenComplete = false
            )
        {
            ReplicationMetrics.SetCapacity(preparePipeOptions.BufferSize, sinkPipeOptions.BufferSize);

            var cts = new CancellationTokenSource();

            var linkedCts =
                CancellationTokenSource.CreateLinkedTokenSource(stoppingToken, cts.Token);

            var prepareChannel = Channel.CreateBounded <PrepareContext>(preparePipeOptions.BufferSize);
            var sinkChannel    = Channel.CreateBounded <SinkContext>(sinkPipeOptions.BufferSize);

            var readerPipe = new ReaderPipe(
                reader,
                checkpointStore,
                ctx => prepareChannel.Writer.WriteAsync(ctx, ctx.CancellationToken)
                );

            var preparePipe = new PreparePipe(
                preparePipeOptions.Filter,
                preparePipeOptions.Transform,
                ctx => sinkChannel.Writer.WriteAsync(ctx, ctx.CancellationToken)
                );
            var sinkPipe = new SinkPipe(sinkPipeOptions, checkpointStore);

            var prepareTask = CreateChannelShovel(
                "Prepare",
                prepareChannel,
                preparePipe.Send,
                ReplicationMetrics.PrepareChannelSize,
                linkedCts.Token
                );

            var writerTask = CreateChannelShovel(
                "Writer",
                sinkChannel,
                sinkPipe.Send,
                ReplicationMetrics.SinkChannelSize,
                CancellationToken.None
                );
            var reporter = Task.Run(Report, stoppingToken);

            while (true)
            {
                ReplicationStatus.Start();

                await readerPipe.Start(linkedCts.Token).ConfigureAwait(false);

                if (!restartWhenComplete)
                {
                    do
                    {
                        Log.Info("Closing the prepare channel...");
                        await Task.Delay(1000, CancellationToken.None).ConfigureAwait(false);
                    } while (!prepareChannel.Writer.TryComplete());
                }

                ReplicationStatus.Stop();

                while (sinkChannel.Reader.Count > 0)
                {
                    await checkpointStore.Flush(CancellationToken.None).ConfigureAwait(false);

                    Log.Info("Waiting for the sink pipe to exhaust ({Left} left)...", sinkChannel.Reader.Count);
                    await Task.Delay(1000, CancellationToken.None).ConfigureAwait(false);
                }

                Log.Info("Storing the last known checkpoint");
                await checkpointStore.Flush(CancellationToken.None).ConfigureAwait(false);

                if (linkedCts.IsCancellationRequested || !restartWhenComplete)
                {
                    sinkChannel.Writer.Complete();
                    break;
                }

                Log.Info("Will restart in 5 sec");
                await Task.Delay(5000, stoppingToken);
            }

            try {
                await prepareTask.ConfigureAwait(false);

                await writerTask.ConfigureAwait(false);

                await reporter.ConfigureAwait(false);
            }
            catch (OperationCanceledException) { }