/// <summary> /// The main loop of a partition pump. It receives events from the Azure Event Hubs service /// and delegates their processing to the event processor processing handlers. /// </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) { List <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 && unrecoverableException == null) { try { receivedEvents = (await InnerConsumer.ReceiveAsync(MaximumMessageCount, Options.MaximumReceiveWaitTime, cancellationToken).ConfigureAwait(false)).ToList(); 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); } } } // Small workaround to make sure we call ProcessEvent with EventData = null when no events have been received. // The code is expected to get simpler when we start using the async enumerator internally to receive events. if (receivedEvents.Count == 0) { receivedEvents.Add(null); } diagnosticScope.Start(); foreach (var eventData in receivedEvents) { try { var processorEvent = new EventProcessorEvent(Context, eventData, OwnerEventProcessor.UpdateCheckpointAsync); await OwnerEventProcessor.ProcessEventAsync(processorEvent).ConfigureAwait(false); } catch (Exception eventProcessingException) { diagnosticScope.Failed(eventProcessingException); unrecoverableException = eventProcessingException; CloseReason = CloseReason.Exception; break; } } } catch (Exception eventHubException) { // Stop running only if it's not a retriable exception. if (RetryPolicy.CalculateRetryDelay(eventHubException, 1) == null) { unrecoverableException = eventHubException; CloseReason = CloseReason.Exception; break; } } } if (unrecoverableException != null) { // In case an exception is thrown by ProcessExceptionAsync, don't catch it and // let the calling method (StopAsync) handle it. var errorContext = new ProcessorErrorContext(Context.PartitionId, unrecoverableException); await OwnerEventProcessor.ProcessExceptionAsync(errorContext).ConfigureAwait(false); } }
/// <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(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 OwnerEventProcessor.ProcessEventsAsync(Context, receivedEvents).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 (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 OwnerEventProcessor.ProcessExceptionAsync(Context, unrecoverableException).ConfigureAwait(false); } }