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 var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; /*@@*/ /*@@*/ storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; /*@@*/ blobContainerName = storageScope.ContainerName; 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 >>"; /*@@*/ /*@@*/ eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; /*@@*/ eventHubName = eventHubScope.EventHubName; /*@@*/ consumerGroup = eventHubScope.ConsumerGroups.First(); 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 EventHandlerStopOnException() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample03_EventHandlerStopOnException var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; /*@@*/ /*@@*/ storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; /*@@*/ blobContainerName = storageScope.ContainerName; 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 >>"; /*@@*/ /*@@*/ eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; /*@@*/ eventHubName = eventHubScope.EventHubName; /*@@*/ consumerGroup = eventHubScope.ConsumerGroups.First(); 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(); /*@@*/ cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); 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 BasicEventProcessing() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample04_BasicEventProcessing var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; /*@@*/ /*@@*/ storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; /*@@*/ blobContainerName = storageScope.ContainerName; 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 >>"; /*@@*/ /*@@*/ eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; /*@@*/ eventHubName = eventHubScope.EventHubName; /*@@*/ consumerGroup = eventHubScope.ConsumerGroups.First(); 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 ProcessByBatch() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample04_ProcessByBatch var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; /*@@*/ /*@@*/ storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; /*@@*/ blobContainerName = storageScope.ContainerName; 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 >>"; /*@@*/ /*@@*/ eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; /*@@*/ eventHubName = eventHubScope.EventHubName; /*@@*/ consumerGroup = eventHubScope.ConsumerGroups.First(); 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 CheckpointByEventCount() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample04_CheckpointByEventCount var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; /*@@*/ /*@@*/ storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; /*@@*/ blobContainerName = storageScope.ContainerName; 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 >>"; /*@@*/ /*@@*/ eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; /*@@*/ eventHubName = eventHubScope.EventHubName; /*@@*/ consumerGroup = eventHubScope.ConsumerGroups.First(); 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 InitializePartition() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample04_InitializePartition var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; /*@@*/ /*@@*/ storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; /*@@*/ blobContainerName = storageScope.ContainerName; 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 >>"; /*@@*/ /*@@*/ eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; /*@@*/ eventHubName = eventHubScope.EventHubName; /*@@*/ consumerGroup = eventHubScope.ConsumerGroups.First(); 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 SharedAccessSignature() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample05_SharedAccessSignature var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; /*@@*/ /*@@*/ storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; /*@@*/ blobContainerName = storageScope.ContainerName; var credential = new AzureSasCredential("<< SHARED ACCESS KEY STRING >>"); var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var consumerGroup = "<< NAME OF THE EVENT HUB CONSUMER GROUP >>"; /*@@*/ /*@@*/ fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; /*@@*/ eventHubName = eventHubScope.EventHubName; /*@@*/ consumerGroup = eventHubScope.ConsumerGroups.First(); /*@@*/ /*@@*/ var resource = $"amqps://{ EventHubsTestEnvironment.Instance.FullyQualifiedNamespace }/{ eventHubScope.EventHubName }".ToLowerInvariant(); /*@@*/ var signature = new SharedAccessSignature(resource, EventHubsTestEnvironment.Instance.SharedAccessKeyName, EventHubsTestEnvironment.Instance.SharedAccessKey); /*@@*/ credential = new AzureSasCredential(signature.Value); var storageClient = new BlobContainerClient( storageConnectionString, blobContainerName); var processor = new EventProcessorClient( storageClient, consumerGroup, fullyQualifiedNamespace, eventHubName, credential); try { using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); // The event handlers are not relevant for this sample; for // illustration, they're delegating the implementation to the // host application. 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.ProcessEventAsync -= Application.ProcessorEventHandler; processor.ProcessErrorAsync -= Application.ProcessorErrorHandler; } #endregion }
public async Task ConnectionStringParse() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample05_ConnectionStringParse #if SNIPPET var credential = new DefaultAzureCredential(); 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 >>"; var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; #else var credential = EventHubsTestEnvironment.Instance.Credential; var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; var blobContainerName = storageScope.ContainerName; #endif var storageEndpoint = new BlobServiceClient(storageConnectionString).Uri; var blobUriBuilder = new BlobUriBuilder(storageEndpoint) { BlobContainerName = blobContainerName }; var storageClient = new BlobContainerClient( blobUriBuilder.ToUri(), credential); EventHubsConnectionStringProperties properties = EventHubsConnectionStringProperties.Parse(eventHubsConnectionString); var processor = new EventProcessorClient( storageClient, consumerGroup, properties.FullyQualifiedNamespace, properties.EventHubName ?? eventHubName, credential); try { using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); // The event handlers are not relevant for this sample; for // illustration, they're delegating the implementation to the // host application. 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.ProcessEventAsync -= Application.ProcessorEventHandler; processor.ProcessErrorAsync -= Application.ProcessorErrorHandler; } #endregion }
public async Task ProcessByBatch() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample07_ProcessByBatch_Usage #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 checkpointStore = new BlobCheckpointStore(storageClient); var maximumBatchSize = 100; var processor = new SimpleBatchProcessor( checkpointStore, maximumBatchSize, consumerGroup, eventHubsConnectionString, eventHubName); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); // There are no event handlers to set for the processor. All logic // normally associated with the processor event handlers is // implemented directly via method override in the custom processor. 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 { // Stopping may take up to the length of time defined // as the TryTimeout configured for the processor; // By default, this is 60 seconds. await processor.StopProcessingAsync(); } #endregion }
public async Task ProcessUntilCanceled() { await using var eventHubScope = await EventHubScope.CreateAsync(2); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_ReadMe_ProcessUntilCanceled var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(45)); #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 Task processEventHandler(ProcessEventArgs eventArgs) => Task.CompletedTask; Task processErrorHandler(ProcessErrorEventArgs eventArgs) => Task.CompletedTask; var storageClient = new BlobContainerClient(storageConnectionString, blobContainerName); var processor = new EventProcessorClient(storageClient, consumerGroup, eventHubsConnectionString, eventHubName); processor.ProcessEventAsync += processEventHandler; processor.ProcessErrorAsync += processErrorHandler; await processor.StartProcessingAsync(); try { // The processor performs its work in the background; block until cancellation // to allow processing to take place. await Task.Delay(Timeout.Infinite, cancellationSource.Token); } catch (TaskCanceledException) { // This is expected when the delay is canceled. } try { await processor.StopProcessingAsync(); } finally { // To prevent leaks, the handlers should be removed when processing is complete. processor.ProcessEventAsync -= processEventHandler; processor.ProcessErrorAsync -= processErrorHandler; } #endregion }
public async Task ProcessEvents() { await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample01_ProcessEvents #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); var partitionEventCount = new ConcurrentDictionary <string, int>(); async Task processEventHandler(ProcessEventArgs args) { try { // If the cancellation token is signaled, then the // processor has been asked to stop. It will invoke // this handler with any events that were in flight; // these will not be lost if not processed. // // It is up to the handler to decide whether to take // action to process the event or to cancel immediately. if (args.CancellationToken.IsCancellationRequested) { return; } string partition = args.Partition.PartitionId; byte[] eventBody = args.Data.EventBody.ToArray(); Debug.WriteLine($"Event from partition { partition } with length { eventBody.Length }."); int eventsSinceLastCheckpoint = partitionEventCount.AddOrUpdate( key: partition, addValue: 1, updateValueFactory: (_, currentCount) => currentCount + 1); if (eventsSinceLastCheckpoint >= 50) { await args.UpdateCheckpointAsync(); partitionEventCount[partition] = 0; } } 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. } } Task processErrorHandler(ProcessErrorEventArgs args) { try { Debug.WriteLine("Error in the EventProcessorClient"); Debug.WriteLine($"\tOperation: { args.Operation }"); Debug.WriteLine($"\tException: { args.Exception }"); Debug.WriteLine(""); } 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 handled in any // way. } 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 ClaimOwnershipAsyncReturnsOnlyTheSuccessfullyClaimedOwnership() { await using (var storageScope = await StorageScope.CreateAsync()) { var storageConnectionString = StorageTestEnvironment.StorageConnectionString; var containerClient = new BlobContainerClient(storageConnectionString, storageScope.ContainerName); var partitionManager = new BlobPartitionManager(containerClient); var ownershipList = new List <PartitionOwnership>(); var ownershipCount = 5; for (int i = 0; i < ownershipCount; i++) { ownershipList.Add( new MockPartitionOwnership ( "eventHubName", "consumerGroup", "ownerIdentifier", $"partitionId_{ i }" )); } await partitionManager.ClaimOwnershipAsync(ownershipList); // The ETags must have been set by the partition manager. var eTags = ownershipList.Select(ownership => ownership.ETag).ToList(); ownershipList.Clear(); // Use a valid eTag when 'i' is odd. This way, we can expect 'ownershipCount / 2' successful // claims (rounded down). var expectedClaimedCount = ownershipCount / 2; for (int i = 0; i < ownershipCount; i++) { ownershipList.Add( new MockPartitionOwnership ( "eventHubName", "consumerGroup", "ownerIdentifier", $"partitionId_{ i }", offset: i, eTag: i % 2 == 1 ? eTags[i] : null )); } var claimedOwnershipList = await partitionManager.ClaimOwnershipAsync(ownershipList); var expectedOwnership = ownershipList.Where(ownership => ownership.Offset % 2 == 1); Assert.That(claimedOwnershipList, Is.Not.Null); Assert.That(claimedOwnershipList.Count, Is.EqualTo(expectedClaimedCount)); var index = 0; foreach (var ownership in claimedOwnershipList.OrderBy(ownership => ownership.PartitionId)) { Assert.That(ownership.IsEquivalentTo(expectedOwnership.ElementAt(index)), Is.True, $"Ownership of partition '{ ownership.PartitionId }' should be equivalent."); ++index; } } }
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(10)); #endif Task processEventHandler(ProcessEventArgs args) { try { // TODO: // Process the event according to application needs. } catch { // TODO: // Take action to handle the exception. // // It is important that all exceptions are // handled and none are permitted to bubble up. } 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; } // Allow the application to handle the exception according to // its business logic. await HandleExceptionAsync(args.Exception, args.CancellationToken); } 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 ErrorHandlerCancellationRecovery() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample03_ErrorHandlerCancellationRecovery var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; /*@@*/ /*@@*/ storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; /*@@*/ blobContainerName = storageScope.ContainerName; 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 >>"; /*@@*/ /*@@*/ eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; /*@@*/ eventHubName = eventHubScope.EventHubName; /*@@*/ consumerGroup = eventHubScope.ConsumerGroups.First(); 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(); /*@@*/ cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); 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 DefaultAzureCredential() { await using var eventHubScope = await EventHubScope.CreateAsync(1); await using var storageScope = await StorageScope.CreateAsync(); #region Snippet:EventHubs_Processor_Sample05_DefaultAzureCredential TokenCredential credential = new DefaultAzureCredential(); var storageEndpoint = "<< STORAGE ENDPOINT (likely similar to {your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; /*@@*/ /*@@*/ storageEndpoint = new BlobServiceClient(StorageTestEnvironment.Instance.StorageConnectionString).Uri.ToString(); /*@@*/ blobContainerName = storageScope.ContainerName; var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var consumerGroup = "<< NAME OF THE EVENT HUB CONSUMER GROUP >>"; /*@@*/ /*@@*/ fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; /*@@*/ eventHubName = eventHubScope.EventHubName; /*@@*/ consumerGroup = eventHubScope.ConsumerGroups.First(); /*@@*/ credential = EventHubsTestEnvironment.Instance.Credential; var blobUriBuilder = new BlobUriBuilder(new Uri(storageEndpoint)); blobUriBuilder.BlobContainerName = blobContainerName; var storageClient = new BlobContainerClient( blobUriBuilder.ToUri(), credential); var processor = new EventProcessorClient( storageClient, consumerGroup, fullyQualifiedNamespace, eventHubName, credential); try { using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); // The event handlers are not relevant for this sample; for // illustration, they're delegating the implementation to the // host application. 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.ProcessEventAsync -= Application.ProcessorEventHandler; processor.ProcessErrorAsync -= Application.ProcessorErrorHandler; } #endregion }
public async Task FixtureSetUp() { _eventHubScope = await EventHubScope.CreateAsync(2); _storageScope = await StorageScope.CreateAsync(); }
/// <summary> /// Requests creation of an Azure storage account to use for a specific test run, /// transforming the asynchronous request into a synchronous one that can be used with /// lazy instantiation. /// </summary> /// /// <returns>The active Azure storage account for this test run./returns> /// private static StorageScope.StorageProperties CreateStorageAccount() => Task .Run(async() => await StorageScope.CreateStorageAccountAsync().ConfigureAwait(false)) .ConfigureAwait(false) .GetAwaiter() .GetResult();