/// <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(); } } }
/// <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); }
/// <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); } }
/// <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); }
/// <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); }