/// <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();
                }
            }
        }
Example #2
0
            /// <summary>
            ///   Closes the partition processor.
            /// </summary>
            ///
            /// <param name="reason">The reason why the partition processor is being closed.</param>
            ///
            /// <returns>A task to be resolved on when the operation has completed.</returns>
            ///
            public Task CloseAsync(PartitionProcessorCloseReason reason)
            {
                // The code to be run when closing the partition processor.  This is the right place to dispose
                // of objects that will no longer be used.

                Console.WriteLine($"\tPartition '{ PartitionId }': partition processor successfully closed. Reason: { reason }.");

                // This method is asynchronous, which means it's expected to return a Task.

                return(Task.CompletedTask);
            }
            /// <summary>
            ///   Closes the partition processor.
            /// </summary>
            ///
            /// <param name="partitionContext">Contains information about the partition from which events are sourced and provides a means of creating checkpoints for that partition.</param>
            /// <param name="reason">The reason why the partition processor is being closed.</param>
            ///
            /// <returns>A task to be resolved on when the operation has completed.</returns>
            ///
            public override Task CloseAsync(PartitionContext partitionContext,
                                            PartitionProcessorCloseReason reason)
            {
                // The code to be run when closing the partition processor.  This is the right place to dispose
                // of objects that will no longer be used.

                Interlocked.Decrement(ref s_activeInstancesCount);

                Console.WriteLine($"\tPartition '{ partitionContext.PartitionId }': partition processor successfully closed. Reason: { reason }.");

                // This method is asynchronous, which means it's expected to return a Task.

                return(Task.CompletedTask);
            }
Example #4
0
        /// <summary>
        ///   The main loop of a partition pump.  It receives events from the Azure Event Hubs service
        ///   and delegates their processing to the inner partition processor.
        /// </summary>
        ///
        /// <param name="cancellationToken">A <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        /// <returns>A task to be resolved on when the operation has completed.</returns>
        ///
        private async Task RunAsync(CancellationToken cancellationToken)
        {
            IEnumerable <EventData> receivedEvents;
            Exception unrecoverableException = null;

            // We'll break from the loop upon encountering a non-retriable exception.  The event processor periodically
            // checks its pumps' status, so it should be aware of when one of them stops working.

            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    receivedEvents = await InnerConsumer.ReceiveAsync(Options.MaximumMessageCount, Options.MaximumReceiveWaitTime, cancellationToken).ConfigureAwait(false);

                    try
                    {
                        await PartitionProcessor.ProcessEventsAsync(Context, receivedEvents, cancellationToken).ConfigureAwait(false);
                    }
                    catch (Exception partitionProcessorException)
                    {
                        unrecoverableException = partitionProcessorException;
                        CloseReason            = PartitionProcessorCloseReason.PartitionProcessorException;

                        break;
                    }
                }
                catch (Exception eventHubException)
                {
                    // Stop running only if it's not a retriable exception.

                    if (RetryPolicy.CalculateRetryDelay(eventHubException, 1) == null)
                    {
                        unrecoverableException = eventHubException;
                        CloseReason            = PartitionProcessorCloseReason.EventHubException;

                        break;
                    }
                }
            }

            if (unrecoverableException != null)
            {
                // In case an exception is encountered while partition processor is processing the error, don't
                // catch it and let the calling method (StopAsync) handle it.

                await PartitionProcessor.ProcessErrorAsync(Context, unrecoverableException, cancellationToken).ConfigureAwait(false);
            }
        }
Example #5
0
 /// <summary>
 ///   Closes the partition processor.
 /// </summary>
 ///
 /// <param name="reason">The reason why the partition processor is being closed.</param>
 ///
 /// <returns>A task to be resolved on when the operation has completed.</returns>
 ///
 public Task CloseAsync(PartitionProcessorCloseReason reason)
 {
     OnClose?.Invoke(AssociatedPartitionContext, AssociatedCheckpointManager, reason);
     return(Task.CompletedTask);
 }
Example #6
0
 /// <summary>
 ///   Closes the partition processor.
 /// </summary>
 ///
 /// <param name="partitionContext">Contains information about the partition from which events are sourced and provides a means of creating checkpoints for that partition.</param>
 /// <param name="reason">The reason why the partition processor is being closed.</param>
 ///
 /// <returns>A task to be resolved on when the operation has completed.</returns>
 ///
 public override Task CloseAsync(PartitionContext partitionContext,
                                 PartitionProcessorCloseReason reason)
 {
     OnClose?.Invoke(partitionContext, reason);
     return(Task.CompletedTask);
 }
        /// <summary>
        ///   The main loop of a partition pump.  It receives events from the Azure Event Hubs service
        ///   and delegates their processing to the inner partition processor.
        /// </summary>
        ///
        /// <param name="cancellationToken">A <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param>
        ///
        /// <returns>A task to be resolved on when the operation has completed.</returns>
        ///
        private async Task RunAsync(CancellationToken cancellationToken)
        {
            IEnumerable <EventData> receivedEvents;
            Exception unrecoverableException = null;

            // We'll break from the loop upon encountering a non-retriable exception.  The event processor periodically
            // checks its pumps' status, so it should be aware of when one of them stops working.

            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    receivedEvents = await InnerConsumer.ReceiveAsync(Options.MaximumMessageCount, Options.MaximumReceiveWaitTime, cancellationToken).ConfigureAwait(false);

                    using DiagnosticScope diagnosticScope = EventDataInstrumentation.ClientDiagnostics.CreateScope(DiagnosticProperty.EventProcessorProcessingActivityName);
                    diagnosticScope.AddAttribute("kind", "server");

                    if (diagnosticScope.IsEnabled)
                    {
                        foreach (var eventData in receivedEvents)
                        {
                            if (EventDataInstrumentation.TryExtractDiagnosticId(eventData, out string diagnosticId))
                            {
                                diagnosticScope.AddLink(diagnosticId);
                            }
                        }
                    }

                    diagnosticScope.Start();

                    try
                    {
                        await PartitionProcessor.ProcessEventsAsync(Context, receivedEvents, cancellationToken).ConfigureAwait(false);
                    }
                    catch (Exception partitionProcessorException)
                    {
                        diagnosticScope.Failed(partitionProcessorException);
                        unrecoverableException = partitionProcessorException;
                        CloseReason            = PartitionProcessorCloseReason.PartitionProcessorException;

                        break;
                    }
                }
                catch (Exception eventHubException)
                {
                    // Stop running only if it's not a retriable exception.

                    if (s_retryPolicy.CalculateRetryDelay(eventHubException, 1) == null)
                    {
                        unrecoverableException = eventHubException;
                        CloseReason            = PartitionProcessorCloseReason.EventHubException;

                        break;
                    }
                }
            }

            if (unrecoverableException != null)
            {
                // In case an exception is encountered while partition processor is processing the error, don't
                // catch it and let the calling method (StopAsync) handle it.

                await PartitionProcessor.ProcessErrorAsync(Context, unrecoverableException, cancellationToken).ConfigureAwait(false);
            }
        }
 /// <summary>
 ///   Closes the partition processor.
 /// </summary>
 ///
 /// <param name="partitionContext">Contains information about the partition from which events are sourced and provides a means of creating checkpoints for that partition.</param>
 /// <param name="reason">The reason why the partition processor is being closed.</param>
 ///
 /// <returns>A task to be resolved on when the operation has completed.</returns>
 ///
 public virtual Task CloseAsync(PartitionContext partitionContext,
                                PartitionProcessorCloseReason reason)
 {
     return(Task.CompletedTask);
 }