public async Task InspectPartition() { #region Snippet:EventHubs_Sample03_InspectPartition var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; /*@@*/ /*@@*/ connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; /*@@*/ eventHubName = _scope.EventHubName; var consumer = new EventHubConsumerClient(consumerGroup, connectionString, eventHubName); try { string[] partitions = await consumer.GetPartitionIdsAsync(); string firstPartition = partitions.FirstOrDefault(); PartitionProperties partitionProperties = await consumer.GetPartitionPropertiesAsync(firstPartition); Debug.WriteLine($"Partition: { partitionProperties.Id }"); Debug.WriteLine($"\tThe partition contains no events: { partitionProperties.IsEmpty }"); Debug.WriteLine($"\tThe first sequence number is: { partitionProperties.BeginningSequenceNumber }"); Debug.WriteLine($"\tThe last sequence number is: { partitionProperties.LastEnqueuedSequenceNumber }"); Debug.WriteLine($"\tThe last offset is: { partitionProperties.LastEnqueuedOffset }"); Debug.WriteLine($"\tThe last enqueued time is: { partitionProperties.LastEnqueuedTime }, in UTC."); } finally { await consumer.CloseAsync(); } #endregion }
// Get the number of unprocessed events by deriving the delta between the server side info and the partition lease info, private static long GetUnprocessedEventCount(PartitionProperties partitionInfo, BlobsCheckpointStore.BlobStorageCheckpoint 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); }
public async Task ReadPartitionFromSequence() { await using var scope = await EventHubScope.CreateAsync(1); #region Snippet:EventHubs_Sample05_ReadPartitionFromSequence #if SNIPPET var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; #else var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; #endif var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, connectionString, eventHubName); try { using CancellationTokenSource cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); string firstPartition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); PartitionProperties properties = await consumer.GetPartitionPropertiesAsync(firstPartition, cancellationSource.Token); EventPosition startingPosition = EventPosition.FromSequenceNumber(properties.LastEnqueuedSequenceNumber); await foreach (PartitionEvent partitionEvent in consumer.ReadEventsFromPartitionAsync( firstPartition, startingPosition, cancellationSource.Token)) { string readFromPartition = partitionEvent.Partition.PartitionId; byte[] eventBodyBytes = partitionEvent.Data.EventBody.ToArray(); Debug.WriteLine($"Read event of length { eventBodyBytes.Length } from { readFromPartition }"); } } catch (TaskCanceledException) { // This is expected if the cancellation token is // signaled. } finally { await consumer.CloseAsync(); } #endregion }
public async Task SendDoesNotUpdatePartitionPropertiesWhenSendingToDifferentPartition() { await using (EventHubScope scope = await EventHubScope.CreateAsync(2)) { var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); await using (var client = new EventHubClient(connectionString)) { var partitionIds = await client.GetPartitionIdsAsync(); EventData[] events = new[] { new EventData(Encoding.UTF8.GetBytes("I should not update stuff")) }; await using (EventHubProducer producer0 = client.CreateProducer(new EventHubProducerOptions { PartitionId = partitionIds[0] })) await using (EventHubProducer producer1 = client.CreateProducer(new EventHubProducerOptions { PartitionId = partitionIds[1] })) { // Sending events beforehand so the partition has some information. await producer0.SendAsync(events); PartitionProperties oldPartitionProperties = await client.GetPartitionPropertiesAsync(partitionIds[0]); Assert.That(oldPartitionProperties, Is.Not.Null, "A set of partition properties should have been returned."); await producer1.SendAsync(events); PartitionProperties newPartitionProperties = await client.GetPartitionPropertiesAsync(partitionIds[0]); Assert.That(newPartitionProperties, Is.Not.Null, "A set of partition properties should have been returned."); // All properties should remain the same. Assert.That(newPartitionProperties.Id, Is.EqualTo(oldPartitionProperties.Id)); Assert.That(newPartitionProperties.EventHubName, Is.EqualTo(oldPartitionProperties.EventHubName)); Assert.That(newPartitionProperties.BeginningSequenceNumber, Is.EqualTo(oldPartitionProperties.BeginningSequenceNumber)); Assert.That(newPartitionProperties.LastEnqueuedSequenceNumber, Is.EqualTo(oldPartitionProperties.LastEnqueuedSequenceNumber)); Assert.That(newPartitionProperties.LastEnqueuedOffset, Is.EqualTo(oldPartitionProperties.LastEnqueuedOffset)); } } } }
/// <summary> /// Runs the sample using the specified Event Hubs connection information. /// </summary> /// /// <param name="connectionString">The connection string for the Event Hubs namespace that the sample should target.</param> /// <param name="eventHubName">The name of the Event Hub, sometimes known as its path, that she sample should run against.</param> /// public async Task RunAsync(string connectionString, string eventHubName) { // To interact with an Event Hubs, a client is needed. There are clients associated with each of the core areas of functionality // with an Event Hub, naming publishing events and consuming events. Each of these clients manages resources and should be // explicitly closed or disposed, but it is not necessary to do both. // // In this example, we will create a producer client and use it to inspect the properties of an Event Hub. When complete, we take // advantage of the new asynchronous dispose to ensure that clean-up is performed when we are done or when an exception is encountered. await using (var producerClient = new EventHubProducerClient(connectionString, eventHubName)) { // Using the client, we will inspect the Event Hub that it is connected to, getting // access to its informational properties. EventHubProperties properties = await producerClient.GetEventHubPropertiesAsync(); Console.WriteLine("The Event Hub has the following properties:"); Console.WriteLine($"\tThe path to the Event Hub from the namespace is: { properties.Name }"); Console.WriteLine($"\tThe Event Hub was created at: { properties.CreatedOn.ToString("yyyy-MM-dd hh:mm:ss tt (zzz)") }, in UTC."); Console.WriteLine(); // Partitions of an Event Hub are an important concept. Using the Event Hub properties, we'll inspect each of its partitions, // getting access to partition-level properties. foreach (string partitionId in properties.PartitionIds) { PartitionProperties partitionProperties = await producerClient.GetPartitionPropertiesAsync(partitionId); Console.WriteLine($"\tPartition: { partitionProperties.Id }"); Console.WriteLine($"\t\tThe partition contains no events: { partitionProperties.IsEmpty }"); Console.WriteLine($"\t\tThe first sequence number of an event in the partition is: { partitionProperties.BeginningSequenceNumber }"); Console.WriteLine($"\t\tThe last sequence number of an event in the partition is: { partitionProperties.LastEnqueuedSequenceNumber }"); Console.WriteLine($"\t\tThe last offset of an event in the partition is: { partitionProperties.LastEnqueuedOffset }"); Console.WriteLine($"\t\tThe last time that an event was enqueued in the partition is: { partitionProperties.LastEnqueuedTime.ToString("yyyy-MM-dd hh:mm:ss tt (zzz)") }, in UTC."); Console.WriteLine(); } } // At this point, our client has passed its "using" scope and has safely been disposed of. We have no // further obligations. Console.WriteLine(); }
public async Task SendUpdatesPartitionProperties() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); await using (var client = new EventHubClient(connectionString)) { var partition = (await client.GetPartitionIdsAsync()).First(); EventData[] events = new[] { new EventData(Encoding.UTF8.GetBytes("I should update stuff")) }; await using (EventHubProducer producer = client.CreateProducer(new EventHubProducerOptions { PartitionId = partition })) { // Sending events beforehand so the partition has some information. await producer.SendAsync(events); PartitionProperties oldPartitionProperties = await client.GetPartitionPropertiesAsync(partition); Assert.That(oldPartitionProperties, Is.Not.Null, "A set of partition properties should have been returned."); await producer.SendAsync(events); PartitionProperties newPartitionProperties = await client.GetPartitionPropertiesAsync(partition); Assert.That(newPartitionProperties, Is.Not.Null, "A set of partition properties should have been returned."); // The following properties should not have been altered. Assert.That(newPartitionProperties.Id, Is.EqualTo(oldPartitionProperties.Id)); Assert.That(newPartitionProperties.EventHubName, Is.EqualTo(oldPartitionProperties.EventHubName)); Assert.That(newPartitionProperties.BeginningSequenceNumber, Is.EqualTo(oldPartitionProperties.BeginningSequenceNumber)); // The following properties should have been updated. Assert.That(newPartitionProperties.LastEnqueuedSequenceNumber, Is.GreaterThan(oldPartitionProperties.LastEnqueuedSequenceNumber)); Assert.That(newPartitionProperties.LastEnqueuedOffset, Is.GreaterThan(oldPartitionProperties.LastEnqueuedOffset)); } } } }
public async Task ClientCanRetrievePartitionProperties(TransportType transportType) { var partitionCount = 4; await using (EventHubScope scope = await EventHubScope.CreateAsync(partitionCount)) { var clientOptions = new EventHubClientOptions(); var connectionString = TestEnvironment.BuildConnectionStringForEventHub(scope.EventHubName); ConnectionStringProperties connectionProperties = ConnectionStringParser.Parse(connectionString); var credential = new SharedAccessSignatureCredential ( new SharedAccessSignature ( $"{ clientOptions.TransportType.GetUriScheme() }://{ connectionProperties.Endpoint.Host }/{ connectionProperties.EventHubName }".ToLowerInvariant(), connectionProperties.SharedAccessKeyName, connectionProperties.SharedAccessKey, TimeSpan.FromHours(4) ) ); await using (var client = new EventHubClient(connectionProperties.Endpoint.Host, connectionProperties.EventHubName, credential, new EventHubClientOptions { TransportType = transportType })) { var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(20)); EventHubProperties properties = await client.GetPropertiesAsync(); var partition = properties.PartitionIds.First(); PartitionProperties partitionProperties = await client.GetPartitionPropertiesAsync(partition, cancellation.Token); Assert.That(partitionProperties, Is.Not.Null, "A set of partition properties should have been returned."); Assert.That(partitionProperties.Id, Is.EqualTo(partition), "The partition identifier should match."); Assert.That(partitionProperties.EventHubName, Is.EqualTo(connectionProperties.EventHubName).Using((IEqualityComparer <string>)StringComparer.InvariantCultureIgnoreCase), "The Event Hub path should match."); Assert.That(partitionProperties.BeginningSequenceNumber, Is.Not.EqualTo(default(long)), "The beginning sequence number should have been populated."); Assert.That(partitionProperties.LastEnqueuedSequenceNumber, Is.Not.EqualTo(default(long)), "The last sequence number should have been populated."); Assert.That(partitionProperties.LastEnqueuedOffset, Is.Not.EqualTo(default(long)), "The last offset should have been populated."); } } }