private static async Task <IEventHubReceiver> CreateReceiver(EventHubPartitionSettings partitionSettings, string offset, Logger logger, ITelemetryProducer telemetryProducer) { bool offsetInclusive = true; var connectionStringBuilder = new EventHubsConnectionStringBuilder(partitionSettings.Hub.ConnectionString) { EntityPath = partitionSettings.Hub.Path }; EventHubClient client = EventHubClient.CreateFromConnectionString(connectionStringBuilder.ToString()); // if we have a starting offset or if we're not configured to start reading from utc now, read from offset if (!partitionSettings.Hub.StartFromNow || offset != EventHubConstants.StartOfStream) { logger.Info("Starting to read from EventHub partition {0}-{1} at offset {2}", partitionSettings.Hub.Path, partitionSettings.Partition, offset); } else { // to start reading from most recent data, we get the latest offset from the partition. EventHubPartitionRuntimeInformation partitionInfo = await client.GetPartitionRuntimeInformationAsync(partitionSettings.Partition); offset = partitionInfo.LastEnqueuedOffset; offsetInclusive = false; logger.Info("Starting to read latest messages from EventHub partition {0}-{1} at offset {2}", partitionSettings.Hub.Path, partitionSettings.Partition, offset); } PartitionReceiver receiver = client.CreateReceiver(partitionSettings.Hub.ConsumerGroup, partitionSettings.Partition, offset, offsetInclusive); if (partitionSettings.Hub.PrefetchCount.HasValue) { receiver.PrefetchCount = partitionSettings.Hub.PrefetchCount.Value; } return(new EventHubReceiverProxy(receiver)); }
/// <summary> /// Retrieves information about a specific partition for an Event Hub, including elements that describe the available /// events in the partition event stream. /// </summary> /// /// <param name="partitionId">The unique identifier of a partition associated with the Event Hub.</param> /// <param name="cancellationToken">An optional <see cref="CancellationToken"/> instance to signal the request to cancel the operation.</param> /// /// <returns>The set of information for the requested partition under the Event Hub this client is associated with.</returns> /// public override async Task <PartitionProperties> GetPartitionPropertiesAsync(string partitionId, CancellationToken cancellationToken) { try { EventHubPartitionRuntimeInformation runtimeInformation = await TrackOneClient.GetPartitionRuntimeInformationAsync(partitionId).ConfigureAwait(false); if (!long.TryParse(runtimeInformation.LastEnqueuedOffset, out var lastEnqueuedOffset)) { throw new FormatException(string.Format(CultureInfo.CurrentCulture, Resources.CannotParseIntegerType, nameof(runtimeInformation.LastEnqueuedOffset), 64, runtimeInformation.LastEnqueuedOffset)); } return(new PartitionProperties ( runtimeInformation.Path, runtimeInformation.PartitionId, runtimeInformation.BeginSequenceNumber, runtimeInformation.LastEnqueuedSequenceNumber, lastEnqueuedOffset, runtimeInformation.LastEnqueuedTimeUtc, runtimeInformation.IsEmpty )); } catch (TrackOne.EventHubsException ex) { throw ex.MapToTrackTwoException(); } }
// Get the number of unprocessed events by deriving the delta between the server side info and the partition lease info, private long GetUnprocessedEventCount(EventHubPartitionRuntimeInformation partitionInfo, BlobPartitionLease partitionLeaseInfo) { long partitionLeaseInfoSequenceNumber = partitionLeaseInfo.SequenceNumber ?? 0; // This handles two scenarios: // 1. If the partition has received its first message, Offset will be null and LastEnqueuedSequenceNumber will be 0 // 2. If there are no instances set to process messages, Offset will be null and LastEnqueuedSequenceNumber will be >= 0 if (partitionLeaseInfo.Offset == null && partitionInfo.LastEnqueuedSequenceNumber >= 0) { return(partitionInfo.LastEnqueuedSequenceNumber + 1); } if (partitionInfo.LastEnqueuedSequenceNumber > partitionLeaseInfoSequenceNumber) { return(partitionInfo.LastEnqueuedSequenceNumber - partitionLeaseInfoSequenceNumber); } // Partition is a circular buffer, so it is possible that // LastEnqueuedSequenceNumber < SequenceNumber long count = 0; unchecked { count = (long.MaxValue - partitionInfo.LastEnqueuedSequenceNumber) + partitionLeaseInfoSequenceNumber; } // It's possible for checkpointing to be ahead of the partition's LastEnqueuedSequenceNumber, // especially if checkpointing is happening often and load is very low. // If count is negative, we need to know that this read is invalid, so return 0. // e.g., (9223372036854775807 - 10) + 11 = -9223372036854775808 return((count < 0) ? 0 : count); }
private static async Task <EventHubReceiver> CreateReceiver(EventHubPartitionSettings partitionSettings, string offset, Logger logger) #endif { bool offsetInclusive = true; #if NETSTANDARD var connectionStringBuilder = new EventHubsConnectionStringBuilder(partitionSettings.Hub.ConnectionString) { EntityPath = partitionSettings.Hub.Path }; EventHubClient client = EventHubClient.CreateFromConnectionString(connectionStringBuilder.ToString()); #else EventHubClient client = EventHubClient.CreateFromConnectionString(partitionSettings.Hub.ConnectionString, partitionSettings.Hub.Path); EventHubConsumerGroup consumerGroup = client.GetConsumerGroup(partitionSettings.Hub.ConsumerGroup); if (partitionSettings.Hub.PrefetchCount.HasValue) { consumerGroup.PrefetchCount = partitionSettings.Hub.PrefetchCount.Value; } #endif // if we have a starting offset or if we're not configured to start reading from utc now, read from offset if (!partitionSettings.Hub.StartFromNow || offset != EventHubConstants.StartOfStream) { logger.Info("Starting to read from EventHub partition {0}-{1} at offset {2}", partitionSettings.Hub.Path, partitionSettings.Partition, offset); } else { // to start reading from most recent data, we get the latest offset from the partition. #if NETSTANDARD EventHubPartitionRuntimeInformation partitionInfo = #else PartitionRuntimeInformation partitionInfo = #endif await client.GetPartitionRuntimeInformationAsync(partitionSettings.Partition); offset = partitionInfo.LastEnqueuedOffset; offsetInclusive = false; logger.Info("Starting to read latest messages from EventHub partition {0}-{1} at offset {2}", partitionSettings.Hub.Path, partitionSettings.Partition, offset); } #if NETSTANDARD PartitionReceiver receiver = client.CreateReceiver(partitionSettings.Hub.ConsumerGroup, partitionSettings.Partition, offset, offsetInclusive); if (partitionSettings.Hub.PrefetchCount.HasValue) { receiver.PrefetchCount = partitionSettings.Hub.PrefetchCount.Value; } return(receiver); #else return(await consumerGroup.CreateReceiverAsync(partitionSettings.Partition, offset, offsetInclusive)); #endif }
private static async Task <IReadOnlyList <PartitionReceiver> > GetReceivers(EventHubClient eventHubClient, string consumerGroupName) { EventHubRuntimeInformation runtimeInformation = await eventHubClient.GetRuntimeInformationAsync(); var receivers = new List <PartitionReceiver>(); foreach (string partitionId in runtimeInformation.PartitionIds) { EventHubPartitionRuntimeInformation partitionRuntimeInformation = await eventHubClient.GetPartitionRuntimeInformationAsync(partitionId); PartitionReceiver receiver = eventHubClient.CreateReceiver( consumerGroupName, partitionId, partitionRuntimeInformation.LastEnqueuedOffset, offsetInclusive: false); receivers.Add(receiver); } return(receivers); }
async Task ValidateEnabledBehavior(PartitionReceiver partitionReceiver, EventHubPartitionRuntimeInformation pInfo) { Assert.True(partitionReceiver.ReceiverRuntimeMetricEnabled == true, "ReceiverRuntimeMetricEnabled == false"); // Receive a message and validate RuntimeInfo is set. var messages = await partitionReceiver.ReceiveAsync(1); Assert.True(messages != null, "Failed to receive a message."); var message = messages.Single(); Assert.True(partitionReceiver.RuntimeInfo.LastEnqueuedOffset == pInfo.LastEnqueuedOffset, $"FAILED partitionReceiver.RuntimeInfo.LastEnqueuedOffset == {partitionReceiver.RuntimeInfo.LastEnqueuedOffset}"); Assert.True(partitionReceiver.RuntimeInfo.LastEnqueuedTimeUtc == pInfo.LastEnqueuedTimeUtc, $"FAILED partitionReceiver.RuntimeInfo.LastEnqueuedTimeUtc == {partitionReceiver.RuntimeInfo.LastEnqueuedTimeUtc}"); Assert.True(partitionReceiver.RuntimeInfo.LastSequenceNumber == pInfo.LastEnqueuedSequenceNumber, $"FAILED partitionReceiver.RuntimeInfo.LastSequenceNumber == {partitionReceiver.RuntimeInfo.LastSequenceNumber}"); Assert.True(partitionReceiver.RuntimeInfo.RetrievalTime > DateTime.UtcNow.AddSeconds(-60), $"FAILED partitionReceiver.RuntimeInfo.RetrievalTime == {partitionReceiver.RuntimeInfo.RetrievalTime}"); Assert.True(partitionReceiver.RuntimeInfo.PartitionId == partitionReceiver.PartitionId, $"FAILED partitionReceiver.RuntimeInfo.PartitionId == {partitionReceiver.RuntimeInfo.PartitionId}"); }