protected sealed override async Task OnInitializingPartitionAsync(EventProcessorPartition partition, CancellationToken cancellationToken)
        {
            _partitionInitializeProcessing.Increment();

            using (_logger.BeginScope("Processor Initialization"))
            {
                _logger.LogInformation("Processing initialization received on partition {partitionId}", partition.PartitionId);

                if (!_partitionContexts.TryGetValue(partition.PartitionId, out var context))
                {
                    context = new ProcessorPartitionContext(_logger, _metricFactory, partition.PartitionId, () => ReadLastEnqueuedEventProperties(partition.PartitionId), _checkpointManager);
                    _partitionContexts.TryAdd(partition.PartitionId, context);
                }

                if (!_partitionProcessors.TryGetValue(partition.PartitionId, out var processor))
                {
                    if (_partitionContexts.TryGetValue(partition.PartitionId, out var partitionContext))
                    {
                        processor = CreateProcessor(_logger, _metricFactory, partitionContext);

                        await processor.InitializeAsync(_logger, _metricFactory, partitionContext).ConfigureAwait(false);

                        _partitionProcessors.TryAdd(partition.PartitionId, processor);
                    }
                    else
                    {
                        _logger.LogError("Error retrieving context from context list for partition {partitionId}", partition.PartitionId);
                        throw new ApplicationException($"Error retriving partition from list for partition {partition.PartitionId}");
                    }
                }

                await processor.PartitionInitializeAsync(context, cancellationToken).ConfigureAwait(false);
            }
        }
 protected abstract Task ProcessBatchAsync(IEnumerable <EventData> events, IProcessor processor, ProcessorPartitionContext partitionContext, CancellationToken cancellationToken);
 protected abstract IProcessor CreateProcessor(ILogger logger, IMetricFactory metricFactory, ProcessorPartitionContext partitionContext);
        /// <inheritdoc />
        protected sealed override async Task ProcessBatchAsync(IEnumerable <EventData> events, IProcessor processor, ProcessorPartitionContext partitionContext, CancellationToken cancellationToken)
        {
            Dictionary <long, Exception> exceptions = null;
            var eventFound        = false;
            var processorInstance = processor as IEventProcessor;

            try
            {
                if (events == null)
                {
                    foreach (var eventData in events)
                    {
                        eventFound = true;

                        try
                        {
                            await processorInstance.PartitionProcessAsync(eventData, partitionContext, cancellationToken).ConfigureAwait(false);
                        }
                        catch (Exception e) when(!(e is TaskCanceledException))
                        {
                            exceptions ??= new Dictionary <long, Exception>();
                            exceptions.Add(eventData.SequenceNumber, e);
                        }
                    }
                }

                if (!eventFound)
                {
                    try
                    {
                        await processorInstance.PartitionProcessAsync(null, partitionContext, cancellationToken).ConfigureAwait(false);
                    }
                    catch (Exception e) when(!(e is TaskCanceledException))
                    {
                        exceptions ??= new Dictionary <long, Exception>();
                        exceptions.Add(-1, e);
                    }
                }
            }
            catch (Exception e) when(!(e is TaskCanceledException))
            {
                _logger.LogError(e, "An error caught in the batch that was not a cancellation exception");
                throw;
            }
            finally
            {
                _logger.LogDebug("Completed batch processing");
            }

            var exceptionCount = (exceptions?.Count ?? 0);

            if (exceptionCount > 0)
            {
                if (exceptionCount == 1)
                {
                    ExceptionDispatchInfo.Capture(exceptions[0]).Throw();
                }

                throw new HubProcessingException($"Error processing messages in batch on partition {partitionContext.PartitionId}", exceptions);
            }
        }
 /// <inheritdoc />
 protected sealed override IProcessor CreateProcessor(ILogger logger, IMetricFactory metricFactory, ProcessorPartitionContext partitionContext)
 {
     return(_processorFactory(logger, metricFactory, partitionContext));
 }
        /// <inheritdoc />
        protected sealed override async Task ProcessBatchAsync(IEnumerable <EventData> events, IProcessor processor, ProcessorPartitionContext partitionContext, CancellationToken cancellationToken)
        {
            var processorInstance = processor as IEventBatchProcessor;

            try
            {
                await processorInstance.PartitionProcessAsync(events, partitionContext, cancellationToken).ConfigureAwait(false);
            }
            catch (Exception e) when(!(e is TaskCanceledException))
            {
                _logger.LogError(e, "An error caught in the batch that was not a cancellation exception");
                throw;
            }
            finally
            {
                _logger.LogDebug("Completed batch processing");
            }
        }