/// <summary>
        ///   Stops the partition pump.  In case it hasn't been started, nothing happens.
        /// </summary>
        ///
        /// <param name="reason">The reason why the partition pump is being closed.</param>
        ///
        /// <returns>A task to be resolved on when the operation has completed.</returns>
        ///
        private async Task StopAsync(PartitionProcessorCloseReason reason)
        {
            if (RunningTask != null)
            {
                await RunningTaskSemaphore.WaitAsync().ConfigureAwait(false);

                try
                {
                    if (RunningTask != null)
                    {
                        RunningTaskTokenSource.Cancel();
                        RunningTaskTokenSource = null;

                        try
                        {
                            await RunningTask.ConfigureAwait(false);
                        }
                        finally
                        {
                            RunningTask = null;
                        }

                        await InnerConsumer.CloseAsync().ConfigureAwait(false);

                        InnerConsumer = null;

                        await PartitionProcessor.CloseAsync(reason).ConfigureAwait(false);
                    }
                }
                finally
                {
                    RunningTaskSemaphore.Release();
                }
            }
        }
示例#2
0
        /// <summary>
        ///   Stops the partition pump.  In case it isn't running, nothing happens.
        /// </summary>
        ///
        /// <param name="reason">The reason why the associated partition processor is being closed.  In case it's <c>null</c>, the internal close reason set by this pump is used.</param>
        ///
        /// <returns>A task to be resolved on when the operation has completed.</returns>
        ///
        public async Task StopAsync(PartitionProcessorCloseReason?reason)
        {
            if (RunningTask != null)
            {
                await RunningTaskSemaphore.WaitAsync().ConfigureAwait(false);

                try
                {
                    if (RunningTask != null)
                    {
                        RunningTaskTokenSource.Cancel();
                        RunningTaskTokenSource = null;

                        try
                        {
                            // RunningTask is only expected to fail when the partition processor throws while processing
                            // an error, but unforeseen scenarios might happen.

                            await RunningTask.ConfigureAwait(false);
                        }
                        catch (Exception)
                        {
                            // TODO: delegate the exception handling to an Exception Callback.
                        }

                        RunningTask = null;

                        // It's important to close the consumer as soon as possible.  Failing to do so multiple times
                        // would make it impossible to create more consumers for the associated partition as there's a
                        // limit per client.

                        await InnerConsumer.CloseAsync().ConfigureAwait(false);

                        // In case an exception is encountered while partition processor is closing, don't catch it and
                        // let the event processor handle it.  The pump has no way to guess when a partition was lost or
                        // when a shutdown request was sent to the event processor, so it expects a "reason" parameter to
                        // provide this information.  However, in case of pump failure, the external event processor does
                        // not have enough information to figure out what failure reason to use, as this information is
                        // only known by the pump.  In this case, we expect the processor-provided reason to be null, and
                        // the private CloseReason is used instead.

                        await PartitionProcessor.CloseAsync(Context, reason ?? CloseReason).ConfigureAwait(false);
                    }
                }
                finally
                {
                    RunningTaskSemaphore.Release();
                }
            }
        }