internal virtual LeaseInfo GetLeaseInfo(string partitionId)
            {
                if (LeaseInfos.TryGetValue(partitionId, out LeaseInfo lease))
                {
                    return(lease);
                }

                return(null);
            }
            protected override async Task <IEnumerable <EventProcessorCheckpoint> > ListCheckpointsAsync(CancellationToken cancellationToken)
            {
                // First, we read information from the location that the EventHubs V5 SDK writes to.
                Dictionary <string, EventProcessorCheckpoint> checkpoints = new Dictionary <string, EventProcessorCheckpoint>();
                string checkpointBlobsPrefix = string.Format(CultureInfo.InvariantCulture, CheckpointPrefixFormat, FullyQualifiedNamespace.ToLowerInvariant(), EventHubName.ToLowerInvariant(), ConsumerGroup.ToLowerInvariant());

                await foreach (BlobItem item in ContainerClient.GetBlobsAsync(traits: BlobTraits.Metadata, prefix: checkpointBlobsPrefix, cancellationToken: cancellationToken).ConfigureAwait(false))
                {
                    if (long.TryParse(item.Metadata[OffsetMetadataKey], NumberStyles.Integer, CultureInfo.InvariantCulture, out long offset) &&
                        long.TryParse(item.Metadata[SequenceNumberMetadataKey], NumberStyles.Integer, CultureInfo.InvariantCulture, out long sequenceNumber))
                    {
                        string partitionId = item.Name.Substring(checkpointBlobsPrefix.Length);

                        LeaseInfos.TryAdd(partitionId, new LeaseInfo(offset, sequenceNumber));
                        checkpoints.Add(partitionId, new EventProcessorCheckpoint()
                        {
                            ConsumerGroup           = ConsumerGroup,
                            EventHubName            = EventHubName,
                            FullyQualifiedNamespace = FullyQualifiedNamespace,
                            PartitionId             = partitionId,
                            StartingPosition        = EventPosition.FromOffset(offset, isInclusive: false)
                        });
                    }
                }

                // Check to see if there are any additional checkpoints in the older location that the V4 SDK would write to. If so, use them (this is helpful when moving from the V4 to V5 SDK,
                // since it means we will not have to reprocess messages processed and checkpointed by the older SDK).
                string legacyCheckpointAndOwnershipPrefix = $"{LegacyCheckpointStorageBlobPrefix}{ConsumerGroup}/";

                await foreach (BlobItem item in ContainerClient.GetBlobsAsync(prefix: legacyCheckpointAndOwnershipPrefix, cancellationToken: cancellationToken).ConfigureAwait(false))
                {
                    string partitionId = item.Name.Substring(legacyCheckpointAndOwnershipPrefix.Length);
                    if (!checkpoints.ContainsKey(partitionId))
                    {
                        using MemoryStream checkpointStream = new MemoryStream();
                        await ContainerClient.GetBlobClient(item.Name).DownloadToAsync(checkpointStream, cancellationToken: cancellationToken).ConfigureAwait(false);

                        checkpointStream.Position = 0;
                        BlobPartitionLease lease = await JsonSerializer.DeserializeAsync <BlobPartitionLease>(checkpointStream, cancellationToken : cancellationToken).ConfigureAwait(false);

                        if (long.TryParse(lease.Offset, out long offset))
                        {
                            LeaseInfos.TryAdd(partitionId, new LeaseInfo(offset, lease.SequenceNumber ?? 0));
                            checkpoints.Add(partitionId, new EventProcessorCheckpoint()
                            {
                                ConsumerGroup           = ConsumerGroup,
                                EventHubName            = EventHubName,
                                FullyQualifiedNamespace = FullyQualifiedNamespace,
                                PartitionId             = partitionId,
                                StartingPosition        = EventPosition.FromOffset(offset, isInclusive: false)
                            });
                        }
                    }
                }

                return(checkpoints.Values);
            }
            protected override Task OnInitializingPartitionAsync(Partition partition, CancellationToken cancellationToken)
            {
                partition.Processor = ProcessorFactory.CreateEventProcessor();
                partition.Context   = new ProcessorPartitionContext(partition.PartitionId, this, ReadLastEnqueuedEventProperties);

                // Since we are re-initializing this partition, any cached information we have about the parititon will be incorrect.
                // Clear it out now, if there is any, we'll refresh it in ListCheckpointsAsync, which EventProcessor will call before starting to pump messages.
                LeaseInfos.TryRemove(partition.PartitionId, out _);
                return(partition.Processor.OpenAsync(partition.Context));
            }