public async Task ClientSettingInherited() { await using (var scope = await EventHubScope.CreateAsync(2)) { var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName); var ehClient = EventHubClient.CreateFromConnectionString(connectionString); var partitionReceiver1 = default(PartitionReceiver); var partitionReceiver2 = default(PartitionReceiver); try { // Send some number of messages to target partition. await TestUtility.SendToPartitionAsync(ehClient, targetPartitionId, "this is the message body", 10); // Get partition runtime info so we can compare with runtime metrics. var pInfo = await ehClient.GetPartitionRuntimeInformationAsync(targetPartitionId); // Enable runtime metrics on the client. ehClient.EnableReceiverRuntimeMetric = true; // Create 2 new receivers. These receivers are expected to show runtime metrics since their parent client is enabled. partitionReceiver1 = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, targetPartitionId, EventPosition.FromStart()); partitionReceiver2 = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, targetPartitionId, EventPosition.FromStart()); await ValidateEnabledBehavior(partitionReceiver1, pInfo); await ValidateEnabledBehavior(partitionReceiver2, pInfo); } finally { await Task.WhenAll( partitionReceiver1?.CloseAsync(), partitionReceiver2?.CloseAsync(), ehClient.CloseAsync()); } } }
public async Task InvokeOnNull() { await using (var scope = await EventHubScope.CreateAsync(1)) { var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName); var ehClient = EventHubClient.CreateFromConnectionString(connectionString); var partitionReceiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, "0", EventPosition.FromEnd()); try { var tcs = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously); var handler = new TestPartitionReceiveHandler(); handler.EventsReceived += (s, eventDatas) => { if (eventDatas == null) { TestUtility.Log("Received null."); tcs.TrySetResult(true); } }; partitionReceiver.SetReceiveHandler(handler, true); await tcs.Task.WithTimeout(TimeSpan.FromSeconds(120)); } finally { // Unregister handler. partitionReceiver.SetReceiveHandler(null); // Close clients. await Task.WhenAll( partitionReceiver.CloseAsync(), ehClient.CloseAsync()); } } }
public async Task ChildEntityShouldInheritRetryPolicyFromParent() { var testMaxRetryCount = 99; await using (var scope = await EventHubScope.CreateAsync(1)) { var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName); var ehClient = EventHubClient.CreateFromConnectionString(connectionString); ehClient.RetryPolicy = new RetryPolicyCustom(testMaxRetryCount); // Validate partition sender inherits. var sender = ehClient.CreateEventSender("0"); Assert.True(sender.RetryPolicy is RetryPolicyCustom, "Sender failed to inherit parent client's RetryPolicy setting."); Assert.True((sender.RetryPolicy as RetryPolicyCustom).maximumRetryCount == testMaxRetryCount, $"Retry policy on the sender shows testMaxRetryCount as {(sender.RetryPolicy as RetryPolicyCustom).maximumRetryCount}"); // Validate partition receiver inherits. var receiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, "0", EventPosition.FromStart()); Assert.True(receiver.RetryPolicy is RetryPolicyCustom, "Receiver failed to inherit parent client's RetryPolicy setting."); Assert.True((receiver.RetryPolicy as RetryPolicyCustom).maximumRetryCount == testMaxRetryCount, $"Retry policy on the receiver shows testMaxRetryCount as {(receiver.RetryPolicy as RetryPolicyCustom).maximumRetryCount}"); } }
public async Task ProducerUpdatesPropertiesAfterPublishingBatches() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var options = new IdempotentProducerOptions { EnableIdempotentPartitions = true }; await using var producer = new IdempotentProducer(connectionString, options); var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); var partition = (await producer.GetPartitionIdsAsync(cancellationSource.Token)).First(); var initialPartitionProperties = await producer.GetPartitionPublishingPropertiesAsync(partition); var batchOptions = new CreateBatchOptions { PartitionId = partition }; using var batch = await producer.CreateBatchAsync(batchOptions, cancellationSource.Token); batch.TryAdd(EventGenerator.CreateEvents(1).First()); batch.TryAdd(EventGenerator.CreateEvents(1).First()); batch.TryAdd(EventGenerator.CreateEvents(1).First()); await producer.SendAsync(batch, cancellationSource.Token); var updatedPartitionProperties = await producer.GetPartitionPublishingPropertiesAsync(partition); Assert.That(updatedPartitionProperties.IsIdempotentPublishingEnabled, Is.True, "Idempotent publishing should be enabled."); Assert.That(updatedPartitionProperties.ProducerGroupId, Is.EqualTo(initialPartitionProperties.ProducerGroupId), "The producer group identifier should not have changed."); Assert.That(updatedPartitionProperties.OwnerLevel, Is.EqualTo(initialPartitionProperties.OwnerLevel), "The owner level should not have changed."); Assert.That(updatedPartitionProperties.LastPublishedSequenceNumber, Is.GreaterThan(initialPartitionProperties.LastPublishedSequenceNumber), "The last published sequence number should have increased."); } }
public async Task CloseSenderClient() { await using (var scope = await EventHubScope.CreateAsync(1)) { var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName); var ehClient = EventHubClient.CreateFromConnectionString(connectionString); var pSender = ehClient.CreatePartitionSender("0"); var pReceiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, "0", EventPosition.FromStart()); try { TestUtility.Log("Sending single event to partition 0"); using (var eventData = new EventData(Encoding.UTF8.GetBytes("Hello EventHub!"))) { await pSender.SendAsync(eventData); TestUtility.Log("Closing partition sender"); await pSender.CloseAsync(); } await Assert.ThrowsAsync <InvalidOperationException>(async() => { TestUtility.Log("Sending another event to partition 0 on the closed sender, this should fail"); using (var eventData = new EventData(Encoding.UTF8.GetBytes("Hello EventHub!"))) { await pSender.SendAsync(eventData); } }); } finally { await Task.WhenAll( pReceiver.CloseAsync(), ehClient.CloseAsync()); } } }
public async Task Read() { await using var scope = await EventHubScope.CreateAsync(1); try { #region Snippet:EventHubs_ReadMe_Read var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; /*@@*/ /*@@*/ connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; /*@@*/ eventHubName = scope.EventHubName; string consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; await using (var consumer = new EventHubConsumerClient(consumerGroup, connectionString, eventHubName)) { using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(45)); await foreach (PartitionEvent receivedEvent in consumer.ReadEventsAsync(cancellationSource.Token)) { // At this point, the loop will wait for events to be available in the Event Hub. When an event // is available, the loop will iterate with the event that was received. Because we did not // specify a maximum wait time, the loop will wait forever unless cancellation is requested using // the cancellation token. } } #endregion } catch (TaskCanceledException) { // Expected } }
public async Task SmallReceiveTimeout() { var maxClients = 4; // Issue receives with 1 second so that some of the Receive calls will timeout while creating AMQP link. // Even those Receive calls should return NULL instead of bubbling the exception up. var receiveTimeoutInSeconds = 1; await using (var scope = await EventHubScope.CreateAsync(1)) { var tasks = Enumerable.Range(0, maxClients) .Select(async i => { PartitionReceiver receiver = null; try { TestUtility.Log($"Testing with {receiveTimeoutInSeconds} seconds on client {i}."); // Start receiving from a future time so that Receive call won't be able to fetch any events. var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName); var ehClient = EventHubClient.CreateFromConnectionString(connectionString); receiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, "0", EventPosition.FromEnqueuedTime(DateTime.UtcNow.AddMinutes(1))); var ed = await receiver.ReceiveAsync(1, TimeSpan.FromSeconds(receiveTimeoutInSeconds)); if (ed == null) { TestUtility.Log($"Received NULL from client {i}"); } } finally { await receiver.CloseAsync(); } }); await Task.WhenAll(tasks); } }
public async Task ConfigureConsumerRetryWithFullOptions() { await using var scope = await EventHubScope.CreateAsync(1); #region Snippet:EventHubs_Sample02_ConsumerRetryWithFullOptions 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 consumerOptions = new EventHubConsumerClientOptions { RetryOptions = new EventHubsRetryOptions { Mode = EventHubsRetryMode.Exponential, MaximumRetries = 5, Delay = TimeSpan.FromMilliseconds(800), MaximumDelay = TimeSpan.FromSeconds(10) } }; var consumer = new EventHubConsumerClient( consumerGroup, connectionString, eventHubName, consumerOptions); #endregion using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); await consumer.CloseAsync(cancellationSource.Token).IgnoreExceptions(); }
public async Task InspectPartition() { await using var scope = await EventHubScope.CreateAsync(1); #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 }
public async Task NoBatch() { await using var scope = await EventHubScope.CreateAsync(1); #region Snippet:EventHubs_Sample04_NoBatch #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 producer = new EventHubProducerClient(connectionString, eventHubName); try { var eventsToSend = new List <EventData>(); for (var index = 0; index < 10; ++index) { var eventBody = new BinaryData("Hello, Event Hubs!"); var eventData = new EventData(eventBody); eventsToSend.Add(eventData); } await producer.SendAsync(eventsToSend); } finally { await producer.CloseAsync(); } #endregion }
public async Task CreateNonEpochReceiverAfterEpochReceiver() { await using (var scope = await EventHubScope.CreateAsync(2)) { var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName); var ehClient = EventHubClient.CreateFromConnectionString(connectionString); var epochReceiver = ehClient.CreateEpochReceiver(PartitionReceiver.DefaultConsumerGroupName, "1", EventPosition.FromStart(), 1); var nonEpochReceiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, "1", EventPosition.FromStart()); try { TestUtility.Log("Starting epoch receiver"); await epochReceiver.ReceiveAsync(10); await Task.Delay(TimeSpan.FromSeconds(10)); try { TestUtility.Log("Starting nonepoch receiver, this should fail"); await nonEpochReceiver.ReceiveAsync(10); throw new InvalidOperationException("Non-Epoch receiver should have encountered an exception by now!"); } catch (ReceiverDisconnectedException ex) when(ex.Message.Contains("non-epoch receiver is not allowed")) { TestUtility.Log($"Received expected exception {ex.GetType()}: {ex.Message}"); } } finally { await Task.WhenAll( epochReceiver.CloseAsync(), nonEpochReceiver.CloseAsync(), ehClient.CloseAsync()); } } }
public async Task ProducerInitializesPropertiesWhenRequested() { await using (EventHubScope scope = await EventHubScope.CreateAsync(2)) { var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var options = new IdempotentProducerOptions { EnableIdempotentPartitions = true }; await using var producer = new IdempotentProducer(connectionString, options); var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); var partition = (await producer.GetPartitionIdsAsync(cancellationSource.Token)).Last(); var partitionProperties = await producer.GetPartitionPublishingPropertiesAsync(partition); Assert.That(partitionProperties, Is.Not.Null, "The properties should have been created."); Assert.That(partitionProperties.IsIdempotentPublishingEnabled, Is.True, "Idempotent publishing should be enabled."); Assert.That(partitionProperties.ProducerGroupId.HasValue, Is.True, "The producer group identifier should have a value."); Assert.That(partitionProperties.OwnerLevel.HasValue, Is.True, "The owner level should have a value."); Assert.That(partitionProperties.LastPublishedSequenceNumber.HasValue, Is.True, "The last published sequence number should have a value."); } }
public async Task SendBatch() { TestUtility.Log("Sending multiple Events via EventHubClient.SendAsync(IEnumerable<EventData>)"); await using (var scope = await EventHubScope.CreateAsync(1)) { var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName); var ehClient = EventHubClient.CreateFromConnectionString(connectionString); try { using (var eventData1 = new EventData(Encoding.UTF8.GetBytes("Hello EventHub!"))) using (var eventData2 = new EventData(Encoding.UTF8.GetBytes("This is another message in the batch!"))) { eventData2.Properties["ContosoEventType"] = "some value here"; await ehClient.SendAsync(new[] { eventData1, eventData2 }); } } finally { await ehClient.CloseAsync(); } } }
public async Task Publish() { await using var scope = await EventHubScope.CreateAsync(1); #region Snippet:EventHubs_Sample07_Publish #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 producer = new EventHubProducerClient(connectionString, eventHubName); try { using (var eventBatch = await producer.CreateBatchAsync()) { var eventBody = new BinaryData("This is an event body"); var eventData = new EventData(eventBody); if (!eventBatch.TryAdd(eventData)) { throw new Exception($"The event could not be added."); } } } finally { await producer.CloseAsync(); } #endregion }
public async Task Publish() { await using var scope = await EventHubScope.CreateAsync(1); #region Snippet:EventHubs_ReadMe_Publish var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; /*@@*/ /*@@*/ connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; /*@@*/ eventHubName = scope.EventHubName; await using (var producer = new EventHubProducerClient(connectionString, eventHubName)) { using EventDataBatch eventBatch = await producer.CreateBatchAsync(); eventBatch.TryAdd(new EventData(new BinaryData("First"))); eventBatch.TryAdd(new EventData(new BinaryData("Second"))); await producer.SendAsync(eventBatch); } #endregion }
/// <summary> /// Performs the tasks needed to initialize and set up the environment for the test scenario. /// When multiple instances are run in parallel, the setup will take place once, prior to the /// execution of the first test instance. /// </summary> /// public async override Task GlobalSetupAsync() { await base.GlobalSetupAsync().ConfigureAwait(false); s_scope = await EventHubScope.CreateAsync(4).ConfigureAwait(false); s_client = EventHubClient.CreateFromConnectionString(TestUtility.BuildEventHubsConnectionString(s_scope.EventHubName)); s_eventBody = EventGenerator.CreateRandomBody(Options.Size); var partition = (await s_client.GetRuntimeInformationAsync().ConfigureAwait(false)).PartitionIds[0]; s_sender = s_client.CreatePartitionSender(partition); // Publish an empty event to force the connection and link to be established. using var batch = s_sender.CreateBatch(); if (!batch.TryAdd(new EventData(Array.Empty <byte>()))) { throw new InvalidOperationException("The empty event could not be added to the batch during global setup."); } await s_sender.SendAsync(batch).ConfigureAwait(false); }
public async Task ProducerSequencesEvents() { await using (EventHubScope scope = await EventHubScope.CreateAsync(2)) { var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; await using var producer = new EventHubProducerClient(connectionString, options); var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); var partition = (await producer.GetPartitionIdsAsync(cancellationSource.Token)).Last(); var sendOptions = new SendEventOptions { PartitionId = partition }; var partitionProperties = await producer.GetPartitionPublishingPropertiesAsync(partition); var eventSequenceNumber = partitionProperties.LastPublishedSequenceNumber; var events = EventGenerator.CreateEvents(10).ToArray(); Assert.That(events.Any(item => item.PublishedSequenceNumber.HasValue), Is.False, "Events should start out as unpublished with no sequence number."); await producer.SendAsync(events, sendOptions, cancellationSource.Token); Assert.That(events.All(item => item.PublishedSequenceNumber.HasValue), Is.True, "Events should be sequenced after publishing."); foreach (var item in events) { Assert.That(item.PublishedSequenceNumber, Is.EqualTo(++eventSequenceNumber), $"The sequence numbers should be contiguous. Event { eventSequenceNumber } was out of order."); } } }
public async Task ProcessByBatch() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample04_ProcessByBatch #if SNIPPET var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var consumerGroup = "<< NAME OF THE EVENT HUB CONSUMER GROUP >>"; #else var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; var blobContainerName = storageScope.ContainerName; var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); #endif var storageClient = new BlobContainerClient( storageConnectionString, blobContainerName); var processor = new EventProcessorClient( storageClient, consumerGroup, eventHubsConnectionString, eventHubName); const int EventsInBatch = 50; var partitionEventBatches = new ConcurrentDictionary <string, List <EventData> >(); var checkpointNeeded = false; async Task processEventHandler(ProcessEventArgs args) { try { string partition = args.Partition.PartitionId; List <EventData> partitionBatch = partitionEventBatches.GetOrAdd( partition, new List <EventData>()); partitionBatch.Add(args.Data); if (partitionBatch.Count >= EventsInBatch) { await Application.ProcessEventBatchAsync( partitionBatch, args.Partition, args.CancellationToken); checkpointNeeded = true; partitionBatch.Clear(); } if (checkpointNeeded) { await args.UpdateCheckpointAsync(); checkpointNeeded = false; } } catch (Exception ex) { Application.HandleProcessingException(args, ex); } } try { using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); // The error handler is not relevant for this sample; for // illustration, it is delegating the implementation to the // host application. processor.ProcessEventAsync += processEventHandler; processor.ProcessErrorAsync += Application.ProcessorErrorHandler; try { await processor.StartProcessingAsync(cancellationSource.Token); await Task.Delay(Timeout.Infinite, cancellationSource.Token); } catch (TaskCanceledException) { // This is expected if the cancellation token is // signaled. } finally { // This may take up to the length of time defined // as part of the configured TryTimeout of the processor; // by default, this is 60 seconds. await processor.StopProcessingAsync(); } } catch { // If this block is invoked, then something external to the // processor was the source of the exception. } finally { // It is encouraged that you unregister your handlers when you have // finished using the Event Processor to ensure proper cleanup. processor.ProcessEventAsync -= processEventHandler; processor.ProcessErrorAsync -= Application.ProcessorErrorHandler; } #endregion }
public async Task ProcessWithHeartbeat() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample04_ProcessWithHeartbeat #if SNIPPET var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var consumerGroup = "<< NAME OF THE EVENT HUB CONSUMER GROUP >>"; #else var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; var blobContainerName = storageScope.ContainerName; var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); #endif var storageClient = new BlobContainerClient( storageConnectionString, blobContainerName); var processorOptions = new EventProcessorClientOptions { MaximumWaitTime = TimeSpan.FromMilliseconds(250) }; var processor = new EventProcessorClient( storageClient, consumerGroup, eventHubsConnectionString, eventHubName, processorOptions); async Task processEventHandler(ProcessEventArgs args) { try { if (args.HasEvent) { await Application.ProcessEventAndCheckpointAsync( args.Data, args.Partition, args.CancellationToken); } await Application.SendHeartbeatAsync(args.CancellationToken); } catch (Exception ex) { Application.HandleProcessingException(args, ex); } } try { using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); // The error handler is not relevant for this sample; for // illustration, it is delegating the implementation to the // host application. processor.ProcessEventAsync += processEventHandler; processor.ProcessErrorAsync += Application.ProcessorErrorHandler; try { await processor.StartProcessingAsync(cancellationSource.Token); await Task.Delay(Timeout.Infinite, cancellationSource.Token); } catch (TaskCanceledException) { // This is expected if the cancellation token is // signaled. } finally { // This may take slightly longer than the length of // time defined as part of the MaximumWaitTime configured // for the processor; in this example, 250 milliseconds. await processor.StopProcessingAsync(); } } catch { // If this block is invoked, then something external to the // processor was the source of the exception. } finally { // It is encouraged that you unregister your handlers when you have // finished using the Event Processor to ensure proper cleanup. processor.ProcessEventAsync -= processEventHandler; processor.ProcessErrorAsync -= Application.ProcessorErrorHandler; } #endregion }
public async Task InitializePartition() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample04_InitializePartition #if SNIPPET var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var consumerGroup = "<< NAME OF THE EVENT HUB CONSUMER GROUP >>"; #else var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; var blobContainerName = storageScope.ContainerName; var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); #endif var storageClient = new BlobContainerClient( storageConnectionString, blobContainerName); var processor = new EventProcessorClient( storageClient, consumerGroup, eventHubsConnectionString, eventHubName); Task initializeEventHandler(PartitionInitializingEventArgs args) { try { if (args.CancellationToken.IsCancellationRequested) { return(Task.CompletedTask); } // If no checkpoint was found, start processing // events enqueued now or in the future. EventPosition startPositionWhenNoCheckpoint = EventPosition.FromEnqueuedTime(DateTimeOffset.UtcNow); args.DefaultStartingPosition = startPositionWhenNoCheckpoint; } catch (Exception ex) { Application.HandleInitializeException(args, ex); } return(Task.CompletedTask); } try { using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); // The event handlers for processing events and errors are // not relevant for this sample; for illustration, they're // delegating the implementation to the host application. processor.PartitionInitializingAsync += initializeEventHandler; processor.ProcessEventAsync += Application.ProcessorEventHandler; processor.ProcessErrorAsync += Application.ProcessorErrorHandler; try { await processor.StartProcessingAsync(cancellationSource.Token); await Task.Delay(Timeout.Infinite, cancellationSource.Token); } catch (TaskCanceledException) { // This is expected if the cancellation token is // signaled. } finally { // This may take up to the length of time defined // as part of the configured TryTimeout of the processor; // by default, this is 60 seconds. await processor.StopProcessingAsync(); } } catch { // If this block is invoked, then something external to the // processor was the source of the exception. } finally { // It is encouraged that you unregister your handlers when you have // finished using the Event Processor to ensure proper cleanup processor.PartitionInitializingAsync -= initializeEventHandler; processor.ProcessEventAsync -= Application.ProcessorEventHandler; processor.ProcessErrorAsync -= Application.ProcessorErrorHandler; } #endregion }
public async Task BasicEventProcessing() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample04_BasicEventProcessing #if SNIPPET var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var consumerGroup = "<< NAME OF THE EVENT HUB CONSUMER GROUP >>"; #else var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; var blobContainerName = storageScope.ContainerName; var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); #endif var storageClient = new BlobContainerClient( storageConnectionString, blobContainerName); var processor = new EventProcessorClient( storageClient, consumerGroup, eventHubsConnectionString, eventHubName); Task processEventHandler(ProcessEventArgs args) { try { if (args.CancellationToken.IsCancellationRequested) { return(Task.CompletedTask); } string partition = args.Partition.PartitionId; byte[] eventBody = args.Data.EventBody.ToArray(); Debug.WriteLine($"Event from partition { partition } with length { eventBody.Length }."); } catch { // 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. } return(Task.CompletedTask); } Task processErrorHandler(ProcessErrorEventArgs args) { try { Debug.WriteLine("Error in the EventProcessorClient"); Debug.WriteLine($"\tOperation: { args.Operation }"); Debug.WriteLine($"\tException: { args.Exception }"); Debug.WriteLine(""); } 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 handled in any // way. Application.HandleErrorException(args, ex); } return(Task.CompletedTask); } try { using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); processor.ProcessEventAsync += processEventHandler; processor.ProcessErrorAsync += processErrorHandler; try { await processor.StartProcessingAsync(cancellationSource.Token); await Task.Delay(Timeout.Infinite, cancellationSource.Token); } catch (TaskCanceledException) { // This is expected if the cancellation token is // signaled. } finally { // This may take up to the length of time defined // as part of the configured TryTimeout of the processor; // by default, this is 60 seconds. await processor.StopProcessingAsync(); } } catch { // The processor will automatically attempt to recover from any // failures, either transient or fatal, and continue processing. // Errors in the processor's operation will be surfaced through // its error handler. // // If this block is invoked, then something external to the // processor was the source of the exception. } finally { // It is encouraged that you unregister your handlers when you have // finished using the Event Processor to ensure proper cleanup. This // is especially important when using lambda expressions or handlers // in any form that may contain closure scopes or hold other references. processor.ProcessEventAsync -= processEventHandler; processor.ProcessErrorAsync -= processErrorHandler; } #endregion }
public async Task CustomMetadata() { await using var scope = await EventHubScope.CreateAsync(1); #region Snippet:EventHubs_Sample04_CustomMetadata #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 producer = new EventHubBufferedProducerClient(connectionString, eventHubName); // The failure handler is required and invoked after all allowable // retries were applied. producer.SendEventBatchFailedAsync += args => { Debug.WriteLine($"Publishing failed for { args.EventBatch.Count } events. Error: '{ args.Exception.Message }'"); return(Task.CompletedTask); }; // The success handler is optional. producer.SendEventBatchSucceededAsync += args => { Debug.WriteLine($"{ args.EventBatch.Count } events were published to partition: '{ args.PartitionId }."); return(Task.CompletedTask); }; try { var eventData = new EventData("Hello, Event Hubs!") { MessageId = "H1", ContentType = "application/json" }; eventData.Properties.Add("EventType", "com.microsoft.samples.hello-event"); eventData.Properties.Add("priority", 1); eventData.Properties.Add("score", 9.0); await producer.EnqueueEventAsync(eventData); eventData = new EventData("Goodbye, Event Hubs!") { MessageId = "G1", ContentType = "application/json" }; eventData.Properties.Add("EventType", "com.microsoft.samples.goodbye-event"); eventData.Properties.Add("priority", "17"); eventData.Properties.Add("blob", true); await producer.EnqueueEventAsync(eventData); } finally { // Closing the producer will flush any // enqueued events that have not been published. await producer.CloseAsync(); } #endregion }
public async Task CheckpointByEventCount() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample04_CheckpointByEventCount #if SNIPPET var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var consumerGroup = "<< NAME OF THE EVENT HUB CONSUMER GROUP >>"; #else var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; var blobContainerName = storageScope.ContainerName; var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); #endif var storageClient = new BlobContainerClient( storageConnectionString, blobContainerName); var processor = new EventProcessorClient( storageClient, consumerGroup, eventHubsConnectionString, eventHubName); const int EventsBeforeCheckpoint = 25; var partitionEventCount = new ConcurrentDictionary <string, int>(); async Task processEventHandler(ProcessEventArgs args) { try { await Application.ProcessEventAsync( args.Data, args.Partition, args.CancellationToken); // If the number of events that have been processed // since the last checkpoint was created exceeds the // checkpointing threshold, a new checkpoint will be // created and the count reset. string partition = args.Partition.PartitionId; int eventsSinceLastCheckpoint = partitionEventCount.AddOrUpdate( key: partition, addValue: 1, updateValueFactory: (_, currentCount) => currentCount + 1); if (eventsSinceLastCheckpoint >= EventsBeforeCheckpoint) { await args.UpdateCheckpointAsync(); partitionEventCount[partition] = 0; } } catch (Exception ex) { Application.HandleProcessingException(args, ex); } } try { using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); // The error handler is not relevant for this sample; for // illustration, it is delegating the implementation to the // host application. processor.ProcessEventAsync += processEventHandler; processor.ProcessErrorAsync += Application.ProcessorErrorHandler; try { await processor.StartProcessingAsync(cancellationSource.Token); await Task.Delay(Timeout.Infinite, cancellationSource.Token); } catch (TaskCanceledException) { // This is expected if the cancellation token is // signaled. } finally { // This may take up to the length of time defined // as part of the configured TryTimeout of the processor; // by default, this is 60 seconds. await processor.StopProcessingAsync(); } } catch { // If this block is invoked, then something external to the // processor was the source of the exception. } finally { // It is encouraged that you unregister your handlers when you have // finished using the Event Processor to ensure proper cleanup processor.ProcessEventAsync -= processEventHandler; processor.ProcessErrorAsync -= Application.ProcessorErrorHandler; } #endregion }
public async Task FixtureSetUp() { _eventHubScope = await EventHubScope.CreateAsync(2); _storageScope = await StorageScope.CreateAsync(); }
public async Task ReadAllPartitions() { await using var scope = await EventHubScope.CreateAsync(1); #region Snippet:EventHubs_Sample07_ReadAllPartitions 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 { using (CancellationTokenSource cancellationSource = new CancellationTokenSource()) { cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); int eventsRead = 0; int maximumEvents = 50; IAsyncEnumerator <PartitionEvent> iterator = consumer.ReadEventsAsync(cancellationSource.Token).GetAsyncEnumerator(); try { while (await iterator.MoveNextAsync()) { PartitionEvent partitionEvent = iterator.Current; string readFromPartition = partitionEvent.Partition.PartitionId; byte[] eventBodyBytes = partitionEvent.Data.EventBody.ToArray(); Debug.WriteLine($"Read event of length { eventBodyBytes.Length } from { readFromPartition }"); eventsRead++; if (eventsRead >= maximumEvents) { break; } } } catch (TaskCanceledException) { // This is expected if the cancellation token is // signaled. } finally { await iterator.DisposeAsync(); } } } finally { await consumer.CloseAsync(); } #endregion }
public async Task ErrorHandlerCancellationRecovery() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample03_ErrorHandlerCancellationRecovery #if SNIPPET var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var consumerGroup = "<< NAME OF THE EVENT HUB CONSUMER GROUP >>"; #else var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; var blobContainerName = storageScope.ContainerName; var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); #endif var storageClient = new BlobContainerClient( storageConnectionString, blobContainerName); var processor = new EventProcessorClient( storageClient, consumerGroup, eventHubsConnectionString, eventHubName); // This token is used to control processing, // if signaled, then processing will be stopped. using var cancellationSource = new CancellationTokenSource(); #if !SNIPPET cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); #endif Task processEventHandler(ProcessEventArgs args) { try { // Process the event. } catch { // Handle the exception. } return(Task.CompletedTask); } async Task processErrorHandler(ProcessErrorEventArgs args) { try { // Always log the exception. Debug.WriteLine("Error in the EventProcessorClient"); Debug.WriteLine($"\tOperation: { args.Operation ?? "Unknown" }"); Debug.WriteLine($"\tPartition: { args.PartitionId ?? "None" }"); Debug.WriteLine($"\tException: { args.Exception }"); Debug.WriteLine(""); // If cancellation was requested, assume that // it was in response to an application request // and take no action. if (args.CancellationToken.IsCancellationRequested) { return; } // If out of memory, signal for cancellation. if (args.Exception is OutOfMemoryException) { cancellationSource.Cancel(); return; } // If processing stopped and this handler determined // the error to be non-fatal, restart processing. if ((!processor.IsRunning) && (!cancellationSource.IsCancellationRequested)) { // To be safe, request that processing stop before // requesting the start; this will ensure that any // processor state is fully reset. await processor.StopProcessingAsync(); await processor.StartProcessingAsync(cancellationSource.Token); } } catch { // Handle the exception. If fatal, signal // for cancellation. } } try { processor.ProcessEventAsync += processEventHandler; processor.ProcessErrorAsync += processErrorHandler; try { // Once processing has started, the delay will // block to allow processing until cancellation // is requested. await processor.StartProcessingAsync(cancellationSource.Token); await Task.Delay(Timeout.Infinite, cancellationSource.Token); } catch (TaskCanceledException) { // This is expected if the cancellation token is // signaled. } finally { // This may take up to the length of time defined // as part of the configured TryTimeout of the processor; // by default, this is 60 seconds. await processor.StopProcessingAsync(); } } finally { processor.ProcessEventAsync -= processEventHandler; processor.ProcessErrorAsync -= processErrorHandler; } #endregion }
public async Task EventHandlerStopOnException() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample03_EventHandlerStopOnException #if SNIPPET var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var consumerGroup = "<< NAME OF THE EVENT HUB CONSUMER GROUP >>"; #else var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; var blobContainerName = storageScope.ContainerName; var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); #endif var storageClient = new BlobContainerClient( storageConnectionString, blobContainerName); var processor = new EventProcessorClient( storageClient, consumerGroup, eventHubsConnectionString, eventHubName); // This token is used to control processing, // if signaled, then processing will be stopped. using var cancellationSource = new CancellationTokenSource(); #if !SNIPPET cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); #endif Task processEventHandler(ProcessEventArgs args) { try { if (args.CancellationToken.IsCancellationRequested) { return(Task.CompletedTask); } // Process the event. } catch { // Handle the exception. If fatal, // signal for cancellation. cancellationSource.Cancel(); } return(Task.CompletedTask); } Task processErrorHandler(ProcessErrorEventArgs args) { // Process the error, as appropriate for the // application. return(Task.CompletedTask); } try { processor.ProcessEventAsync += processEventHandler; processor.ProcessErrorAsync += processErrorHandler; try { // Once processing has started, the delay will // block to allow processing until cancellation // is requested. await processor.StartProcessingAsync(cancellationSource.Token); await Task.Delay(Timeout.Infinite, cancellationSource.Token); } catch (TaskCanceledException) { // This is expected if the cancellation token is // signaled. } finally { // This may take up to the length of time defined // as part of the configured TryTimeout of the processor; // by default, this is 60 seconds. await processor.StopProcessingAsync(); } } finally { processor.ProcessEventAsync -= processEventHandler; processor.ProcessErrorAsync -= processErrorHandler; } #endregion }
public async Task ReadPartitionWaitTime() { await using var scope = await EventHubScope.CreateAsync(1); #region Snippet:EventHubs_Sample05_ReadPartitionWaitTime 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 { using CancellationTokenSource cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); string firstPartition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); EventPosition startingPosition = EventPosition.Earliest; int loopTicks = 0; int maximumTicks = 10; var options = new ReadEventOptions { MaximumWaitTime = TimeSpan.FromSeconds(1) }; await foreach (PartitionEvent partitionEvent in consumer.ReadEventsFromPartitionAsync( firstPartition, startingPosition, options)) { if (partitionEvent.Data != null) { string readFromPartition = partitionEvent.Partition.PartitionId; byte[] eventBodyBytes = partitionEvent.Data.EventBody.ToArray(); Debug.WriteLine($"Read event of length { eventBodyBytes.Length } from { readFromPartition }"); } else { Debug.WriteLine("Wait time elapsed; no event was available."); } loopTicks++; if (loopTicks >= maximumTicks) { break; } } } catch (TaskCanceledException) { // This is expected if the cancellation token is // signaled. } finally { await consumer.CloseAsync(); } #endregion }
public async Task CreateReceiverWithEndOfStream() { var receiver = default(PartitionReceiver); var partitionSender = default(PartitionSender); await using (var scope = await EventHubScope.CreateAsync(1)) { var connectionString = TestUtility.BuildEventHubsConnectionString(scope.EventHubName); var ehClient = EventHubClient.CreateFromConnectionString(connectionString); try { // Randomly pick one of the available partitons. var partitions = await this.GetPartitionsAsync(ehClient); var partitionId = partitions[new Random().Next(partitions.Length)]; TestUtility.Log($"Randomly picked partition {partitionId}"); partitionSender = ehClient.CreatePartitionSender(partitionId); // Send couple of messages before creating an EndOfStream receiver. // We are not expecting to receive these messages would be sent before receiver creation. for (int i = 0; i < 10; i++) { var ed = new EventData(new byte[1]); await partitionSender.SendAsync(ed); } // Create a new receiver which will start reading from the end of the stream. TestUtility.Log($"Creating a new receiver with offset EndOFStream"); receiver = ehClient.CreateReceiver(PartitionReceiver.DefaultConsumerGroupName, partitionId, EventPosition.FromEnd()); // Attemp to receive the message. This should return only 1 message. var receiveTask = receiver.ReceiveAsync(100); // Send a new message which is expected to go to the end of stream. // We are expecting to receive only this message. // Wait 5 seconds before sending to avoid race. await Task.Delay(5000); var eventToReceive = new EventData(new byte[1]); eventToReceive.Properties["stamp"] = Guid.NewGuid().ToString(); await partitionSender.SendAsync(eventToReceive); // Complete asyncy receive task. var receivedMessages = await receiveTask; // We should have received only 1 message from this call. Assert.True(receivedMessages.Count() == 1, $"Didn't receive 1 message. Received {receivedMessages.Count()} messages(s)."); // Check stamp. Assert.True(receivedMessages.Single().Properties["stamp"].ToString() == eventToReceive.Properties["stamp"].ToString() , "Stamps didn't match on the message sent and received!"); TestUtility.Log("Received correct message as expected."); // Next receive on this partition shouldn't return any more messages. receivedMessages = await receiver.ReceiveAsync(100, TimeSpan.FromSeconds(15)); Assert.True(receivedMessages == null, $"Received messages at the end."); } finally { await Task.WhenAll( partitionSender.CloseAsync(), receiver.CloseAsync(), ehClient.CloseAsync()); } } }
public async Task ReadPartitionWithReceiver() { await using var scope = await EventHubScope.CreateAsync(1); #region Snippet:EventHubs_Sample05_ReadPartitionWithReceiver 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; using CancellationTokenSource cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); string firstPartition; await using (var producer = new EventHubProducerClient(connectionString, eventHubName)) { firstPartition = (await producer.GetPartitionIdsAsync()).First(); } var receiver = new PartitionReceiver( consumerGroup, firstPartition, EventPosition.Earliest, connectionString, eventHubName); try { while (!cancellationSource.IsCancellationRequested) { int batchSize = 50; TimeSpan waitTime = TimeSpan.FromSeconds(1); IEnumerable <EventData> eventBatch = await receiver.ReceiveBatchAsync( batchSize, waitTime, cancellationSource.Token); foreach (EventData eventData in eventBatch) { byte[] eventBodyBytes = eventData.EventBody.ToArray(); Debug.WriteLine($"Read event of length { eventBodyBytes.Length } from { firstPartition }"); } } } catch (TaskCanceledException) { // This is expected if the cancellation token is // signaled. } finally { await receiver.CloseAsync(); } #endregion }