/// <summary> /// Stops an owned partition processing task in case it is running. It is also removed from the tasks dictionary /// along with its corresponding token source. /// </summary> /// /// <param name="partitionId">The identifier of the Event Hub partition whose processing is being stopped.</param> /// <param name="reason">The reason why the processing for the specified partition is being stopped.</param> /// /// <returns>A task to be resolved on when the operation has completed.</returns> /// private async Task StopPartitionProcessingIfRunningAsync(string partitionId, ProcessingStoppedReason reason) { if (ActivePartitionProcessors.TryRemove(partitionId, out var processingTask) && ActivePartitionProcessorTokenSources.TryRemove(partitionId, out var tokenSource)) { try { tokenSource.Cancel(); await processingTask.ConfigureAwait(false); } catch (Exception ex) when(ex is TaskCanceledException || ex is OperationCanceledException) { // Nothing to do here. These exceptions are expected. } catch (Exception) { // TODO: delegate the exception handling to an Exception Callback. } finally { tokenSource.Dispose(); } } // TODO: if reason = Shutdown or OwnershipLost and we got an exception when closing, what should the final reason be? PartitionContexts.TryRemove(partitionId, out var context); await ProcessingForPartitionStoppedAsync(reason, context); }
protected override Task OnPartitionProcessingStoppedAsync( EventProcessorPartition partition, ProcessingStoppedReason reason, CancellationToken cancellationToken) { try { Console.WriteLine( $"No longer processing partition { partition.PartitionId } " + $"because { reason }"); } catch (Exception ex) { // It is very important that you always guard against exceptions in // your handler code; the processor does not have enough // understanding of your code to determine the correct action to take. // Any exceptions from your handlers go uncaught by the processor and // will NOT be redirected to the error handler. // // In this case, unhandled exceptions will not impact the processor // operation but will go unobserved, hiding potential application problems. Console.WriteLine($"Exception while stopping processing for a partition: { ex }"); } return(Task.CompletedTask); }
/// <summary> /// Invokes the processor infrastructure method responsible for stopping a partition /// processing task, using its private accessor. /// </summary> /// /// <typeparam name="T">The partition type to which the processor is bound.</typeparam> /// /// <param name="processor">The processor instance to operate on.</param> /// <param name="partitionId">The identifier of the Event Hub partition whose processing should be stopped.</param> /// <param name="reason">The reason why the processing is being stopped.</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param> /// /// <returns><c>true</c> if the <paramref name="partitionId"/> was owned and was being processed; otherwise, <c>false</c>.</returns> /// private static Task <bool> InvokeTryStopProcessingPartitionAsync <T>(EventProcessor <T> processor, string partitionId, ProcessingStoppedReason reason, CancellationToken cancellationToken) where T : EventProcessorPartition, new() => (Task <bool>) typeof(EventProcessor <T>) .GetMethod("TryStopProcessingPartitionAsync", BindingFlags.Instance | BindingFlags.NonPublic) .Invoke(processor, new object[] { partitionId, reason, cancellationToken });
/// <summary> /// Initializes a new instance of the <see cref="PartitionProcessingStoppedContext"/> class. /// </summary> /// /// <param name="partitionContext">The context of the Event Hub partition this instance is associated with.</param> /// <param name="reason">The reason why the processing for the associated partition is being stopped.</param> /// protected internal PartitionProcessingStoppedContext(PartitionContext partitionContext, ProcessingStoppedReason reason) { Argument.AssertNotNull(partitionContext, nameof(partitionContext)); Context = partitionContext; Reason = reason; }
public virtual void StopPartitionProcessingComplete(string partitionId, ProcessingStoppedReason reason) { if (IsEnabled()) { WriteEvent(21, partitionId ?? string.Empty, reason); } }
protected override Task ProcessorStoppingAsync(ProcessingStoppedReason reason, CancellationToken cancellationToken) { var baseMessageCount = base.MessageCount; Interlocked.Add(ref Program.TotalMessageCount, MessageCount); return(base.ProcessorStoppingAsync(reason, cancellationToken)); }
public Task CloseAsync(EventProcessorHostPartition context, ProcessingStoppedReason reason) { // signal cancellation for any in progress executions _cts.Cancel(); _logger.LogDebug(GetOperationDetails(context, $"CloseAsync, {reason.ToString()}")); return(Task.CompletedTask); }
/// <summary> /// Initializes a new instance of the <see cref="PartitionClosingEventArgs"/> class. /// </summary> /// /// <param name="partitionId">The identifier of the Event Hub partition this instance is associated with.</param> /// <param name="reason">The reason why the processing for the associated partition is being stopped.</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param> /// public PartitionClosingEventArgs(string partitionId, ProcessingStoppedReason reason, CancellationToken cancellationToken = default) { Argument.AssertNotNullOrEmpty(partitionId, nameof(partitionId)); PartitionId = partitionId; Reason = reason; }
/// <summary> /// Initializes a new instance of the <see cref="PartitionClosingEventArgs"/> class. /// </summary> /// /// <param name="partition">The context of the Event Hub partition this instance is associated with.</param> /// <param name="reason">The reason why the processing for the associated partition is being stopped.</param> /// <param name="cancellationToken">A <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param> /// public PartitionClosingEventArgs(PartitionContext partition, ProcessingStoppedReason reason, CancellationToken cancellationToken = default) { Argument.AssertNotNull(partition, nameof(partition)); Partition = partition; Reason = reason; }
public async Task Close(ProcessingStoppedReason stoppedReason) { _channel.Writer.Complete(); if (stoppedReason != ProcessingStoppedReason.Shutdown) { _cancellationTokenSource.Cancel(); } _shutdownTokenSource.Cancel(); await _checkpointTask.ConfigureAwait(false); _cancellationTokenSource.Dispose(); _shutdownTokenSource.Dispose(); }
protected sealed override async Task OnPartitionProcessingStoppedAsync(EventProcessorPartition partition, ProcessingStoppedReason reason, CancellationToken cancellationToken) { using (_logger.BeginScope("Processor Stop")) { _logger.LogInformation("Processing stopped received on partition {partitionId}", partition.PartitionId); if (_partitionProcessors.TryGetValue(partition.PartitionId, out var processor) && _partitionContexts.TryGetValue(partition.PartitionId, out var context)) { await processor.PartitionStopAsync(context, reason, cancellationToken).ConfigureAwait(false); } else { _logger.LogError("Processing stopped received on partition {partitionId}. Could not notify instance", partition.PartitionId); } } }
/// <summary> /// The handler to be called once event processing stops for a given partition. /// </summary> /// /// <param name="reason">The reason why the processing for the associated partition is being stopped.</param> /// <param name="context">The context in which the associated partition was being processed.</param> /// /// <returns>A task to be resolved on when the operation has completed.</returns> /// protected virtual ValueTask ProcessingForPartitionStoppedAsync(ProcessingStoppedReason reason, T context) => new ValueTask();
protected override Task OnPartitionProcessingStoppedAsync(Partition partition, ProcessingStoppedReason reason, CancellationToken cancellationToken) { return(partition.Processor.CloseAsync(partition.Context, reason)); }
protected override Task OnPartitionProcessingStoppedAsync(EventProcessorHostPartition partition, ProcessingStoppedReason reason, CancellationToken cancellationToken) { return(partition.EventProcessor.CloseAsync(partition, reason)); }
/// <inheritdoc /> public override sealed async Task PartitionStopAsync(ProcessorPartitionContext partitionContext, ProcessingStoppedReason reason, CancellationToken cancellationToken) { await base.PartitionStopAsync(partitionContext, reason, cancellationToken).ConfigureAwait(false); using (Logger.BeginScope("Processor stopping")) { if (_checkpointTo == null) { Logger.LogInformation("Shutting down but no checkpoint data available on partition {partitionId}", partitionContext.PartitionId); } else if (reason == ProcessingStoppedReason.OwnershipLost) { Logger.LogWarning("Cannot checkpoint, ownership was lost for partition {partitionId}, last known sequence number: {checkpointTo}", partitionContext.PartitionId, _checkpointTo.SequenceNumber); } else { try { Logger.LogInformation("Graceful shutdown on partition {partitionId}, forcing checkpoint to sequence number {sequenceNumber}", partitionContext.PartitionId, _checkpointTo.SequenceNumber); var tokenSource = new CancellationTokenSource(3000); var checkpointSuccess = await _checkpointPolicy.CheckpointAsync(_checkpointTo, true, tokenSource.Token).ConfigureAwait(false); Logger.LogInformation("Completed checkpoint on partition {partitionId} result {result}", partitionContext.PartitionId, checkpointSuccess); } catch (Exception e) { Logger.LogError(e, "Error checkpointing on partition {partitionId} during graceful shutdown, duplicate data expected", partitionContext.PartitionId); } } var derivedTokenSource = new CancellationTokenSource(3000); await ProcessorStoppingAsync(reason, derivedTokenSource.Token).ConfigureAwait(false); } }
/// <summary> /// Provided to allow derived types to add additional logic when the partition processor is stopping /// </summary> /// <param name="reason">The reason to stop (shutdown or lease lost)</param> /// <param name="cancellationToken">A token to monitor for abort and cancellation requests</param> protected virtual Task ProcessorStoppingAsync(ProcessingStoppedReason reason, CancellationToken cancellationToken) { return(Task.CompletedTask); }
/// <inheritdoc /> public virtual Task PartitionStopAsync(ProcessorPartitionContext partitionContext, ProcessingStoppedReason reason, CancellationToken cancellationToken) { using (Logger.BeginScope("OnStop")) { Logger.LogInformation("Stopping partition {partitionId}, reason {reason}", partitionContext.PartitionId, Enum.GetName(typeof(ProcessingStoppedReason), reason)); if (reason == ProcessingStoppedReason.Shutdown) { Logger.LogInformation("Checkpointing in graceful shutdown for partition {partitionId}", partitionContext.PartitionId, Enum.GetName(typeof(ProcessingStoppedReason), reason)); } } return(Task.CompletedTask); }