From e46832258799fbfb5dc8399d92a2ee77bd340238 Mon Sep 17 00:00:00 2001 From: Jesse Squire Date: Tue, 20 Aug 2024 17:20:41 -0400 Subject: [PATCH 01/16] [Event Hubs] Convert tests to use identity auth The focus of these changes is to convert the Event Hubs live tests to use identity-based authorization by default. Connection strings will continue to have test coverage and appear in "Hello World" samples and in legacy samples for the migration guide. --- .../README.md | 65 +- .../samples/Sample01_HelloWorld.md | 10 +- .../Sample02_EventProcessorConfiguration.md | 202 +++-- .../Sample03_EventProcessorHandlers.md | 158 ++-- .../samples/Sample04_ProcessingEvents.md | 114 ++- ...le05_IdentityAndSharedAccessCredentials.md | 34 +- ...mple06_RequestingStorageServiceVersions.md | 26 +- .../samples/Sample07_BatchProcessing.md | 26 +- .../EventProcessorClientLiveTests.cs | 154 ++-- .../MigrationGuideSnippetsLiveTests.cs | 35 +- .../tests/Snippets/ReadMeSnippetsLiveTests.cs | 98 ++- ...02_EventProcessorConfigurationLiveTests.cs | 311 ++++--- ...ample03_EventProcessorHandlersLiveTests.cs | 232 +++-- .../Sample04_ProcessingEventsLiveTests.cs | 119 ++- ...tityAndSharedAccessCredentialsLiveTests.cs | 14 +- ...questingStorageServiceVersionsLiveTests.cs | 30 +- .../Sample07_BatchProcessingLiveTests.cs | 37 +- .../MigrationGuide.md | 110 ++- .../MigrationGuide_WindowsAzureServiceBus.md | 45 +- .../Azure.Messaging.EventHubs/README.md | 41 +- .../TROUBLESHOOTING.md | 46 +- .../samples/README.md | 62 +- .../samples/Sample01_HelloWorld.md | 14 +- .../samples/Sample02_EventHubsClients.md | 76 +- .../samples/Sample03_EventHubMetadata.md | 29 +- .../samples/Sample04_PublishingEvents.md | 122 ++- .../samples/Sample05_ReadingEvents.md | 109 ++- ...le06_IdentityAndSharedAccessCredentials.md | 20 +- .../Sample07_EarlierLanguageVersions.md | 30 +- .../samples/Sample08_CustomEventProcessor.md | 30 +- .../samples/Sample09_ObservableEventBatch.md | 16 +- .../Sample10_AzureEventSourceListener.md | 42 +- .../samples/Sample11_MockingClientTypes.md | 8 +- .../Connection/EventHubConnectionLiveTests.cs | 79 +- .../EventHubConsumerClientLiveTests.cs | 489 +++++++---- .../Primitives/PartitionReceiverLiveTests.cs | 824 +++++++++++++----- ...EventHubBufferedProducerClientLiveTests.cs | 113 ++- .../EventHubProducerClientLiveTests.cs | 181 ++-- .../Producer/IdempotentPublishingLiveTests.cs | 198 +++-- .../tests/Snippets/ReadMeSnippetsLiveTests.cs | 2 +- .../Snippets/Sample01_HelloWorldLiveTests.cs | 16 +- .../Sample02_EventHubsClientsLiveTests.cs | 75 +- .../Sample03_EventHubMetadataLiveTests.cs | 35 +- .../Sample04_PublishingEventsLiveTests.cs | 135 ++- .../Sample05_ReadingEventsLiveTests.cs | 116 ++- ...mple07_EarlierLanguageVersionsLiveTests.cs | 23 +- .../Sample08_CustomEventProcessorLiveTests.cs | 30 +- .../Sample09_ObservableEventBatchLiveTests.cs | 23 +- .../Sample10_AzureEventSourceListenerTests.cs | 50 +- .../tests/Snippets/SamplesCommonTests.cs | 8 +- 50 files changed, 3246 insertions(+), 1616 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/README.md b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/README.md index 6e8a98dfd82ce..249e00b104542 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/README.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/README.md @@ -120,10 +120,12 @@ var processor = new EventProcessorClient(storageClient, consumerGroup, eventHubs In order to use the `EventProcessorClient`, handlers for event processing and errors must be provided. These handlers are considered self-contained and developers are responsible for ensuring that exceptions within the handler code are accounted for. ```C# Snippet:EventHubs_Processor_ReadMe_ConfigureHandlers -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; @@ -157,8 +159,23 @@ async Task processErrorHandler(ProcessErrorEventArgs eventArgs) } } -var storageClient = new BlobContainerClient(storageConnectionString, blobContainerName); -var processor = new EventProcessorClient(storageClient, consumerGroup, eventHubsConnectionString, eventHubName); +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + +var storageClient = new BlobContainerClient( + blobUriBuilder.ToUri(), + credential); + +var processor = new EventProcessorClient +( + storageClient, + consumerGroup, + fullyQualifiedNamespace, + eventHubName, + credential +); processor.ProcessEventAsync += processEventHandler; processor.ProcessErrorAsync += processErrorHandler; @@ -172,18 +189,35 @@ The `EventProcessorClient` will perform its processing in the background once it var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(45)); -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; 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); +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + +var storageClient = new BlobContainerClient( + blobUriBuilder.ToUri(), + credential); + +var processor = new EventProcessorClient +( + storageClient, + consumerGroup, + fullyQualifiedNamespace, + eventHubName, + credential +); processor.ProcessEventAsync += processEventHandler; processor.ProcessErrorAsync += processErrorHandler; @@ -225,13 +259,22 @@ To make use of an Active Directory principal with Azure Storage blob containers, ```C# Snippet:EventHubs_Processor_ReadMe_CreateWithIdentity var credential = new DefaultAzureCredential(); -var blobStorageUrl ="<< FULLY-QUALIFIED CONTAINER URL (like https://myaccount.blob.core.windows.net/mycontainer) >>"; -var fullyQualifiedNamespace = "<< FULLY-QUALIFIED EVENT HUBS NAMESPACE (like something.servicebus.windows.net) >>"; +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; +var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; + +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 >>"; -var storageClient = new BlobContainerClient(new Uri(blobStorageUrl), credential); +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + +var storageClient = new BlobContainerClient( + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient ( diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample01_HelloWorld.md b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample01_HelloWorld.md index e4333c783818d..d53cb5b428352 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample01_HelloWorld.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample01_HelloWorld.md @@ -12,13 +12,13 @@ To begin, please ensure that you're familiar with the items discussed in the [Ge ## Client lifetime -Each of the Event Hubs client types is safe to cache and use for the lifetime of the application, which is best practice when the application publishes or reads events regularly or semi-regularly. The clients are responsible for efficient resource management, working to keep resource usage low during periods of inactivity and manage health during periods of higher use. +Each of the Event Hubs client types is safe to cache and use for the lifetime of the application, which is best practice when the application publishes or reads events regularly or semi-regularly. The clients are responsible for efficient resource management, working to keep resource usage low during periods of inactivity and manage health during periods of higher use. For the `EventProcessorClient`, calling the `StopProcessingAsync` method when your application is closing will ensure that network resources and other unmanaged objects are cleaned up. Calling either the `CloseAsync` or `DisposeAsync` method on the `EventHubProducerClient` will perform the equivalent clean-up. ## Publish events -To publish events, we will make use of the `EventHubsProducerClient`. Because this is the only area of our sample that will be publishing events, we will close the client once publishing has completed. In the majority of real-world scenarios, closing the producer when the application exits is the preferred pattern. +To publish events, we will make use of the `EventHubsProducerClient`. Because this is the only area of our sample that will be publishing events, we will close the client once publishing has completed. In the majority of real-world scenarios, closing the producer when the application exits is the preferred pattern. So that we have something to process, our example will publish a full batch of events. The `EventHubDataBatch` exists to ensure that a set of events can safely be published without exceeding the size allowed by the Event Hub. The `EventDataBatch` queries the service to understand the maximum size and is responsible for accurately measuring each event as it is added to the batch. When its `TryAdd` method returns `false`, the event is too large to fit into the batch. @@ -74,9 +74,9 @@ finally Now that the events have been published, we'll process them using the `EventProcessorClient`. It's important to note that because events are not removed when reading, you are likely to see events that had been previously published as well as those from the batch that we just sent, if you're using an existing Event Hub. -The `EventProcessorClient` is associated with a specific Event Hub and [consumer group](https://docs.microsoft.com/azure/event-hubs/event-hubs-features#consumer-groups). Conceptually, the consumer group is a label that identifies one or more event consumers as a set. Often, consumer groups are named after the responsibility of the consumer in an application, such as "Telemetry" or "OrderProcessing". When an Event Hub is created, a default consumer group is created for it. The default group, named "$Default", is what we'll be using for illustration. +The `EventProcessorClient` is associated with a specific Event Hub and [consumer group](https://learn.microsoft.com/azure/event-hubs/event-hubs-features#consumer-groups). Conceptually, the consumer group is a label that identifies one or more event consumers as a set. Often, consumer groups are named after the responsibility of the consumer in an application, such as "Telemetry" or "OrderProcessing". When an Event Hub is created, a default consumer group is created for it. The default group, named "$Default", is what we'll be using for illustration. -When events are published, they will continue to exist in the Event Hub and be available for consuming until they reach an age greater than the [retention period](https://docs.microsoft.com//azure/event-hubs/event-hubs-faq#what-is-the-maximum-retention-period-for-events). Once removed, the events are no longer available to be read and cannot be recovered. Though the Event Hubs service is free to remove events older than the retention period, it does not do so deterministically; there is no guarantee of when events will be removed. +When events are published, they will continue to exist in the Event Hub and be available for consuming until they reach an age greater than the [retention period](https://learn.microsoft.com//azure/event-hubs/event-hubs-faq#what-is-the-maximum-retention-period-for-events). Once removed, the events are no longer available to be read and cannot be recovered. Though the Event Hubs service is free to remove events older than the retention period, it does not do so deterministically; there is no guarantee of when events will be removed. Each `EventProcessorClient` has its own full view of the events each partition of an Event Hub, meaning that events are available to all processors and are not removed from the partition when a processor reads them. This allows for one or more of the different Event Hub clients to read and process events from the partition at different speeds and beginning with different events without interfering with one another. @@ -218,4 +218,4 @@ finally processor.ProcessEventAsync -= processEventHandler; processor.ProcessErrorAsync -= processErrorHandler; } -``` \ No newline at end of file +``` diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample02_EventProcessorConfiguration.md b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample02_EventProcessorConfiguration.md index fdb831d8d6d3e..c4c30bb327496 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample02_EventProcessorConfiguration.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample02_EventProcessorConfiguration.md @@ -34,13 +34,13 @@ As part of its normal operation, an `EventProcessorClient` needs to enumerate th ## Controlling processor identity -When constructing an `EventProcessorClient`, it is recommended that you set a stable unique identifier for the instance. This can be done by setting the [Identifier](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventprocessorclientoptions.identifier?view=azure-dotnet#azure-messaging-eventhubs-eventprocessorclientoptions-identifier) property of [EventProcessorClientOptions](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventprocessorclientoptions) and passing the options to the constructor. +When constructing an `EventProcessorClient`, it is recommended that you set a stable unique identifier for the instance. This can be done by setting the [Identifier](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventprocessorclientoptions.identifier?view=azure-dotnet#azure-messaging-eventhubs-eventprocessorclientoptions-identifier) property of [EventProcessorClientOptions](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventprocessorclientoptions) and passing the options to the constructor. A stable identifier allows the processor to recover partition ownership when an application or host instance is restarted. It also aids readability in Azure SDK logs and allows for more easily correlating logs to a specific processor instance. ## Influencing load balancing behavior -To scale event processing, you can run multiple instances of the `EventProcessorClient` and they will coordinate to balance work between them. The responsibility for processing is distributed among each of the active processors configured to read from the same Event Hub and using the same consumer group. To balance work, each active `EventProcessorClient` instance will assume responsibility for processing a set of Event Hub partitions, referred to as "owning" the partitions. The processors collaborate on ownership using storage as a central point of coordination. +To scale event processing, you can run multiple instances of the `EventProcessorClient` and they will coordinate to balance work between them. The responsibility for processing is distributed among each of the active processors configured to read from the same Event Hub and using the same consumer group. To balance work, each active `EventProcessorClient` instance will assume responsibility for processing a set of Event Hub partitions, referred to as "owning" the partitions. The processors collaborate on ownership using storage as a central point of coordination. While an `EventProcessorClient` is running, it will periodically perform a load balancing cycle in which it audits its own health and inspects the current state of collaboration with other processors. As part of that cycle, it will refresh the timestamp on an ownership record for each partition that it owns. These ownership records help to ensure that each `EventProcessorClient` understands how to maintain its fair share of partitions. @@ -48,13 +48,15 @@ There are several configuration options that can be used together to influence t ### Load balancing strategy -This controls the approach that the `EventProcessorClient` will use to make decisions about how aggressively to request partition ownership; this is most impactful during the initial startup or when recovering from a crash. More information on the strategies available can be found in the [documentation](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.processor.loadbalancingstrategy). +This controls the approach that the `EventProcessorClient` will use to make decisions about how aggressively to request partition ownership; this is most impactful during the initial startup or when recovering from a crash. More information on the strategies available can be found in the [documentation](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.processor.loadbalancingstrategy). ```C# Snippet:EventHubs_Processor_Sample02_LoadBalancingStrategy -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; @@ -63,29 +65,37 @@ var processorOptions = new EventProcessorClientOptions LoadBalancingStrategy = LoadBalancingStrategy.Greedy }; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); ``` ### Load balancing intervals -There are two intervals considered during load balancing which can influence its behavior. The `LoadBalancingUpdateInterval` controls how frequently a load balancing cycle is run. During the load balancing cycle, the `EventProcessorClient` will attempt to refresh its ownership record for each partition that it owns. The `PartitionOwnershipExpirationInterval` controls how long an ownership record is considered valid. If the processor does not update an ownership record before this interval elapses, the partition represented by this record is considered unowned and is eligible to be claimed by another processor. +There are two intervals considered during load balancing which can influence its behavior. The `LoadBalancingUpdateInterval` controls how frequently a load balancing cycle is run. During the load balancing cycle, the `EventProcessorClient` will attempt to refresh its ownership record for each partition that it owns. The `PartitionOwnershipExpirationInterval` controls how long an ownership record is considered valid. If the processor does not update an ownership record before this interval elapses, the partition represented by this record is considered unowned and is eligible to be claimed by another processor. It is recommended that the `PartitionOwnershipExpirationInterval` be at least 3 times greater than the `LoadBalancingUpdateInterval` and very strongly advised that it should be no less than twice as long. When these intervals are too close together, ownership may expire before it is renewed during load balancing which will cause partitions to migrate. ```C# Snippet:EventHubs_Processor_Sample02_LoadBalancingIntervals -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; @@ -95,27 +105,35 @@ var processorOptions = new EventProcessorClientOptions PartitionOwnershipExpirationInterval = TimeSpan.FromSeconds(30) }; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); ``` -## Using web sockets +## Using web sockets Communication with the Event Hubs service can be configured by adjusting the `EventHubConfigurationOptions` that are exposed by the `ConnectionOptions` member of a client options type. By default, the `EventProcessorClient` communicates using the AMQP protocol over TCP. Some application host environments prefer to restrict raw TCP socket use, especially in many enterprise or VPN scenarios. In these environments, or when a proxy is in use, communication with the Event Hubs service can make use of web sockets by configuring the client's connection settings. ```C# Snippet:EventHubs_Processor_Sample02_TransportFullConnectionOptions -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; @@ -127,51 +145,67 @@ var processorOptions = new EventProcessorClientOptions } }; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); ``` The connection options are populated by default; you may set just the desired properties rather than creating a new instance, if you prefer. ```C# Snippet:EventHubs_Processor_Sample02_TransportProperty -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; var processorOptions = new EventProcessorClientOptions(); processorOptions.ConnectionOptions.TransportType = EventHubsTransportType.AmqpWebSockets; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); ``` ## Setting a custom proxy -A common scenario for adjusting the connection options is configuring a proxy. Proxy support takes the form of the [IWebProxy](https://docs.microsoft.com/dotnet/api/system.net.iwebproxy?view=netcore-3.1) interface, of which [WebProxy](https://docs.microsoft.com/dotnet/api/system.net.webproxy?view=netcore-3.1) is the most common default implementation. Event Hubs supports a proxy only when using `AmqpWebSockets` as the transport type. +A common scenario for adjusting the connection options is configuring a proxy. Proxy support takes the form of the [IWebProxy](https://learn.microsoft.com/dotnet/api/system.net.iwebproxy?view=netcore-3.1) interface, of which [WebProxy](https://learn.microsoft.com/dotnet/api/system.net.webproxy?view=netcore-3.1) is the most common default implementation. Event Hubs supports a proxy only when using `AmqpWebSockets` as the transport type. ```C# Snippet:EventHubs_Processor_Sample02_ProxyFullConnectionOptions -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; @@ -184,25 +218,33 @@ var processorOptions = new EventProcessorClientOptions } }; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); ``` The connection options are populated by default; you may set just the desired properties rather than creating a new instance, if you prefer. ```C# Snippet:EventHubs_Processor_Sample02_ProxyProperty -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; @@ -210,21 +252,27 @@ var processorOptions = new EventProcessorClientOptions(); processorOptions.ConnectionOptions.TransportType = EventHubsTransportType.AmqpWebSockets; processorOptions.ConnectionOptions.Proxy = new WebProxy("https://proxyserver:80", true); +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); ``` ## Using the default system proxy -To use the default proxy for your environment, the recommended approach is to make use of [HttpClient.DefaultProxy](https://docs.microsoft.com/dotnet/api/system.net.http.httpclient.defaultproxy?view=netcore-3.1), which will attempt to detect proxy settings from the ambient environment in a manner consistent with expectations for the target platform. +To use the default proxy for your environment, the recommended approach is to make use of [HttpClient.DefaultProxy](https://learn.microsoft.com/dotnet/api/system.net.http.httpclient.defaultproxy?view=netcore-3.1), which will attempt to detect proxy settings from the ambient environment in a manner consistent with expectations for the target platform. **Note:** This member was first introduced in .NET Core 3.1 and is not supported for earlier target frameworks. @@ -243,39 +291,49 @@ Connections to the Azure Event Hubs service are made using the fully qualified n However, a custom address is required for proper routing by some environments, such as those using unconventional proxy configurations or certain configurations of an Express Route circuit. To support these scenarios, a custom endpoint address may be specified as part of the connection options. This custom address will take precedence for establishing the connection to the Event Hubs service. ```C# Snippet:EventHubs_Processor_Sample02_ConnectionOptionsCustomEndpoint -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; var processorOptions = new EventProcessorClientOptions(); processorOptions.ConnectionOptions.CustomEndpointAddress = new Uri("amqps://app-gateway.mycompany.com"); +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); ``` ## Influencing SSL certificate validation -For some environments using a proxy or custom gateway for routing traffic to Event Hubs, a certificate not trusted by the root certificate authorities may be issued. This can often be a self-signed certificate from the gateway or one issued by a company's internal certificate authority. +For some environments using a proxy or custom gateway for routing traffic to Event Hubs, a certificate not trusted by the root certificate authorities may be issued. This can often be a self-signed certificate from the gateway or one issued by a company's internal certificate authority. -By default, these certificates are not trusted by the Event Hubs client library and the connection will be refused. To enable these scenarios, a [RemoteCertificateValidationCallback](https://docs.microsoft.com/dotnet/api/system.net.security.remotecertificatevalidationcallback) can be registered to provide custom validation logic for remote certificates. This allows an application to override the default trust decision and assert responsibility for accepting or rejecting the certificate. +By default, these certificates are not trusted by the Event Hubs client library and the connection will be refused. To enable these scenarios, a [RemoteCertificateValidationCallback](https://learn.microsoft.com/dotnet/api/system.net.security.remotecertificatevalidationcallback) can be registered to provide custom validation logic for remote certificates. This allows an application to override the default trust decision and assert responsibility for accepting or rejecting the certificate. ```C# Snippet:EventHubs_Processor_Sample02_RemoteCertificateValidationCallback -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; @@ -299,15 +357,21 @@ static bool ValidateServerCertificate( var processorOptions = new EventProcessorClientOptions(); processorOptions.ConnectionOptions.CertificateValidationCallback = ValidateServerCertificate; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); ``` @@ -315,13 +379,15 @@ var processor = new EventProcessorClient( The built-in retry policy offers an implementation for an exponential back-off strategy by default, as this provides a good balance between making forward progress and allowing for transient issues that may take some time to resolve. The built-in policy also offers a fixed strategy for those cases where your application requires that you have a deterministic understanding of how long an operation may take. -The values used as thresholds for the different aspects of these strategies can be configured by adjusting the `EventHubsRetryOptions` that are exposed by the `RetryOptions` member of a client options type. +The values used as thresholds for the different aspects of these strategies can be configured by adjusting the `EventHubsRetryOptions` that are exposed by the `RetryOptions` member of a client options type. ```C# Snippet:EventHubs_Processor_Sample02_RetryWithFullOptions -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; @@ -336,25 +402,33 @@ var processorOptions = new EventProcessorClientOptions } }; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); ``` The retry options are populated by default; you may set just the desired properties rather than creating a new instance, if you prefer. ```C# Snippet:EventHubs_Processor_Sample02_RetryByProperty -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; @@ -362,15 +436,21 @@ var processorOptions = new EventProcessorClientOptions(); processorOptions.RetryOptions.Mode = EventHubsRetryMode.Fixed; processorOptions.RetryOptions.MaximumRetries = 5; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); ``` @@ -423,4 +503,4 @@ var options = new EventHubsRetryOptions { CustomRetryPolicy = new ExampleRetryPolicy() }; -``` \ No newline at end of file +``` diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample03_EventProcessorHandlers.md b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample03_EventProcessorHandlers.md index df93787629a56..9e23058e482a3 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample03_EventProcessorHandlers.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample03_EventProcessorHandlers.md @@ -1,6 +1,6 @@ # Event Processor Handlers -Once started, the majority of work performed by the `EventProcessorClient` takes place in the background. Interaction with the host application takes place using .NET [events](https://docs.microsoft.com/dotnet/standard/events/), allowing the processor to surface information and the application to influence processor behavior. Unlike most .NET events, those used by the processor are asynchronous and allow only a single handler to be subscribed. +Once started, the majority of work performed by the `EventProcessorClient` takes place in the background. Interaction with the host application takes place using .NET [events](https://learn.microsoft.com/dotnet/standard/events/), allowing the processor to surface information and the application to influence processor behavior. Unlike most .NET events, those used by the processor are asynchronous and allow only a single handler to be subscribed. This sample details the means to receive information and interact with the `EventProcessorClient` as it is running and demonstrates how to configure the event handlers for some common scenarios. To begin, please ensure that you're familiar with the items discussed in the [Getting started](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples#getting-started) section of the README, and have the prerequisites and connection string information available. @@ -21,31 +21,39 @@ This sample details the means to receive information and interact with the `Even ## Process Event -The processor will invoke the `ProcessEventAsync` handler when an event read from the Event Hubs service is available for processing or, if the [MaximumWaitTime](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventprocessorclientoptions.maximumwaittime?view=azure-dotnet#Azure_Messaging_EventHubs_EventProcessorClientOptions_MaximumWaitTime) was specified, when that duration has elapsed without an event being available. This handler will be invoked concurrently, limited to one call per partition. The processor will await each invocation to ensure that the events from the same partition are processed one-at-a-time in the order that they were read from the partition. +The processor will invoke the `ProcessEventAsync` handler when an event read from the Event Hubs service is available for processing or, if the [MaximumWaitTime](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventprocessorclientoptions.maximumwaittime?view=azure-dotnet#Azure_Messaging_EventHubs_EventProcessorClientOptions_MaximumWaitTime) was specified, when that duration has elapsed without an event being available. This handler will be invoked concurrently, limited to one call per partition. The processor will await each invocation to ensure that the events from the same partition are processed one-at-a-time in the order that they were read from the partition. Processing events are covered in more depth for different scenarios in [Sample04_ProcessingEvents](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample04_ProcessingEvents.md). ### Respecting cancellation -The [event arguments](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.processor.processeventargs?view=azure-dotnet) contain a cancellation token that the `EventProcessorClient` uses to signal the handler that processing should cease as soon as possible. This is most commonly seen when the `EventProcessorClient` is stopping or has encountered an unrecoverable problem. It is up to the handler to decide whether to take action to process the event and, perhaps, record a checkpoint or to cancel immediately. If the handler chooses not to process the event, the data will not be lost and the event will be replayed when the partition processed in the future, so long as the event is not used to create a checkpoint. +The [event arguments](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.processor.processeventargs?view=azure-dotnet) contain a cancellation token that the `EventProcessorClient` uses to signal the handler that processing should cease as soon as possible. This is most commonly seen when the `EventProcessorClient` is stopping or has encountered an unrecoverable problem. It is up to the handler to decide whether to take action to process the event and, perhaps, record a checkpoint or to cancel immediately. If the handler chooses not to process the event, the data will not be lost and the event will be replayed when the partition processed in the future, so long as the event is not used to create a checkpoint. ```C# Snippet:EventHubs_Processor_Sample03_EventHandlerCancellation -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); Task processEventHandler(ProcessEventArgs args) { @@ -92,25 +100,33 @@ It is important to note that the error handler is **_NOT_** invoked for failures ### Inspecting error details -The [event arguments](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.processor.processerroreventargs?view=azure-dotnet) contain a cancellation token that the `EventProcessorClient` uses to signal the handler that processing should cease as soon as possible. This is most commonly seen when the `EventProcessorClient` is stopping or has encountered an unrecoverable problem. It is up to the handler to decide whether to take action for the error or cancel immediately. The arguments also contain information about the exception that was observed, the operation that the processor was performing at the time, and the partition that the operation was associated with, if any. +The [event arguments](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.processor.processerroreventargs?view=azure-dotnet) contain a cancellation token that the `EventProcessorClient` uses to signal the handler that processing should cease as soon as possible. This is most commonly seen when the `EventProcessorClient` is stopping or has encountered an unrecoverable problem. It is up to the handler to decide whether to take action for the error or cancel immediately. The arguments also contain information about the exception that was observed, the operation that the processor was performing at the time, and the partition that the operation was associated with, if any. ```C# Snippet:EventHubs_Processor_Sample03_ErrorHandlerArgs -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); Task processErrorHandler(ProcessErrorEventArgs args) { @@ -154,7 +170,7 @@ finally ### Reacting to processor errors -The exceptions surfaced to your error handler represent a failure within the infrastructure of the processor. The processor is highly resilient; there is generally no action needed by your application to react to occasional errors. +The exceptions surfaced to your error handler represent a failure within the infrastructure of the processor. The processor is highly resilient; there is generally no action needed by your application to react to occasional errors. The processor lacks insight into your application, host environment, and error patterns observed over time. If you're seeing frequent exceptions in your handler or consistent patterns - those often indicate a problem that needs to be addressed. While the processor is likely to recover from that specific instance of the error but, in aggregate, there may need to consider a wider problem. @@ -165,22 +181,30 @@ The error handler (but no other event handler) may safely call `StopProcessingAs This example demonstrates signaling the application to stop processing if the application is out of memory and restarting the processor if it indicates that it has stopped running. ```C# Snippet:EventHubs_Processor_Sample03_ErrorHandlerCancellationRecovery -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); // This token is used to control processing, // if signaled, then processing will be stopped. @@ -281,26 +305,34 @@ When the `EventProcessorClient` begins processing, it will take ownership over a ### Requesting a default starting point for the partition When a partition is initialized, one of the decisions made is where in the partition's event stream to begin processing. If a checkpoint exists for a partition, processing will begin at the next available event after the checkpoint. When no checkpoint is found for a partition, a default location is used. One of the common reasons that you may choose to participate in initialization is to influence where to begin processing when a checkpoint is not found, overriding the default. - -The [event arguments](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.processor.partitioninitializingeventargs?view=azure-dotnet) contain a `DefaultStartingPosition` which can be used to influence where processing begins when a checkpoint is unavailable. The arguments also contain a cancellation token that the `EventProcessorClient` uses to signal the handler that initialization should cease as soon as possible. This is most commonly seen when the `EventProcessorClient` is stopping or has encountered an unrecoverable problem. It is up to the handler to decide whether to take action or to cancel immediately, but there typically is no benefit to continuing initialization when the token has been signaled. + +The [event arguments](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.processor.partitioninitializingeventargs?view=azure-dotnet) contain a `DefaultStartingPosition` which can be used to influence where processing begins when a checkpoint is unavailable. The arguments also contain a cancellation token that the `EventProcessorClient` uses to signal the handler that initialization should cease as soon as possible. This is most commonly seen when the `EventProcessorClient` is stopping or has encountered an unrecoverable problem. It is up to the handler to decide whether to take action or to cancel immediately, but there typically is no benefit to continuing initialization when the token has been signaled. ```C# Snippet:EventHubs_Processor_Sample03_InitializeHandlerArgs -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); Task initializeEventHandler(PartitionInitializingEventArgs args) { @@ -350,25 +382,33 @@ The processor will invoke the `PartitionClosingAsync` handler when processing fo ### Inspecting closing details -The [event arguments](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.processor.partitionclosingeventargs?view=azure-dotnet) contain a cancellation token that the `EventProcessorClient` uses to signal the handler that processing should cease as soon as possible. This is most commonly seen when the `EventProcessorClient` is stopping or has encountered an unrecoverable problem. It is up to the handler to decide whether to take action for the error to cancel immediately. The arguments also contain information about the reason for closing the partition and the partition being closed. +The [event arguments](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.processor.partitionclosingeventargs?view=azure-dotnet) contain a cancellation token that the `EventProcessorClient` uses to signal the handler that processing should cease as soon as possible. This is most commonly seen when the `EventProcessorClient` is stopping or has encountered an unrecoverable problem. It is up to the handler to decide whether to take action for the error to cancel immediately. The arguments also contain information about the reason for closing the partition and the partition being closed. ```C# Snippet:EventHubs_Processor_Sample03_CloseHandlerArgs -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); Task closeEventHandler(PartitionClosingEventArgs args) { @@ -425,22 +465,30 @@ The following examples discuss common guidance for handlers used with the `Event It is extremely important that you always guard against exceptions in your handler code; it is strongly recommended to wrap your entire handler in a `try/catch` block and ensure that you do not re-throw exceptions. The processor does not have enough understanding of your handler code to determine the correct action to take in the face of an exception nor to understand whether it is safe to assume that processing has not been corrupted. Any exceptions thrown from your handler will not be caught by the processor and will NOT be redirected to the error handler. This will typically cause processing for the partition to abort, and be restarted, but may also crash your application process. ```C# Snippet:EventHubs_Processor_Sample03_EventHandlerExceptionHandling -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); Task processEventHandler(ProcessEventArgs args) { @@ -479,22 +527,30 @@ finally With the notable exception of the `ProcessErrorAsync` handler, the `EventProcessorClient` will await a handler when it is invoked. Because of this, you are unable to safely perform operations on the client, such as calling `StopProcessingAsync` when an exception is observed. Doing so is likely to result in a deadlock. A common technique to work around this limitation for is to signal a cancellation token observed by the application. ```C# Snippet:EventHubs_Processor_Sample03_EventHandlerStopOnException -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); // This token is used to control processing, // if signaled, then processing will be stopped. @@ -568,4 +624,4 @@ finally processor.ProcessEventAsync -= processEventHandler; processor.ProcessErrorAsync -= processErrorHandler; } -``` \ No newline at end of file +``` diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample04_ProcessingEvents.md b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample04_ProcessingEvents.md index 3e09dfd8e3fed..17864c4779d23 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample04_ProcessingEvents.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample04_ProcessingEvents.md @@ -21,19 +21,19 @@ This sample demonstrates scenarios for processing events read from the Event Hub The `EventProcessorClient` is intended to provide a robust and resilient client for processing events from an Event Hub and is capable of automatically managing the recovery process for transient failures. It will also collaborate with other `EventProcessorClient` instances to dynamically distribute and share processing responsibility as processors are added and removed from the group. -The `EventProcessorClient` is safe to cache and use for the lifetime of the application, which is best practice when the application processes events regularly or semi-regularly. The processor is responsible for efficient resource management, working to keep resource usage low during periods of inactivity and manage health during periods of higher use. Calling the `StopProcessingAsync` method when your application is closing will ensure that network resources and other unmanaged objects are cleaned up. +The `EventProcessorClient` is safe to cache and use for the lifetime of the application, which is best practice when the application processes events regularly or semi-regularly. The processor is responsible for efficient resource management, working to keep resource usage low during periods of inactivity and manage health during periods of higher use. Calling the `StopProcessingAsync` method when your application is closing will ensure that network resources and other unmanaged objects are cleaned up. ## Event lifetime -When events are published, they will continue to exist in the Event Hub and be available for consuming until they reach an age greater than the [retention period](https://docs.microsoft.com//azure/event-hubs/event-hubs-faq#what-is-the-maximum-retention-period-for-events). Once removed, the events are no longer available to be read and cannot be recovered. Though the Event Hubs service is free to remove events older than the retention period, it does not do so deterministically; there is no guarantee of when events will be removed. +When events are published, they will continue to exist in the Event Hub and be available for consuming until they reach an age greater than the [retention period](https://learn.microsoft.com//azure/event-hubs/event-hubs-faq#what-is-the-maximum-retention-period-for-events). Once removed, the events are no longer available to be read and cannot be recovered. Though the Event Hubs service is free to remove events older than the retention period, it does not do so deterministically; there is no guarantee of when events will be removed. ## Processing and consumer groups -An `EventProcessorClient` is associated with a specific Event Hub and [consumer group](https://docs.microsoft.com/azure/event-hubs/event-hubs-features#consumer-groups). Conceptually, the consumer group is a label that identifies one or more event consumers as a set. Often, consumer groups are named after the responsibility of the consumer in an application, such as "Telemetry" or "OrderProcessing". When an Event Hub is created, a default consumer group is created for it, named "$Default." These examples will make use of the default consumer group for illustration. +An `EventProcessorClient` is associated with a specific Event Hub and [consumer group](https://learn.microsoft.com/azure/event-hubs/event-hubs-features#consumer-groups). Conceptually, the consumer group is a label that identifies one or more event consumers as a set. Often, consumer groups are named after the responsibility of the consumer in an application, such as "Telemetry" or "OrderProcessing". When an Event Hub is created, a default consumer group is created for it, named "$Default." These examples will make use of the default consumer group for illustration. ## Processing and partitions -Every event that is published is sent to one of the [partitions](https://docs.microsoft.com/azure/architecture/reference-architectures/event-hubs/partitioning-in-event-hubs-and-kafka) of the Event Hub. When processing events, the `EventProcessorClient` will take ownership over a set of partitions to process, treating each as an independent unit of work. This allows the processor to isolate partitions from one another, helping to ensure that a failure in one partition does not impact processing for another. +Every event that is published is sent to one of the [partitions](https://learn.microsoft.com/azure/architecture/reference-architectures/event-hubs/partitioning-in-event-hubs-and-kafka) of the Event Hub. When processing events, the `EventProcessorClient` will take ownership over a set of partitions to process, treating each as an independent unit of work. This allows the processor to isolate partitions from one another, helping to ensure that a failure in one partition does not impact processing for another. ## Checkpointing @@ -43,25 +43,25 @@ When an event processor connects, it will begin reading events at the checkpoint ## Load balancing -If more than one `EventProcessorClient` is configured to process an Event Hub, belongs to the same consumer group, and make use of the same Blob Storage container, those processors will collaborate using Blob storage to share responsibility for processing the partitions of the Event Hub. Each `EventProcessorClient` will claim ownership of partitions until each had an equal share; the processors will ensure that each partition belongs to only a single processor. As processors are added or removed from the group, the partitions will be redistributed to keep the work even. +If more than one `EventProcessorClient` is configured to process an Event Hub, belongs to the same consumer group, and make use of the same Blob Storage container, those processors will collaborate using Blob storage to share responsibility for processing the partitions of the Event Hub. Each `EventProcessorClient` will claim ownership of partitions until each had an equal share; the processors will ensure that each partition belongs to only a single processor. As processors are added or removed from the group, the partitions will be redistributed to keep the work even. -An important call-out is that Event Hubs has an [at-least-once delivery guarantee](https://docs.microsoft.com/azure/event-grid/compare-messaging-services#event-hubs); it is highly recommended to ensure that your processing is resilient to event duplication in whatever way is appropriate for your application scenarios. +An important call-out is that Event Hubs has an [at-least-once delivery guarantee](https://learn.microsoft.com/azure/event-grid/compare-messaging-services#event-hubs); it is highly recommended to ensure that your processing is resilient to event duplication in whatever way is appropriate for your application scenarios. This can be observed when a processor is starting up, as it will attempt to claim ownership of partitions by taking those that do not currently have owners. In the case where a processor isn’t able to reach its fair share by claiming unowned partitions, it will attempt to steal ownership from other processors. During this time, the new owner will begin reading from the last recorded checkpoint. At the same time, the old owner may be dispatching the events that it last read to the handler for processing; it will not understand that ownership has changed until it attempts to read the next set of events from the Event Hubs service. -As a result, you are likely to see some duplicate events being processed when `EventProcessorClients` join or leave the consumer group, which will subside when the processors have reached a stable state with respect to load balancing. The duration of that window will differ depending on the configuration of your processor and your checkpointing strategy. +As a result, you are likely to see some duplicate events being processed when `EventProcessorClients` join or leave the consumer group, which will subside when the processors have reached a stable state with respect to load balancing. The duration of that window will differ depending on the configuration of your processor and your checkpointing strategy. ## Starting and stopping processing -Once it has been configured, the `EventProcessorClient` must be explicitly started by calling its [StartProcessingAsync](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventprocessorclient.startprocessingasync?view=azure-dotnet#Azure_Messaging_EventHubs_EventProcessorClient_StartProcessingAsync_System_Threading_CancellationToken_) method to begin processing. After being started, processing is performed in the background and will continue until the processor has been explicitly stopped by calling its [StopProcessingAsync](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventprocessorclient.stopprocessingasync?view=azure-dotnet) method. While this allows the application code to perform other tasks, it also places the responsibility of ensuring that the process does not terminate during processing if there are no other tasks being performed. +Once it has been configured, the `EventProcessorClient` must be explicitly started by calling its [StartProcessingAsync](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventprocessorclient.startprocessingasync?view=azure-dotnet#Azure_Messaging_EventHubs_EventProcessorClient_StartProcessingAsync_System_Threading_CancellationToken_) method to begin processing. After being started, processing is performed in the background and will continue until the processor has been explicitly stopped by calling its [StopProcessingAsync](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventprocessorclient.stopprocessingasync?view=azure-dotnet) method. While this allows the application code to perform other tasks, it also places the responsibility of ensuring that the process does not terminate during processing if there are no other tasks being performed. + + When stopping, the processor will relinquish ownership of partitions that it was responsible for processing and clean up network resources used for communication with the Event Hubs service. As a result, this method will perform network I/O and may need to wait for partition reads that were active to complete. Due to service calls and network latency, an invocation of this method may take slightly longer than the configured [MaximumWaitTime](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventprocessorclientoptions.maximumwaittime?view=azure-dotnet#Azure_Messaging_EventHubs_EventProcessorClientOptions_MaximumWaitTime). In the case where the wait time was not configured, stopping may take slightly longer than the [TryTimeout](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventhubsretryoptions.trytimeout?view=azure-dotnet#Azure_Messaging_EventHubs_EventHubsRetryOptions_TryTimeout) of the active retry policy. By default, this is 60 seconds. - When stopping, the processor will relinquish ownership of partitions that it was responsible for processing and clean up network resources used for communication with the Event Hubs service. As a result, this method will perform network I/O and may need to wait for partition reads that were active to complete. Due to service calls and network latency, an invocation of this method may take slightly longer than the configured [MaximumWaitTime](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventprocessorclientoptions.maximumwaittime?view=azure-dotnet#Azure_Messaging_EventHubs_EventProcessorClientOptions_MaximumWaitTime). In the case where the wait time was not configured, stopping may take slightly longer than the [TryTimeout](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventhubsretryoptions.trytimeout?view=azure-dotnet#Azure_Messaging_EventHubs_EventHubsRetryOptions_TryTimeout) of the active retry policy. By default, this is 60 seconds. - For more information on configuring the `TryTimeout`, see: [Configuring the timeout used for Event Hubs service operations](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample02_EventProcessorConfiguration.md#configuring-the-timeout-used-for-event-hubs-service-operations). - + ## Interacting with the processor while running -The act of processing events read from the partition and handling any errors that occur is delegated by the `EventProcessorClient` to code that you provide using the [.NET event pattern](https://docs.microsoft.com/dotnet/csharp/event-pattern). This allows your logic to concentrate on delivering business value while the processor handles the tasks associated with reading events, managing the partitions, and allowing state to be persisted in the form of checkpoints. +The act of processing events read from the partition and handling any errors that occur is delegated by the `EventProcessorClient` to code that you provide using the [.NET event pattern](https://learn.microsoft.com/dotnet/csharp/event-pattern). This allows your logic to concentrate on delivering business value while the processor handles the tasks associated with reading events, managing the partitions, and allowing state to be persisted in the form of checkpoints. An in-depth discussion of the handlers used with the `EventProcessorClient` along with guidance for implementing them can be found in the sample: [Event Processor Handlers](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample03_EventProcessorHandlers.md). The following examples will assume familiarity with best practices for handler implementation and will often avoid going into detail in the interest of brevity. @@ -70,22 +70,30 @@ An in-depth discussion of the handlers used with the `EventProcessorClient` alon At minimum, the `EventProcessorClient` will make sure that you've registered a handler for processing events and receiving notification about exceptions the processor encounters before it will begin processing events. This example illustrates a common general pattern for processing, without taking checkpointing into consideration. ```C# Snippet:EventHubs_Processor_Sample04_BasicEventProcessing -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); Task processEventHandler(ProcessEventArgs args) { @@ -196,25 +204,33 @@ The creation of checkpoints comes at a cost, both in terms of processing perform In either case, it is important to understand that your processing must be tolerant of receiving the same event to be processed more than once; the Event Hubs service, like most messaging platforms, guarantees at-least-once delivery. Even were you to create a checkpoint for each event that you process, it is entirely possible that you would receive that same event again from the service. -This example illustrates checkpointing after 25 events have been processed for a given partition. +This example illustrates checkpointing after 25 events have been processed for a given partition. ```C# Snippet:EventHubs_Processor_Sample04_CheckpointByEventCount -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); const int EventsBeforeCheckpoint = 25; var partitionEventCount = new ConcurrentDictionary(); @@ -305,22 +321,30 @@ When a partition is initialized, one of the decisions made is where in the parti This example will demonstrate choosing to start with the event closest to being on or after the current date and time. ```C# Snippet:EventHubs_Processor_Sample04_InitializePartition -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); Task initializeEventHandler(PartitionInitializingEventArgs args) { @@ -397,34 +421,42 @@ finally ## Heartbeat while processing events -It is often helpful for an application to understand whether an `EventProcessorClient` instance is still healthy but no events were available for its partitions versus when the processor or its host may have stopped. This can be accomplished by setting a maximum wait time for events to be available to read from the Event Hubs service. +It is often helpful for an application to understand whether an `EventProcessorClient` instance is still healthy but no events were available for its partitions versus when the processor or its host may have stopped. This can be accomplished by setting a maximum wait time for events to be available to read from the Event Hubs service. -When the wait time is set, if no events are read within that interval, the processor will invoke the `ProcessEventAsync` handler and pass a set of arguments that indicates no event was available, using the [MaximumWaitTime](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventprocessorclientoptions.maximumwaittime?view=azure-dotnet) of the `EventProcessorClientOptions`. +When the wait time is set, if no events are read within that interval, the processor will invoke the `ProcessEventAsync` handler and pass a set of arguments that indicates no event was available, using the [MaximumWaitTime](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventprocessorclientoptions.maximumwaittime?view=azure-dotnet) of the `EventProcessorClientOptions`. This example demonstrates emitting a heartbeat to the host application whenever an event is processed or after a maximum of 250 milliseconds passes with no event. ```C# Snippet:EventHubs_Processor_Sample04_ProcessWithHeartbeat -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; -var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); - var processorOptions = new EventProcessorClientOptions { MaximumWaitTime = TimeSpan.FromMilliseconds(250) }; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + +var storageClient = new BlobContainerClient( + blobUriBuilder.ToUri(), + credential); + var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); async Task processEventHandler(ProcessEventArgs args) @@ -491,4 +523,4 @@ finally processor.ProcessEventAsync -= processEventHandler; processor.ProcessErrorAsync -= Application.ProcessorErrorHandler; } -``` \ No newline at end of file +``` diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample05_IdentityAndSharedAccessCredentials.md b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample05_IdentityAndSharedAccessCredentials.md index 63b2b692f5fea..2f79adf3c97ed 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample05_IdentityAndSharedAccessCredentials.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample05_IdentityAndSharedAccessCredentials.md @@ -16,7 +16,7 @@ This sample demonstrates using credentials to authorize clients with the Event H ## Prerequisites -To begin, please ensure that you're familiar with the items discussed in the [Getting started](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples#getting-started) section of the README. You will also need to the fully qualified namespace for the Event Hubs resource that you would like to use. This can be found in the Azure Portal view of the Event Hubs namespace in the "Overview" tab. In the center pane, the "essentials" area will list a "hostname." This is the fully qualified namespace and is likely be similar to: `{your-namespace}.servicebus.windows.net`. +To begin, please ensure that you're familiar with the items discussed in the [Getting started](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples#getting-started) section of the README. You will also need to the fully qualified namespace for the Event Hubs resource that you would like to use. This can be found in the Azure Portal view of the Event Hubs namespace in the "Overview" tab. In the center pane, the "essentials" area will list a "hostname." This is the fully qualified namespace and is likely be similar to: `{your-namespace}.servicebus.windows.net`. If you'd like to use an identity credential for accessing Azure Storage, you will need one of the Blob service endpoint URLs. These can be found in the Azure Portal view of the Azure Storage account in the "Properties" area under the "Settings" tab. Either the primary or secondary endpoint can be used, but you'll need to ensure that "Blob service" appears under the endpoint that you've selected for it to be valid. This endpoint is likely similar to: `{your-account-name}.blob.core.windows.net`. @@ -24,30 +24,30 @@ Depending on the type of authorization that you wish to use, additional setup ma ### Identity authorization -**Azure.Identity** +**Azure.Identity** -The `Azure.Identity` library is recommended for identity-based authentication across the different sources supported by the Azure platform for [role-based access control (RBAC)](https://docs.microsoft.com/azure/role-based-access-control/overview). This includes Azure Active Directory principals and Managed Identities. To allow for the best developer experience, and one that supports promoting applications between environments without code changes, this sample will concentrate on the `DefaultAzureCredential`. Please see the [Azure.Identity README](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/README.md#defaultazurecredential) for details on configuring your environment for `DefaultAzureCredential` integration. +The `Azure.Identity` library is recommended for identity-based authentication across the different sources supported by the Azure platform for [role-based access control (RBAC)](https://learn.microsoft.com/azure/role-based-access-control/overview). This includes Azure Active Directory principals and Managed Identities. To allow for the best developer experience, and one that supports promoting applications between environments without code changes, this sample will concentrate on the `DefaultAzureCredential`. Please see the [Azure.Identity README](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/README.md#defaultazurecredential) for details on configuring your environment for `DefaultAzureCredential` integration. -**Role Assignments** +**Role Assignments** -Once your environment is configured, you'll need to ensure that the principal that you've chosen has access to your Event Hubs resources in Azure. To do so, they will need to be assigned the appropriate role. For those unfamiliar with role assignments, it is recommended to follow [these steps](https://docs.microsoft.com/azure/event-hubs/authenticate-managed-identity?tabs=latest#to-assign-azure-roles-using-the-azure-portal) in the Azure portal for the most intuitive experience. Roles may also be assigned via the [Azure CLI](https://docs.microsoft.com/cli/azure/role/assignment?view=azure-cli-latest#az_role_assignment_create) or [PowerShell](https://docs.microsoft.com/powershell/module/az.resources/new-azroleassignment), though these require more in-depth knowledge of the Azure platform and may be difficult for developers exploring Azure for the first time. +Once your environment is configured, you'll need to ensure that the principal that you've chosen has access to your Event Hubs resources in Azure. To do so, they will need to be assigned the appropriate role. For those unfamiliar with role assignments, it is recommended to follow [these steps](https://learn.microsoft.com/azure/event-hubs/authenticate-managed-identity?tabs=latest#to-assign-azure-roles-using-the-azure-portal) in the Azure portal for the most intuitive experience. Roles may also be assigned via the [Azure CLI](https://learn.microsoft.com/cli/azure/role/assignment?view=azure-cli-latest#az_role_assignment_create) or [PowerShell](https://learn.microsoft.com/powershell/module/az.resources/new-azroleassignment), though these require more in-depth knowledge of the Azure platform and may be difficult for developers exploring Azure for the first time. -The available role choices for Event Hubs are: +The available role choices for Event Hubs are: -- [Azure Event Hubs Data Owner](https://docs.microsoft.com/azure/role-based-access-control/built-in-roles#azure-event-hubs-data-owner) for full access to read and publish events. -- [Azure Event Hubs Data Receiver](https://docs.microsoft.com/azure/role-based-access-control/built-in-roles#azure-event-hubs-data-receiver) for the ability to read events but not publish them. +- [Azure Event Hubs Data Owner](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles#azure-event-hubs-data-owner) for full access to read and publish events. +- [Azure Event Hubs Data Receiver](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles#azure-event-hubs-data-receiver) for the ability to read events but not publish them. -You will also need to ensure that your principal is assigned the [Storage Blob Data Contributor](https://docs.microsoft.com/azure/role-based-access-control/built-in-roles#storage-blob-data-contributor) role for the Blob Storage container that you're using for checkpoint and ownership data. +You will also need to ensure that your principal is assigned the [Storage Blob Data Contributor](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles#storage-blob-data-contributor) role for the Blob Storage container that you're using for checkpoint and ownership data. ### Event Hubs Shared Access Signature authorization Shared access signatures (SAS) are recommended over shared access keys, when RBAC cannot be used. A shared access signature allows for granular and time-limited access to Event Hubs resources. In order to use SAS-based authorization, a token needs to be generated and the associated Event Hubs resource needs to be configured to authorize its use. -The steps to to generate a SAS token can be found in the article "[Authenticate access to Event Hubs resources using shared access signatures (SAS)](https://docs.microsoft.com/azure/event-hubs/authenticate-shared-access-signature)", with details for some additional languages detailed in the article "[Generate SAS token](https://docs.microsoft.com/rest/api/eventhub/generate-sas-token)". Information about configuring SAS authorization can be found in the article "[Authorizing access to Event Hubs resources using Shared Access Signatures](https://docs.microsoft.com/azure/event-hubs/authorize-access-shared-access-signature)". +The steps to to generate a SAS token can be found in the article "[Authenticate access to Event Hubs resources using shared access signatures (SAS)](https://learn.microsoft.com/azure/event-hubs/authenticate-shared-access-signature)", with details for some additional languages detailed in the article "[Generate SAS token](https://learn.microsoft.com/rest/api/eventhub/generate-sas-token)". Information about configuring SAS authorization can be found in the article "[Authorizing access to Event Hubs resources using Shared Access Signatures](https://learn.microsoft.com/azure/event-hubs/authorize-access-shared-access-signature)". ### Event Hubs Shared Access Key authorization -Shared access keys for Event Hubs authorization are generated when access policies are created for an Event Hubs namespace or one of its Event Hub instances. Since these keys are most often used in association with a connection string, the article "[Get an Event Hubs connection string](https://docs.microsoft.com/azure/event-hubs/event-hubs-get-connection-string#get-connection-string-from-the-portal)" is the best source of information on generating and accessing them. +Shared access keys for Event Hubs authorization are generated when access policies are created for an Event Hubs namespace or one of its Event Hub instances. Since these keys are most often used in association with a connection string, the article "[Get an Event Hubs connection string](https://learn.microsoft.com/azure/event-hubs/event-hubs-get-connection-string#get-connection-string-from-the-portal)" is the best source of information on generating and accessing them. In step 6 of the article, the policy that you select will be the name of your shared access key when used for credential authorization. In step 7, you'll want to copy the "Primary key" rather than connection string. @@ -55,22 +55,24 @@ In step 6 of the article, the policy that you select will be the name of your sh The `EventProcessorClient` is intended to provide a robust and resilient client for processing events from an Event Hub and is capable of automatically managing the recovery process for transient failures. It will also collaborate with other `EventProcessorClient` instances to dynamically distribute and share processing responsibility as processors are added and removed from the group. -The `EventProcessorClient` is safe to cache and use for the lifetime of the application, which is best practice when the application processes events regularly or semi-regularly. The processor is responsible for efficient resource management, working to keep resource usage low during periods of inactivity and manage health during periods of higher use. Calling the `StopProcessingAsync` method when your application is closing will ensure that network resources and other unmanaged objects are cleaned up. +The `EventProcessorClient` is safe to cache and use for the lifetime of the application, which is best practice when the application processes events regularly or semi-regularly. The processor is responsible for efficient resource management, working to keep resource usage low during periods of inactivity and manage health during periods of higher use. Calling the `StopProcessingAsync` method when your application is closing will ensure that network resources and other unmanaged objects are cleaned up. ## Processing events with identity-based authorization ```C# Snippet:EventHubs_Processor_Sample05_DefaultAzureCredential var credential = new DefaultAzureCredential(); -var storageEndpoint = "<< STORAGE ENDPOINT (likely similar to {your-account}.blob.core.windows.net) >>"; +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; 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 >>"; -var blobUriBuilder = new BlobUriBuilder(new Uri(storageEndpoint)); -blobUriBuilder.BlobContainerName = blobContainerName; +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; var storageClient = new BlobContainerClient( blobUriBuilder.ToUri(), @@ -347,4 +349,4 @@ finally processor.ProcessEventAsync -= Application.ProcessorEventHandler; processor.ProcessErrorAsync -= Application.ProcessorErrorHandler; } -``` \ No newline at end of file +``` diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample06_RequestingStorageServiceVersions.md b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample06_RequestingStorageServiceVersions.md index b1cd782660c4d..065e1f67e8ea6 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample06_RequestingStorageServiceVersions.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample06_RequestingStorageServiceVersions.md @@ -1,6 +1,6 @@ # Requesting Azure Storage Service Versions -This sample demonstrates configuring the Blob Storage client to use a specific version of the service, rather than the default. This is useful when the Azure environment that you are targeting supports a different version of Blob Storage service than is available in the Azure public cloud. For example, if you are running Event Hubs on an Azure Stack Hub version 2002, the highest available version for the Storage service is version 2017-11-09. In this case, you will need to use the following code to change the Blob Storage service API version to 2017-11-09. For more information on the Azure Storage service versions supported on Azure Stack Hub, please refer to the [Azure Stack documentation](https://docs.microsoft.com/azure-stack/user/azure-stack-acs-differences). +This sample demonstrates configuring the Blob Storage client to use a specific version of the service, rather than the default. This is useful when the Azure environment that you are targeting supports a different version of Blob Storage service than is available in the Azure public cloud. For example, if you are running Event Hubs on an Azure Stack Hub version 2002, the highest available version for the Storage service is version 2017-11-09. In this case, you will need to use the following code to change the Blob Storage service API version to 2017-11-09. For more information on the Azure Storage service versions supported on Azure Stack Hub, please refer to the [Azure Stack documentation](https://learn.microsoft.com/azure-stack/user/azure-stack-acs-differences). To begin, please ensure that you're familiar with the items discussed in the [Event Processor Handlers](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample03_EventProcessorHandlers.md) sample. You'll also need to have the prerequisites and connection string information available, as discussed in the [Getting started](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples#getting-started) section of the README. @@ -10,7 +10,7 @@ To begin, please ensure that you're familiar with the items discussed in the [Ev ## Configuring the Blob Storage client - This sample demonstrates using an [Azure.Core](https://docs.microsoft.com/dotnet/api/overview/azure/core-readme) pipeline policy to request the Blob Storage client request use of a specific service version. + This sample demonstrates using an [Azure.Core](https://learn.microsoft.com/dotnet/api/overview/azure/core-readme) pipeline policy to request the Blob Storage client request use of a specific service version. ```C# Snippet:EventHubs_Processor_Sample06_StorageVersionPolicy /// @@ -50,10 +50,12 @@ private class StorageApiVersionPolicy : HttpPipelineSynchronousPolicy ``` ```C# Snippet:EventHubs_Processor_Sample06_ChooseStorageVersion -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; @@ -63,16 +65,22 @@ storageClientOptions.AddPolicy( new StorageApiVersionPolicy(), HttpPipelinePosition.PerCall); +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName, + blobUriBuilder.ToUri(), + credential, storageClientOptions); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -125,4 +133,4 @@ finally processor.ProcessEventAsync -= Application.ProcessorEventHandler; processor.ProcessErrorAsync -= Application.ProcessorErrorHandler; } -``` \ No newline at end of file +``` diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample07_BatchProcessing.md b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample07_BatchProcessing.md index febb3126fa087..a94329be52822 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample07_BatchProcessing.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples/Sample07_BatchProcessing.md @@ -24,15 +24,17 @@ public class SimpleBatchProcessor : PluggableCheckpointStoreEventProcessor(); var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var options = new EventProcessorOptions { LoadBalancingUpdateInterval = TimeSpan.FromMilliseconds(250), LoadBalancingStrategy = loadBalancingStrategy }; - var processor = CreateProcessor(scope.ConsumerGroups.First(), connectionString, options: options); + var processor = CreateProcessorWithIdentity(scope.ConsumerGroups.First(), scope.EventHubName, options: options); processor.ProcessErrorAsync += CreateAssertingErrorHandler(); processor.ProcessEventAsync += CreateEventTrackingHandler(sentCount, processedEvents, completionSource, cancellationSource.Token); @@ -92,7 +91,7 @@ public async Task EventsCanBeReadByOneProcessorClient(LoadBalancingStrategy load /// /// [Test] - public async Task EventsCanBeReadByOneProcessorClientUsingAnIdentityCredential() + public async Task EventsCanBeReadByOneProcessorClientUsingTheConnectionString() { // Setup the environment. @@ -105,7 +104,7 @@ public async Task EventsCanBeReadByOneProcessorClientUsingAnIdentityCredential() // Send a set of events. var sourceEvents = EventGenerator.CreateEvents(50).ToList(); - var sentCount = await SendEvents(connectionString, sourceEvents, cancellationSource.Token); + var sentCount = await SendEvents(scope.EventHubName, sourceEvents, cancellationSource.Token); Assert.That(sentCount, Is.EqualTo(sourceEvents.Count), "Not all of the source events were sent."); @@ -114,7 +113,7 @@ public async Task EventsCanBeReadByOneProcessorClientUsingAnIdentityCredential() var processedEvents = new ConcurrentDictionary(); var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var options = new EventProcessorOptions { LoadBalancingUpdateInterval = TimeSpan.FromMilliseconds(250) }; - var processor = CreateProcessorWithIdentity(scope.ConsumerGroups.First(), scope.EventHubName, options: options); + var processor = CreateProcessor(scope.ConsumerGroups.First(), connectionString, options: options); processor.ProcessErrorAsync += CreateAssertingErrorHandler(); processor.ProcessEventAsync += CreateEventTrackingHandler(sentCount, processedEvents, completionSource, cancellationSource.Token); @@ -147,7 +146,6 @@ public async Task EventsCanBeReadByOneProcessorClientUsingTheSharedKeyCredential // Setup the environment. await using EventHubScope scope = await EventHubScope.CreateAsync(2); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); @@ -155,7 +153,7 @@ public async Task EventsCanBeReadByOneProcessorClientUsingTheSharedKeyCredential // Send a set of events. var sourceEvents = EventGenerator.CreateEvents(50).ToList(); - var sentCount = await SendEvents(connectionString, sourceEvents, cancellationSource.Token); + var sentCount = await SendEvents(scope.EventHubName, sourceEvents, cancellationSource.Token); Assert.That(sentCount, Is.EqualTo(sourceEvents.Count), "Not all of the source events were sent."); @@ -197,7 +195,6 @@ public async Task EventsCanBeReadByOneProcessorClientUsingTheSasCredential() // Setup the environment. await using EventHubScope scope = await EventHubScope.CreateAsync(2); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); @@ -205,7 +202,7 @@ public async Task EventsCanBeReadByOneProcessorClientUsingTheSasCredential() // Send a set of events. var sourceEvents = EventGenerator.CreateEvents(50).ToList(); - var sentCount = await SendEvents(connectionString, sourceEvents, cancellationSource.Token); + var sentCount = await SendEvents(scope.EventHubName, sourceEvents, cancellationSource.Token); Assert.That(sentCount, Is.EqualTo(sourceEvents.Count), "Not all of the source events were sent."); @@ -247,7 +244,6 @@ public async Task EventsCanBeReadByMultipleProcessorClients() // Setup the environment. await using EventHubScope scope = await EventHubScope.CreateAsync(4); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); @@ -255,7 +251,7 @@ public async Task EventsCanBeReadByMultipleProcessorClients() // Send a set of events. var sourceEvents = EventGenerator.CreateEvents(500).ToList(); - var sentCount = await SendEvents(connectionString, sourceEvents, cancellationSource.Token); + var sentCount = await SendEvents(scope.EventHubName, sourceEvents, cancellationSource.Token); Assert.That(sentCount, Is.EqualTo(sourceEvents.Count), "Not all of the source events were sent."); @@ -271,8 +267,8 @@ public async Task EventsCanBeReadByMultipleProcessorClients() var processors = new[] { - CreateProcessor(scope.ConsumerGroups.First(), connectionString, options: options), - CreateProcessor(scope.ConsumerGroups.First(), connectionString, options: options) + CreateProcessorWithIdentity(scope.ConsumerGroups.First(), scope.EventHubName, options: options), + CreateProcessorWithIdentity(scope.ConsumerGroups.First(), scope.EventHubName, options: options) }; foreach (var processor in processors) @@ -314,14 +310,16 @@ public async Task ProcessorClientCreatesOwnership() var partitionIds = new HashSet(); await using EventHubScope scope = await EventHubScope.CreateAsync(partitionCount); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); // Discover the partitions. - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { foreach (var partitionId in (await producer.GetPartitionIdsAsync())) { @@ -332,7 +330,7 @@ public async Task ProcessorClientCreatesOwnership() // Send a set of events. var sourceEvents = EventGenerator.CreateEvents(200).ToList(); - var sentCount = await SendEvents(connectionString, sourceEvents, cancellationSource.Token); + var sentCount = await SendEvents(scope.EventHubName, sourceEvents, cancellationSource.Token); Assert.That(sentCount, Is.EqualTo(sourceEvents.Count), "Not all of the source events were sent."); @@ -379,7 +377,6 @@ public async Task ProcessorClientCanStartFromAnInitialPosition() // Setup the environment. await using EventHubScope scope = await EventHubScope.CreateAsync(1); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); @@ -388,7 +385,7 @@ public async Task ProcessorClientCanStartFromAnInitialPosition() var sourceEvents = EventGenerator.CreateEvents(25).ToList(); var lastSourceEvent = sourceEvents.Last(); - var sentCount = await SendEvents(connectionString, sourceEvents, cancellationSource.Token); + var sentCount = await SendEvents(scope.EventHubName, sourceEvents, cancellationSource.Token); Assert.That(sentCount, Is.EqualTo(sourceEvents.Count), "Not all of the source events were sent."); @@ -396,7 +393,11 @@ public async Task ProcessorClientCanStartFromAnInitialPosition() var startingOffset = 0L; - await using (var consumer = new EventHubConsumerClient(scope.ConsumerGroups.First(), connectionString)) + await using (var consumer = new EventHubConsumerClient( + scope.ConsumerGroups.First(), + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { await foreach (var partitionEvent in consumer.ReadEventsAsync(new ReadEventOptions { MaximumWaitTime = null }, cancellationSource.Token)) { @@ -412,7 +413,7 @@ public async Task ProcessorClientCanStartFromAnInitialPosition() // Send the second set of events to be read by the processor. sourceEvents = EventGenerator.CreateEvents(20).ToList(); - sentCount = await SendEvents(connectionString, sourceEvents, cancellationSource.Token); + sentCount = await SendEvents(scope.EventHubName, sourceEvents, cancellationSource.Token); Assert.That(sentCount, Is.EqualTo(sourceEvents.Count), "Not all of the source events were sent."); @@ -421,7 +422,7 @@ public async Task ProcessorClientCanStartFromAnInitialPosition() var processedEvents = new ConcurrentDictionary(); var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var options = new EventProcessorOptions { LoadBalancingUpdateInterval = TimeSpan.FromMilliseconds(250) }; - var processor = CreateProcessor(scope.ConsumerGroups.First(), connectionString, options: options); + var processor = CreateProcessorWithIdentity(scope.ConsumerGroups.First(), scope.EventHubName, options: options); processor.PartitionInitializingAsync += args => { @@ -460,7 +461,6 @@ public async Task ProcessorClientBeginsWithTheNextEventAfterCheckpointing() // Setup the environment. await using EventHubScope scope = await EventHubScope.CreateAsync(1); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); @@ -473,7 +473,7 @@ public async Task ProcessorClientBeginsWithTheNextEventAfterCheckpointing() var afterCheckpointEvents = EventGenerator.CreateEvents(segmentEventCount).ToList(); var sourceEvents = Enumerable.Concat(beforeCheckpointEvents, afterCheckpointEvents).ToList(); var checkpointEvent = beforeCheckpointEvents.Last(); - var sentCount = await SendEvents(connectionString, sourceEvents, cancellationSource.Token); + var sentCount = await SendEvents(scope.EventHubName, sourceEvents, cancellationSource.Token); Assert.That(sentCount, Is.EqualTo(sourceEvents.Count), "Not all of the source events were sent."); @@ -493,7 +493,7 @@ public async Task ProcessorClientBeginsWithTheNextEventAfterCheckpointing() var beforeCheckpointProcessHandler = CreateEventTrackingHandler(segmentEventCount, processedEvents, completionSource, cancellationSource.Token, processedEventCallback); var options = new EventProcessorOptions { LoadBalancingUpdateInterval = TimeSpan.FromMilliseconds(250) }; var checkpointStore = new InMemoryCheckpointStore(_ => { }); - var processor = CreateProcessor(scope.ConsumerGroups.First(), connectionString, checkpointStore, options); + var processor = CreateProcessorWithIdentity(scope.ConsumerGroups.First(), scope.EventHubName, checkpointStore, options); processor.ProcessErrorAsync += CreateAssertingErrorHandler(); processor.ProcessEventAsync += beforeCheckpointProcessHandler; @@ -590,7 +590,13 @@ public async Task ProcessorClientDetectsAnInvalidEventHubName(bool async) // Create the processor and attempt to start. - var processor = new EventProcessorClient(Mock.Of(), EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, "fake"); + var processor = new EventProcessorClient( + Mock.Of(), + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + "fake", + EventHubsTestEnvironment.Instance.Credential); + processor.ProcessErrorAsync += _ => Task.CompletedTask; processor.ProcessEventAsync += _ => Task.CompletedTask; @@ -627,8 +633,23 @@ public async Task ProcessorClientDetectsAnInvalidConsumerGroup(bool async) // Create the processor and attempt to start. - var containerClient = new BlobContainerClient(StorageTestEnvironment.Instance.StorageConnectionString, storageScope.ContainerName); - var processor = new EventProcessorClient(containerClient, "fake", EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + var blobUri = new Uri($"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"); + + var blobUriBuilder = new BlobUriBuilder(blobUri) + { + BlobContainerName = storageScope.ContainerName + }; + + var storageClient = new BlobContainerClient( + blobUriBuilder.ToUri(), + EventHubsTestEnvironment.Instance.Credential); + + var processor = new EventProcessorClient( + storageClient, + "fake", + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential); processor.ProcessErrorAsync += _ => Task.CompletedTask; processor.ProcessEventAsync += _ => Task.CompletedTask; @@ -647,13 +668,14 @@ public async Task ProcessorClientDetectsAnInvalidConsumerGroup(bool async) } /// - /// Verifies that the can read a set of published events. + /// Verifies that the detects an invalid connection + /// to Storage. /// /// [Test] [TestCase(true)] [TestCase(false)] - public async Task ProcessorClientDetectsAnInvalidStorageConnectionString(bool async) + public async Task ProcessorClientDetectsAnInvalidStorageConnection(bool async) { // Setup the environment. @@ -665,9 +687,24 @@ public async Task ProcessorClientDetectsAnInvalidStorageConnectionString(bool as // Create the processor and attempt to start. - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString.Replace(StorageTestEnvironment.Instance.StorageEndpointSuffix, "fake.com"); - var containerClient = new BlobContainerClient(storageConnectionString, storageScope.ContainerName); - var processor = new EventProcessorClient(containerClient, eventHubScope.ConsumerGroups[0], EventHubsTestEnvironment.Instance.EventHubsConnectionString, eventHubScope.EventHubName); + var blobUri = new Uri($"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"); + + var blobUriBuilder = new BlobUriBuilder(blobUri) + { + BlobContainerName = storageScope.ContainerName + }; + + var containerClient = new BlobContainerClient( + blobUriBuilder.ToUri(), + EventHubsTestEnvironment.Instance.Credential); + + var processor = new EventProcessorClient( + containerClient, + eventHubScope.ConsumerGroups[0], + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + eventHubScope.EventHubName, + EventHubsTestEnvironment.Instance.Credential); + processor.ProcessErrorAsync += _ => Task.CompletedTask; processor.ProcessEventAsync += _ => Task.CompletedTask; @@ -702,8 +739,24 @@ public async Task ProcessorClientDetectsAnInvalidStorageContainer(bool async) // Create the processor and attempt to start. - var containerClient = new BlobContainerClient(StorageTestEnvironment.Instance.StorageConnectionString, "fake"); - var processor = new EventProcessorClient(containerClient, eventHubScope.ConsumerGroups[0], EventHubsTestEnvironment.Instance.EventHubsConnectionString, eventHubScope.EventHubName); + var blobUri = new Uri($"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"); + + var blobUriBuilder = new BlobUriBuilder(blobUri) + { + BlobContainerName = "fake" + }; + + var containerClient = new BlobContainerClient( + blobUriBuilder.ToUri(), + EventHubsTestEnvironment.Instance.Credential); + + var processor = new EventProcessorClient( + containerClient, + eventHubScope.ConsumerGroups[0], + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + eventHubScope.EventHubName, + EventHubsTestEnvironment.Instance.Credential); + processor.ProcessErrorAsync += _ => Task.CompletedTask; processor.ProcessEventAsync += _ => Task.CompletedTask; @@ -733,14 +786,13 @@ public async Task ProcessorClientStopsWithoutWaitingForTimeoutWhenPartitionsAreE // Setup the environment. await using EventHubScope scope = await EventHubScope.CreateAsync(4); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); // Send a single event. - var sentCount = await SendEvents(connectionString, EventGenerator.CreateEvents(1), cancellationSource.Token); + var sentCount = await SendEvents(scope.EventHubName, EventGenerator.CreateEvents(1), cancellationSource.Token); Assert.That(sentCount, Is.EqualTo(1), "A single event should have been sent."); // Attempt to read events using the longest possible TryTimeout. @@ -750,7 +802,7 @@ public async Task ProcessorClientStopsWithoutWaitingForTimeoutWhenPartitionsAreE var processedEvents = new ConcurrentDictionary(); var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - var processor = CreateProcessor(scope.ConsumerGroups.First(), connectionString, options: options); + var processor = CreateProcessorWithIdentity(scope.ConsumerGroups.First(), scope.EventHubName, options: options); processor.ProcessErrorAsync += CreateAssertingErrorHandler(); processor.ProcessEventAsync += CreateEventTrackingHandler(sentCount, processedEvents, completionSource, cancellationSource.Token); @@ -792,14 +844,13 @@ public async Task ProcessorClientCanRestartAfterStopping() // Setup the environment. await using EventHubScope scope = await EventHubScope.CreateAsync(4); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); // Send a single event. - var sentCount = await SendEvents(connectionString, EventGenerator.CreateEvents(1), cancellationSource.Token); + var sentCount = await SendEvents(scope.EventHubName, EventGenerator.CreateEvents(1), cancellationSource.Token); Assert.That(sentCount, Is.EqualTo(1), "A single event should have been sent."); // Attempt to read events using the longest possible TryTimeout. @@ -809,7 +860,7 @@ public async Task ProcessorClientCanRestartAfterStopping() var processedEvents = new ConcurrentDictionary(); var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - var processor = CreateProcessor(scope.ConsumerGroups.First(), connectionString, options: options); + var processor = CreateProcessorWithIdentity(scope.ConsumerGroups.First(), scope.EventHubName, options: options); var activeEventHandler = CreateEventTrackingHandler(sentCount, processedEvents, completionSource, cancellationSource.Token); processor.ProcessEventAsync += activeEventHandler; @@ -833,7 +884,7 @@ public async Task ProcessorClientCanRestartAfterStopping() // Send another single event to prove restart was successful. - sentCount = await SendEvents(connectionString, EventGenerator.CreateEvents(1), cancellationSource.Token); + sentCount = await SendEvents(scope.EventHubName, EventGenerator.CreateEvents(1), cancellationSource.Token); Assert.That(sentCount, Is.EqualTo(1), "A single event should have been sent."); // Reset the event handler so that it uses a completion source that hasn't been signaled.. @@ -870,14 +921,13 @@ public async Task ProcessorClientCeasesProcessingWhenStopping() // Setup the environment. await using EventHubScope scope = await EventHubScope.CreateAsync(4); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); // Publish some events - var sentCount = await SendEvents(connectionString, EventGenerator.CreateSmallEvents(400), cancellationSource.Token); + var sentCount = await SendEvents(scope.EventHubName, EventGenerator.CreateSmallEvents(400), cancellationSource.Token); Assert.That(sentCount, Is.EqualTo(400), "All generated events should have been published."); // Attempt to read events using the longest possible TryTimeout. @@ -889,7 +939,7 @@ public async Task ProcessorClientCeasesProcessingWhenStopping() var eventsProcessedAfterStop = false; var readCount = 0; var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - var processor = CreateProcessor(scope.ConsumerGroups.First(), connectionString, options: options); + var processor = CreateProcessorWithIdentity(scope.ConsumerGroups.First(), scope.EventHubName, options: options); processor.ProcessEventAsync += args => { @@ -937,7 +987,6 @@ public async Task ProcessorClientCanCheckpointAfterStopping() // Setup the environment. await using EventHubScope scope = await EventHubScope.CreateAsync(1); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); @@ -951,7 +1000,7 @@ public async Task ProcessorClientCanCheckpointAfterStopping() var sourceEvents = Enumerable.Concat(beforeCheckpointEvents, afterCheckpointEvents).ToList(); var checkpointEvent = beforeCheckpointEvents.Last(); var checkpointArgs = default(ProcessEventArgs); - var sentCount = await SendEvents(connectionString, sourceEvents, cancellationSource.Token); + var sentCount = await SendEvents(scope.EventHubName, sourceEvents, cancellationSource.Token); Assert.That(sentCount, Is.EqualTo(sourceEvents.Count), "Not all of the source events were sent."); @@ -973,7 +1022,7 @@ public async Task ProcessorClientCanCheckpointAfterStopping() var beforeCheckpointProcessHandler = CreateEventTrackingHandler(segmentEventCount, processedEvents, completionSource, cancellationSource.Token, processedEventCallback); var options = new EventProcessorOptions { LoadBalancingUpdateInterval = TimeSpan.FromMilliseconds(250) }; var checkpointStore = new InMemoryCheckpointStore(_ => { }); - var processor = CreateProcessor(scope.ConsumerGroups.First(), connectionString, checkpointStore, options); + var processor = CreateProcessorWithIdentity(scope.ConsumerGroups.First(), scope.EventHubName, checkpointStore, options); processor.ProcessErrorAsync += CreateAssertingErrorHandler(); processor.ProcessEventAsync += beforeCheckpointProcessHandler; @@ -1112,19 +1161,22 @@ private EventProcessorClient CreateProcessorWithSharedAccessSignature(string con /// Sends a set of events using a new producer to do so. /// /// - /// The connection string to use when creating the producer. + /// The name of the Event Hub to use when creating the producer. /// The set of events to send. /// The token used to signal a cancellation request. /// /// The count of events that were sent. /// - private async Task SendEvents(string connectionString, + private async Task SendEvents(string eventHubName, IEnumerable sourceEvents, CancellationToken cancellationToken) { var sentCount = 0; - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + eventHubName, + EventHubsTestEnvironment.Instance.Credential)) { foreach (var batch in (await EventGenerator.BuildBatchesAsync(sourceEvents, producer, default, cancellationToken))) { diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/MigrationGuideSnippetsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/MigrationGuideSnippetsLiveTests.cs index f62558c7a0b38..779f3550176c9 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/MigrationGuideSnippetsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/MigrationGuideSnippetsLiveTests.cs @@ -9,6 +9,8 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Azure.Core; +using Azure.Identity; using Azure.Messaging.EventHubs.Consumer; using Azure.Storage.Blobs; using Azure.Storage.Blobs.Models; @@ -38,19 +40,23 @@ public async Task MigrateCheckpoints() #region Snippet:EventHubs_Migrate_Checkpoints #if SNIPPET + var credential = new DefaultAzureCredential(); + 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 >>"; - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; var legacyBlobContainerName = "<< NAME OF THE BLOB CONTAINER THAT CONTAINS THE LEGACY DATA>>"; #else + var credential = EventHubsTestEnvironment.Instance.Credential; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = "fake-hub"; var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = storageScope.ContainerName; #endif @@ -63,9 +69,10 @@ public async Task MigrateCheckpoints() #if SNIPPET var legacyCheckpoints = await ReadLegacyCheckpoints( - storageConnectionString, + storageAccountEndpoint, legacyBlobContainerName, consumerGroup, + credential, cancellationSource.Token); #else var legacyCheckpoints = ReadFakeLegacyCheckpoints("fake"); @@ -90,7 +97,15 @@ public async Task MigrateCheckpoints() // assumes that the connection string grants the appropriate permissions to create a // container in the storage account. - var storageClient = new BlobContainerClient(storageConnectionString, blobContainerName); + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + + var storageClient = new BlobContainerClient( + blobUriBuilder.ToUri(), + credential); + await storageClient.CreateIfNotExistsAsync(cancellationToken: cancellationSource.Token); // Translate each of the legacy checkpoints, storing the offset and @@ -160,12 +175,20 @@ private IEnumerable ReadFakeLegacyCheckpoints(string fakeCo #region Snippet:EventHubs_Migrate_LegacyCheckpoints private async Task> ReadLegacyCheckpoints( - string connectionString, + string storageAccountEndpoint, string container, string consumerGroup, + TokenCredential credential, CancellationToken cancellationToken) { - var storageClient = new BlobContainerClient(connectionString, container); + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = container + }; + + var storageClient = new BlobContainerClient( + blobUriBuilder.ToUri(), + credential); // If there is no container, no action can be taken. diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/ReadMeSnippetsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/ReadMeSnippetsLiveTests.cs index 79b33991df588..5bae5cc75586a 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/ReadMeSnippetsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/ReadMeSnippetsLiveTests.cs @@ -67,18 +67,23 @@ public void ConfigureHandlers() #region Snippet:EventHubs_Processor_ReadMe_ConfigureHandlers #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = "not-real"; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake-hub"; + var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif async Task processEventHandler(ProcessEventArgs eventArgs) @@ -111,8 +116,23 @@ async Task processErrorHandler(ProcessErrorEventArgs eventArgs) } } - var storageClient = new BlobContainerClient(storageConnectionString, blobContainerName); - var processor = new EventProcessorClient(storageClient, consumerGroup, eventHubsConnectionString, eventHubName); + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + + var storageClient = new BlobContainerClient( + blobUriBuilder.ToUri(), + credential); + + var processor = new EventProcessorClient + ( + storageClient, + consumerGroup, + fullyQualifiedNamespace, + eventHubName, + credential + ); processor.ProcessEventAsync += processEventHandler; processor.ProcessErrorAsync += processErrorHandler; @@ -139,25 +159,45 @@ public async Task ProcessUntilCanceled() cancellationSource.CancelAfter(TimeSpan.FromSeconds(45)); #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = storageScope.ContainerName; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = eventHubScope.EventHubName; - var consumerGroup = eventHubScope.ConsumerGroups.First(); + var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = storageScope.ContainerName; #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); + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + + var storageClient = new BlobContainerClient( + blobUriBuilder.ToUri(), + credential); + + var processor = new EventProcessorClient + ( + storageClient, + consumerGroup, + fullyQualifiedNamespace, + eventHubName, + credential + ); processor.ProcessEventAsync += processEventHandler; processor.ProcessErrorAsync += processErrorHandler; @@ -202,20 +242,32 @@ public void CreateWithIdentity() #if SNIPPET var credential = new DefaultAzureCredential(); - var blobStorageUrl ="<< FULLY-QUALIFIED CONTAINER URL (like https://myaccount.blob.core.windows.net/mycontainer) >>"; - var fullyQualifiedNamespace = "<< FULLY-QUALIFIED EVENT HUBS NAMESPACE (like something.servicebus.windows.net) >>"; + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; + var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; + + 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 >>"; #else var credential = EventHubsTestEnvironment.Instance.Credential; - var blobStorageUrl = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix }/{ "fake-container" }"; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var eventHubName = "fake-hub"; + var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif - var storageClient = new BlobContainerClient(new Uri(blobStorageUrl), credential); + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + + var storageClient = new BlobContainerClient( + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient ( diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample02_EventProcessorConfigurationLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample02_EventProcessorConfigurationLiveTests.cs index 5d3d0d6f03cc4..ea6239c1c6055 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample02_EventProcessorConfigurationLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample02_EventProcessorConfigurationLiveTests.cs @@ -5,6 +5,7 @@ using System.Net; using System.Net.Security; using System.Security.Cryptography.X509Certificates; +using Azure.Identity; using Azure.Messaging.EventHubs.Processor; using Azure.Storage.Blobs; using NUnit.Framework; @@ -31,18 +32,23 @@ public void ConfigureLoadBalancingStrategy() #region Snippet:EventHubs_Processor_Sample02_LoadBalancingStrategy #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = "not-real"; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif var processorOptions = new EventProcessorClientOptions @@ -50,15 +56,21 @@ public void ConfigureLoadBalancingStrategy() LoadBalancingStrategy = LoadBalancingStrategy.Greedy }; + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); #endregion @@ -74,18 +86,23 @@ public void ConfigureLoadBalancingIntervals() #region Snippet:EventHubs_Processor_Sample02_LoadBalancingIntervals #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = "not-real"; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif var processorOptions = new EventProcessorClientOptions @@ -94,15 +111,21 @@ public void ConfigureLoadBalancingIntervals() PartitionOwnershipExpirationInterval = TimeSpan.FromSeconds(30) }; + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); #endregion @@ -118,18 +141,23 @@ public void ConfigureTransportWithFullOptions() #region Snippet:EventHubs_Processor_Sample02_TransportFullConnectionOptions #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = "not-real"; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif var processorOptions = new EventProcessorClientOptions @@ -140,15 +168,21 @@ public void ConfigureTransportWithFullOptions() } }; + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); #endregion @@ -164,32 +198,43 @@ public void ConfigureTransportByProperty() #region Snippet:EventHubs_Processor_Sample02_TransportProperty #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = "not-real"; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif var processorOptions = new EventProcessorClientOptions(); processorOptions.ConnectionOptions.TransportType = EventHubsTransportType.AmqpWebSockets; + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); #endregion @@ -205,18 +250,23 @@ public void ConfigureProxyWithFullOptions() #region Snippet:EventHubs_Processor_Sample02_ProxyFullConnectionOptions #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = "not-real"; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif var processorOptions = new EventProcessorClientOptions @@ -228,15 +278,21 @@ public void ConfigureProxyWithFullOptions() } }; + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); #endregion @@ -252,33 +308,44 @@ public void ConfigureProxyByProperty() #region Snippet:EventHubs_Processor_Sample02_ProxyProperty #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = "not-real"; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif var processorOptions = new EventProcessorClientOptions(); processorOptions.ConnectionOptions.TransportType = EventHubsTransportType.AmqpWebSockets; processorOptions.ConnectionOptions.Proxy = new WebProxy("https://proxyserver:80", true); + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); #endregion @@ -294,32 +361,43 @@ public void ConfigureCustomEndpointAddress() #region Snippet:EventHubs_Processor_Sample02_ConnectionOptionsCustomEndpoint #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = "not-real"; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif var processorOptions = new EventProcessorClientOptions(); processorOptions.ConnectionOptions.CustomEndpointAddress = new Uri("amqps://app-gateway.mycompany.com"); + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); #endregion @@ -335,18 +413,23 @@ public void ConfigureRemoteCertificateValidationCallback() #region Snippet:EventHubs_Processor_Sample02_RemoteCertificateValidationCallback #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = "not-real"; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif static bool ValidateServerCertificate( @@ -369,15 +452,21 @@ static bool ValidateServerCertificate( var processorOptions = new EventProcessorClientOptions(); processorOptions.ConnectionOptions.CertificateValidationCallback = ValidateServerCertificate; + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); #endregion @@ -393,18 +482,23 @@ public void ConfigureRetryWithFullOptions() #region Snippet:EventHubs_Processor_Sample02_RetryWithFullOptions #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = "not-real"; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif var processorOptions = new EventProcessorClientOptions @@ -418,15 +512,21 @@ public void ConfigureRetryWithFullOptions() } }; + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); #endregion @@ -442,33 +542,44 @@ public void ConfigureRetryByProperty() #region Snippet:EventHubs_Processor_Sample02_RetryByProperty #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = "not-real"; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif var processorOptions = new EventProcessorClientOptions(); processorOptions.RetryOptions.Mode = EventHubsRetryMode.Fixed; processorOptions.RetryOptions.MaximumRetries = 5; + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); #endregion diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample03_EventProcessorHandlersLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample03_EventProcessorHandlersLiveTests.cs index d4c74c52e1acb..c7ec9df2d6f60 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample03_EventProcessorHandlersLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample03_EventProcessorHandlersLiveTests.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Azure.Identity; using Azure.Messaging.EventHubs.Consumer; using Azure.Messaging.EventHubs.Processor; using Azure.Storage.Blobs; @@ -33,29 +34,40 @@ public void EventHandlerExceptionHandling() #region Snippet:EventHubs_Processor_Sample03_EventHandlerExceptionHandling #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = "not-real"; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); Task processEventHandler(ProcessEventArgs args) { @@ -101,29 +113,40 @@ public void EventHandlerCancellation() #region Snippet:EventHubs_Processor_Sample03_EventHandlerCancellation #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = "not-real"; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); Task processEventHandler(ProcessEventArgs args) { @@ -177,29 +200,40 @@ public async Task EventHandlerStopOnException() #region Snippet:EventHubs_Processor_Sample03_EventHandlerStopOnException #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = storageScope.ContainerName; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = eventHubScope.EventHubName; - var consumerGroup = eventHubScope.ConsumerGroups.First(); + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); // This token is used to control processing, // if signaled, then processing will be stopped. @@ -290,29 +324,40 @@ public void ErrorHandlerArgs() #region Snippet:EventHubs_Processor_Sample03_ErrorHandlerArgs #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = "not-real"; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); Task processErrorHandler(ProcessErrorEventArgs args) { @@ -369,29 +414,40 @@ public async Task ErrorHandlerCancellationRecovery() #region Snippet:EventHubs_Processor_Sample03_ErrorHandlerCancellationRecovery #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = storageScope.ContainerName; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = eventHubScope.EventHubName; - var consumerGroup = eventHubScope.ConsumerGroups.First(); + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); // This token is used to control processing, // if signaled, then processing will be stopped. @@ -500,29 +556,40 @@ public void InitializeHandlerArgs() #region Snippet:EventHubs_Processor_Sample03_InitializeHandlerArgs #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = "not-real"; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); Task initializeEventHandler(PartitionInitializingEventArgs args) { @@ -578,29 +645,40 @@ public void CloseHandlerArgs() #region Snippet:EventHubs_Processor_Sample03_CloseHandlerArgs #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = "not-real"; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; - var consumerGroup = "fakeConsumer"; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; + var eventHubName = "fake"; + var consumerGroup = "$Default"; + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = "fake"; #endif + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); Task closeEventHandler(PartitionClosingEventArgs args) { diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample04_ProcessingEventsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample04_ProcessingEventsLiveTests.cs index b736b6d04f9a3..ba76369b51116 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample04_ProcessingEventsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample04_ProcessingEventsLiveTests.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Azure.Identity; using Azure.Messaging.EventHubs.Consumer; using Azure.Messaging.EventHubs.Processor; using Azure.Storage.Blobs; @@ -37,29 +38,40 @@ public async Task BasicEventProcessing() #region Snippet:EventHubs_Processor_Sample04_BasicEventProcessing #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = storageScope.ContainerName; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = storageScope.ContainerName; #endif + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); Task processEventHandler(ProcessEventArgs args) { @@ -177,29 +189,40 @@ public async Task CheckpointByEventCount() #region Snippet:EventHubs_Processor_Sample04_CheckpointByEventCount #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = storageScope.ContainerName; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = storageScope.ContainerName; #endif + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); const int EventsBeforeCheckpoint = 25; var partitionEventCount = new ConcurrentDictionary(); @@ -298,29 +321,40 @@ public async Task InitializePartition() #region Snippet:EventHubs_Processor_Sample04_InitializePartition #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = storageScope.ContainerName; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = storageScope.ContainerName; #endif + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); Task initializeEventHandler(PartitionInitializingEventArgs args) { @@ -410,34 +444,45 @@ public async Task ProcessWithHeartbeat() #region Snippet:EventHubs_Processor_Sample04_ProcessWithHeartbeat #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = storageScope.ContainerName; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); -#endif - var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = storageScope.ContainerName; +#endif var processorOptions = new EventProcessorClientOptions { MaximumWaitTime = TimeSpan.FromMilliseconds(250) }; + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + + var storageClient = new BlobContainerClient( + blobUriBuilder.ToUri(), + credential); + var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, + fullyQualifiedNamespace, eventHubName, + credential, processorOptions); async Task processEventHandler(ProcessEventArgs args) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample05_IdentityAndSharedAccessCredentialsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample05_IdentityAndSharedAccessCredentialsLiveTests.cs index 8b2697a9d05ed..11ccf8705359b 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample05_IdentityAndSharedAccessCredentialsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample05_IdentityAndSharedAccessCredentialsLiveTests.cs @@ -39,7 +39,7 @@ public async Task DefaultAzureCredential() #if SNIPPET var credential = new DefaultAzureCredential(); - var storageEndpoint = "<< STORAGE ENDPOINT (likely similar to {your-account}.blob.core.windows.net) >>"; + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; @@ -47,15 +47,19 @@ public async Task DefaultAzureCredential() var consumerGroup = "<< NAME OF THE EVENT HUB CONSUMER GROUP >>"; #else var credential = EventHubsTestEnvironment.Instance.Credential; - var storageEndpoint = new BlobServiceClient(StorageTestEnvironment.Instance.StorageConnectionString).Uri.ToString(); - var blobContainerName = storageScope.ContainerName; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = storageScope.ContainerName; #endif - var blobUriBuilder = new BlobUriBuilder(new Uri(storageEndpoint)); - blobUriBuilder.BlobContainerName = blobContainerName; + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; var storageClient = new BlobContainerClient( blobUriBuilder.ToUri(), diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample06_RequestingStorageServiceVersionsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample06_RequestingStorageServiceVersionsLiveTests.cs index 2a7b0639ffd14..2f21d4266cfcf 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample06_RequestingStorageServiceVersionsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample06_RequestingStorageServiceVersionsLiveTests.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Azure.Core; using Azure.Core.Pipeline; +using Azure.Identity; using Azure.Messaging.EventHubs.Processor; using Azure.Storage.Blobs; using NUnit.Framework; @@ -36,18 +37,23 @@ public async Task ProcessEvents() #region Snippet:EventHubs_Processor_Sample06_ChooseStorageVersion #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = storageScope.ContainerName; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = storageScope.ContainerName; #endif var storageClientOptions = new BlobClientOptions(); @@ -56,16 +62,22 @@ public async Task ProcessEvents() new StorageApiVersionPolicy(), HttpPipelinePosition.PerCall); + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName, + blobUriBuilder.ToUri(), + credential, storageClientOptions); var processor = new EventProcessorClient( storageClient, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample07_BatchProcessingLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample07_BatchProcessingLiveTests.cs index 3fe28b1eb7d45..4f6e8f53b8141 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample07_BatchProcessingLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample07_BatchProcessingLiveTests.cs @@ -6,6 +6,8 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Azure.Core; +using Azure.Identity; using Azure.Messaging.EventHubs.Primitives; using Azure.Messaging.EventHubs.Processor; using Azure.Storage.Blobs; @@ -36,23 +38,33 @@ public async Task ProcessByBatch() #region Snippet:EventHubs_Processor_Sample07_ProcessByBatch_Usage #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; #else - var storageConnectionString = StorageTestEnvironment.Instance.StorageConnectionString; - var blobContainerName = storageScope.ContainerName; - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var credential = EventHubsTestEnvironment.Instance.Credential; + + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); + + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = storageScope.ContainerName; #endif + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); var checkpointStore = new BlobCheckpointStore(storageClient); var maximumBatchSize = 100; @@ -61,8 +73,9 @@ public async Task ProcessByBatch() checkpointStore, maximumBatchSize, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); @@ -103,15 +116,17 @@ public class SimpleBatchProcessor : PluggableCheckpointStoreEventProcessor` also offers native batch processing, a greater level of control over communication with the Event Hubs service, and a less opinionated API. The caveat is that this comes with additional complexity and exists as an abstract base, which needs to be extended. +- The [PluggableCheckpointStoreEventProcessor<TPartition>](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.primitives.PluggableCheckpointStoreEventProcessor-1?view=azure-dotnet) provides a base for creating a custom processor for reading and processing events from all partitions of an Event Hub, using the provided checkpoint store for state persistence. It fills a role similar to the [EventProcessorClient](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples) from the [Azure.Messaging.EventHubs.Processor](https://www.nuget.org/packages/Azure.Messaging.EventHubs.Processor) package, with cooperative load balancing and resiliency as its core features. However, `PluggableCheckpointStoreEventProcessor` also offers native batch processing, a greater level of control over communication with the Event Hubs service, and a less opinionated API. The caveat is that this comes with additional complexity and exists as an abstract base, which needs to be extended. -- The [EventProcessor<TPartition>](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.primitives.eventprocessor-1?view=azure-dotnet) is our lowest-level base for creating a custom processor allowing the greatest degree of customizability. It fills a role similar to the [PluggableCheckpointStoreEventProcessor<TPartition>](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.primitives.PluggableCheckpointStoreEventProcessor-1?view=azure-dotnet), with cooperative load balancing, resiliency, and batch processing as its core features. However, `EventProcessor` also provides the ability to customize checkpoint storage, including using different stores for ownership and checkpoint data. `EventProcessor` exists as an abstract base, which needs to be extended. More on the design and philosophy behind this type can be found in its [design document](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs/design/proposal-event-processor%7BT%7D.md). +- The [EventProcessor<TPartition>](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.primitives.eventprocessor-1?view=azure-dotnet) is our lowest-level base for creating a custom processor allowing the greatest degree of customizability. It fills a role similar to the [PluggableCheckpointStoreEventProcessor<TPartition>](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.primitives.PluggableCheckpointStoreEventProcessor-1?view=azure-dotnet), with cooperative load balancing, resiliency, and batch processing as its core features. However, `EventProcessor` also provides the ability to customize checkpoint storage, including using different stores for ownership and checkpoint data. `EventProcessor` exists as an abstract base, which needs to be extended. More on the design and philosophy behind this type can be found in its [design document](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs/design/proposal-event-processor%7BT%7D.md). ### Client constructors @@ -206,10 +206,14 @@ finally In the `Azure.Messaging.EventHubs` library, the `EventHubProducerClient` is used as the publisher for a batch created with its default configuration. ```C# Snippet:EventHubs_Sample04_AutomaticRouting -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -276,10 +280,14 @@ finally In the `Azure.Messaging.EventHubs` library, the `EventHubProducerClient` is used as the publisher for a batch created with a partition key specified as an option. ```C# Snippet:EventHubs_Sample04_PartitionKey -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -351,10 +359,14 @@ finally In the `Azure.Messaging.EventHubs` library, the `EventHubProducerClient` is used as the publisher for a batch created with a partition identifier specified as an option. ```C# Snippet:EventHubs_Sample04_PartitionId -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -387,7 +399,7 @@ finally ### Reading events -In the `Microsoft.Azure.EventHubs` library, reading events can be performed by either the `EventProcessorHost` or the `PartitionReceiver`, depending on whether you would like to read from all partitions of an Event Hub or a single partition. Generally, using the `EventProcessorHost` is the preferred approach for most production scenarios. +In the `Microsoft.Azure.EventHubs` library, reading events can be performed by either the `EventProcessorHost` or the `PartitionReceiver`, depending on whether you would like to read from all partitions of an Event Hub or a single partition. Generally, using the `EventProcessorHost` is the preferred approach for most production scenarios. The `Azure.Messaging.EventHubs` library also provides multiple types for reading events, with the `EventProcessorClient` focused on reading from all partitions, and the `EventHubConsumerClient` and `PartitionReceiver` focused on reading from a single partition. The `EventProcessorClient` is the preferred approach for most production scenarios. For a detailed discussion of common scenarios and options, please see the [Event Processor Client](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples) and [Reading Events](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample05_ReadingEvents.md) samples. @@ -658,17 +670,19 @@ finally } ``` -In the `Azure.Messaging.EventHubs` library, the `EventHubConsumerClient` can be used to read events from a partition in a streaming manner using the asynchronous enumerator pattern. +In the `Azure.Messaging.EventHubs` library, the `EventHubConsumerClient` can be used to read events from a partition in a streaming manner using the asynchronous enumerator pattern. ```C# Snippet:EventHubs_Sample05_ReadPartition -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -703,8 +717,9 @@ finally For those that prefer a batched approach to reading, `Azure.Messaging.EventHubs` also offers a `PartitionReceiver` that follows pull-based semantics. ```C# Snippet:EventHubs_Sample05_ReadPartitionWithReceiver -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; using CancellationTokenSource cancellationSource = new CancellationTokenSource(); @@ -712,7 +727,10 @@ cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); string firstPartition; -await using (var producer = new EventHubProducerClient(connectionString, eventHubName)) +await using (var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential)) { firstPartition = (await producer.GetPartitionIdsAsync()).First(); } @@ -721,8 +739,9 @@ var receiver = new PartitionReceiver( consumerGroup, firstPartition, EventPosition.Earliest, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -762,7 +781,7 @@ In `Azure.Messaging.EventHubs`, Activity baggage is not currently flowed through ## Migrating EventProcessorHost checkpoints -In `Microsoft.Azure.EventHubs`, the `EventProcessorHost` supported a model of pluggable storage providers for checkpoint data, using Azure Storage Blobs as the default. Using the Azure Storage checkpoint manager, the lease and checkpoint information is stored as a JSON blob appearing within the Azure Storage account provided to the `EventProcessorHost`. More details can be found in the [documentation](https://docs.microsoft.com/azure/event-hubs/event-hubs-event-processor-host#partition-ownership-tracking). +In `Microsoft.Azure.EventHubs`, the `EventProcessorHost` supported a model of pluggable storage providers for checkpoint data, using Azure Storage Blobs as the default. Using the Azure Storage checkpoint manager, the lease and checkpoint information is stored as a JSON blob appearing within the Azure Storage account provided to the `EventProcessorHost`. More details can be found in the [documentation](https://learn.microsoft.com/azure/event-hubs/event-hubs-event-processor-host#partition-ownership-tracking). In `Azure.Messaging.EventHubs`, the `EventProcessorClient` is an opinionated implementation, storing checkpoints in Azure Storage Blobs using the blob metadata to track information. Unfortunately, the `EventProcessorClient` is unable to consume legacy checkpoints due to the differences in format, approach, and the possibility of a custom checkpoint provider having been used. @@ -777,14 +796,16 @@ private class MigrationCheckpoint } ``` -The `Azure.Messaging.EventHubs` checkpoints are expected by the `EventProcessorClient` to exist in a specifically named blob per partition that contains two metadata attributes. Any content of the blob itself is ignored. Casing is significant where both the name of the blob and the metadata attributes are concerned and must be lowercase. +The `Azure.Messaging.EventHubs` checkpoints are expected by the `EventProcessorClient` to exist in a specifically named blob per partition that contains two metadata attributes. Any content of the blob itself is ignored. Casing is significant where both the name of the blob and the metadata attributes are concerned and must be lowercase. ```C# Snippet:EventHubs_Migrate_Checkpoints +var credential = new DefaultAzureCredential(); + 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 >>"; -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; var legacyBlobContainerName = "<< NAME OF THE BLOB CONTAINER THAT CONTAINS THE LEGACY DATA>>"; @@ -796,9 +817,10 @@ using var cancellationSource = new CancellationTokenSource(); // Note: The ReadLegacyCheckpoints method will be defined in another snippet. var legacyCheckpoints = await ReadLegacyCheckpoints( - storageConnectionString, + storageAccountEndpoint, legacyBlobContainerName, consumerGroup, + credential, cancellationSource.Token); // The member names of MigrationCheckpoint match the names of the checkpoint @@ -820,7 +842,15 @@ var prefix = string.Format( // assumes that the connection string grants the appropriate permissions to create a // container in the storage account. -var storageClient = new BlobContainerClient(storageConnectionString, blobContainerName); +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + +var storageClient = new BlobContainerClient( + blobUriBuilder.ToUri(), + credential); + await storageClient.CreateIfNotExistsAsync(cancellationToken: cancellationSource.Token); // Translate each of the legacy checkpoints, storing the offset and @@ -849,12 +879,20 @@ The following snippet to read and parse legacy checkpoints assumes that the defa ```C# Snippet:EventHubs_Migrate_LegacyCheckpoints private async Task> ReadLegacyCheckpoints( - string connectionString, + string storageAccountEndpoint, string container, string consumerGroup, + TokenCredential credential, CancellationToken cancellationToken) { - var storageClient = new BlobContainerClient(connectionString, container); + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = container + }; + + var storageClient = new BlobContainerClient( + blobUriBuilder.ToUri(), + credential); // If there is no container, no action can be taken. diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/MigrationGuide_WindowsAzureServiceBus.md b/sdk/eventhub/Azure.Messaging.EventHubs/MigrationGuide_WindowsAzureServiceBus.md index 6ad936287d768..deae35e89f4f8 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/MigrationGuide_WindowsAzureServiceBus.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs/MigrationGuide_WindowsAzureServiceBus.md @@ -164,10 +164,14 @@ finally In the `Azure.Messaging.EventHubs` library, the `EventHubProducerClient` is used as the publisher for a batch created with its default configuration. ```C# Snippet:EventHubs_Sample04_AutomaticRouting -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -227,10 +231,14 @@ finally In the `Azure.Messaging.EventHubs` library, the `EventHubProducerClient` is used as the publisher for a batch created with a partition key specified as an option. ```C# Snippet:EventHubs_Sample04_PartitionKey -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -299,10 +307,14 @@ finally In the `Azure.Messaging.EventHubs` library, the `EventHubProducerClient` is used as the publisher for a batch created with a partition identifier specified as an option. ```C# Snippet:EventHubs_Sample04_PartitionId -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -588,14 +600,16 @@ finally In the `Azure.Messaging.EventHubs` library, the `EventHubConsumerClient` can be used to read events from a partition in a streaming manner using the asynchronous enumerator pattern. ```C# Snippet:EventHubs_Sample05_ReadPartition -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -630,8 +644,9 @@ finally For those that prefer a batched approach to reading, `Azure.Messaging.EventHubs` also offers a `PartitionReceiver` that follows pull-based semantics. ```C# Snippet:EventHubs_Sample05_ReadPartitionWithReceiver -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; using CancellationTokenSource cancellationSource = new CancellationTokenSource(); @@ -639,7 +654,10 @@ cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); string firstPartition; -await using (var producer = new EventHubProducerClient(connectionString, eventHubName)) +await using (var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential)) { firstPartition = (await producer.GetPartitionIdsAsync()).First(); } @@ -648,8 +666,9 @@ var receiver = new PartitionReceiver( consumerGroup, firstPartition, EventPosition.Earliest, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/README.md b/sdk/eventhub/Azure.Messaging.EventHubs/README.md index ff5bd91461f85..8470eb1c1fbc4 100755 --- a/sdk/eventhub/Azure.Messaging.EventHubs/README.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs/README.md @@ -26,7 +26,7 @@ The Azure Event Hubs client library allows for publishing and consuming of Azure Visual Studio users wishing to take full advantage of the C# 8.0 syntax will need to use Visual Studio 2019 or later. Visual Studio 2019, including the free Community edition, can be downloaded [here](https://visualstudio.microsoft.com). Users of Visual Studio 2017 can take advantage of the C# 8 syntax by making use of the [Microsoft.Net.Compilers NuGet package](https://www.nuget.org/packages/Microsoft.Net.Compilers/) and setting the language version, though the editing experience may not be ideal. - You can still use the library with previous C# language versions, but will need to manage asynchronous enumerable and asynchronous disposable members manually rather than benefiting from the new syntax. You may still target any framework version supported by your .NET Core SDK, including earlier versions of .NET Core or the .NET framework. For more information, see: [how to specify target frameworks](https://learn.microsoft.com/dotnet/standard/frameworks#how-to-specify-target-frameworks). + You can still use the library with previous C# language versions, but will need to manage asynchronous enumerable and asynchronous disposable members manually rather than benefiting from the new syntax. You may still target any framework version supported by your .NET Core SDK, including earlier versions of .NET Core or the .NET framework. For more information, see: [how to specify target frameworks](https://learn.microsoft.com/dotnet/standard/frameworks#how-to-specify-target-frameworks). **Important Note:** In order to build or run the [examples](#examples) and the [samples](#next-steps) without modification, use of C# 11.0 is necessary. You can still run the samples if you decide to tweak them for other language versions. An example of doing so is available in the sample: [Earlier Language Versions](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample07_EarlierLanguageVersions.md). To quickly create a basic set of Event Hubs resources in Azure and to receive a connection string for them, you can deploy our sample template by clicking: @@ -66,13 +66,13 @@ For examples of authenticating the Event Hubs clients for an ASP.NET Core applic - An **Event Hub client** is the primary interface for developers interacting with the Event Hubs client library. There are several different Event Hub clients, each dedicated to a specific use of Event Hubs, such as publishing or consuming events. -- An **Event Hub producer** is a type of client that serves as a source of telemetry data, diagnostics information, usage logs, or other log data, as part of an embedded device solution, a mobile device application, a game title running on a console or other device, some client or server based business solution, or a web site. +- An **Event Hub producer** is a type of client that serves as a source of telemetry data, diagnostics information, usage logs, or other log data, as part of an embedded device solution, a mobile device application, a game title running on a console or other device, some client or server based business solution, or a web site. -- An **Event Hub consumer** is a type of client which reads information from the Event Hub and allows processing of it. Processing may involve aggregation, complex computation and filtering. Processing may also involve distribution or storage of the information in a raw or transformed fashion. Event Hub consumers are often robust and high-scale platform infrastructure parts with built-in analytics capabilities, like Azure Stream Analytics, Apache Spark, or Apache Storm. +- An **Event Hub consumer** is a type of client which reads information from the Event Hub and allows processing of it. Processing may involve aggregation, complex computation and filtering. Processing may also involve distribution or storage of the information in a raw or transformed fashion. Event Hub consumers are often robust and high-scale platform infrastructure parts with built-in analytics capabilities, like Azure Stream Analytics, Apache Spark, or Apache Storm. - A **partition** is an ordered sequence of events that is held in an Event Hub. Partitions are a means of data organization associated with the parallelism required by event consumers. Azure Event Hubs provides message streaming through a partitioned consumer pattern in which each consumer only reads a specific subset, or partition, of the message stream. As newer events arrive, they are added to the end of this sequence. The number of partitions is specified at the time an Event Hub is created and cannot be changed. -- A **consumer group** is a view of an entire Event Hub. Consumer groups enable multiple consuming applications to each have a separate view of the event stream, and to read the stream independently at their own pace and from their own position. There can be at most 5 concurrent readers on a partition per consumer group; however it is recommended that there is only one active consumer for a given partition and consumer group pairing. Each active reader receives all of the events from its partition; if there are multiple readers on the same partition, then they will receive duplicate events. +- A **consumer group** is a view of an entire Event Hub. Consumer groups enable multiple consuming applications to each have a separate view of the event stream, and to read the stream independently at their own pace and from their own position. There can be at most 5 concurrent readers on a partition per consumer group; however it is recommended that there is only one active consumer for a given partition and consumer group pairing. Each active reader receives all of the events from its partition; if there are multiple readers on the same partition, then they will receive duplicate events. For more concepts and deeper discussion, see: [Event Hubs Features](https://learn.microsoft.com/azure/event-hubs/event-hubs-features). @@ -82,7 +82,7 @@ Each of the Event Hubs client types is safe to cache and use as a singleton for ### Thread safety -We guarantee that all client instance methods are thread-safe and independent of each other ([guideline](https://azure.github.io/azure-sdk/dotnet_introduction.html#dotnet-service-methods-thread-safety)). This ensures that the recommendation of reusing client instances is always safe, even across threads. +We guarantee that all client instance methods are thread-safe and independent of each other ([guideline](https://azure.github.io/azure-sdk/dotnet_introduction.html#dotnet-service-methods-thread-safety)). This ensures that the recommendation of reusing client instances is always safe, even across threads. The data model types, such as `EventData` and `EventDataBatch` are not thread-safe. They should not be shared across threads nor used concurrently with client methods. @@ -212,18 +212,35 @@ Since the `EventProcessorClient` has a dependency on Azure Storage blobs for per var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(45)); -var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; +var credential = new DefaultAzureCredential(); + +var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; -var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +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 >>"; 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); +var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) +{ + BlobContainerName = blobContainerName +}; + +var storageClient = new BlobContainerClient( + blobUriBuilder.ToUri(), + credential); + +var processor = new EventProcessorClient +( + storageClient, + consumerGroup, + fullyQualifiedNamespace, + eventHubName, + credential +); processor.ProcessEventAsync += processEventHandler; processor.ProcessErrorAsync += processErrorHandler; @@ -305,7 +322,7 @@ public void ConfigureServices(IServiceCollection services) { builder.AddEventHubProducerClient(Configuration.GetConnectionString("EventHubs")); }); - + services.AddControllers(); } ``` @@ -337,7 +354,7 @@ public void ConfigureServices(IServiceCollection services) // register that instance as the default credential instead. builder.UseCredential(new ManagedIdentityCredential()); }); - + services.AddControllers(); } ``` @@ -360,7 +377,7 @@ The Event Hubs client library is also instrumented for distributed tracing using Beyond the introductory scenarios discussed, the Azure Event Hubs client library offers support for additional scenarios to help take advantage of the full feature set of the Azure Event Hubs service. In order to help explore some of these scenarios, the Event Hubs client library offers a project of samples to serve as an illustration for common scenarios. Please see the samples [README](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/README.md) for details. -## Contributing +## Contributing This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com. diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/TROUBLESHOOTING.md b/sdk/eventhub/Azure.Messaging.EventHubs/TROUBLESHOOTING.md index 3c63e5dfdd251..f651fca83dc73 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/TROUBLESHOOTING.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs/TROUBLESHOOTING.md @@ -231,7 +231,7 @@ Generally, it is recommended that an event processor own no more than 3 partitio Further reading: - [Debug ThreadPool Starvation][DebugThreadPoolStarvation] -- [Diagnosing .NET Core ThreadPool Starvation with PerfView (Why my service is not saturating all cores or seems to stall)](https://docs.microsoft.com/archive/blogs/vancem/diagnosing-net-core-threadpool-starvation-with-perfview-why-my-service-is-not-saturating-all-cores-or-seems-to-stall) +- [Diagnosing .NET Core ThreadPool Starvation with PerfView (Why my service is not saturating all cores or seems to stall)](https://learn.microsoft.com/archive/blogs/vancem/diagnosing-net-core-threadpool-starvation-with-perfview-why-my-service-is-not-saturating-all-cores-or-seems-to-stall) - [Diagnosing ThreadPool Exhaustion Issues in .NET Core Apps][DiagnoseThreadPoolExhaustion] _(video)_ #### "Soft Delete" or "Blob versioning" is enabled for a Blob Storage checkpoint store: @@ -453,28 +453,28 @@ For more information on ways to request support, please see: [Support][SUPPORT]. [MigrationGuideT1]: https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs/MigrationGuide.md [SUPPORT]: https://github.com/Azure/azure-sdk-for-net/blob/main/SUPPORT.md - -[AuthorizeSAS]: https://docs.microsoft.com/azure/event-hubs/authorize-access-shared-access-signature -[AzureSdkNetLogging]: https://docs.microsoft.com/dotnet/azure/sdk/logging#map-to-aspnet-core-logging -[DebugThreadPoolStarvation]: https://docs.microsoft.com/dotnet/core/diagnostics/debug-threadpool-starvation -[DependencyInjectionAzureFunctions]: https://docs.microsoft.com/azure/azure-functions/functions-dotnet-dependency-injection -[DependencyInjectionAzureSdk]: https://docs.microsoft.com/dotnet/azure/sdk/dependency-injection -[DiagnoseThreadPoolExhaustion]: https://docs.microsoft.com/shows/on-net/diagnosing-thread-pool-exhaustion-issues-in-net-core-apps -[EventHubsException]: https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventhubsexception -[EventHubsIPAddresses]: https://docs.microsoft.com/azure/event-hubs/troubleshooting-guide#what-ip-addresses-do-i-need-to-allow -[EventHubsMessagingExceptions]: https://docs.microsoft.com/azure/event-hubs/event-hubs-messaging-exceptions -[EventHubsQuotas]: https://docs.microsoft.com/azure/event-hubs/event-hubs-quotas -[EventHubsRetryOptions]: https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventhubsretryoptions -[EventHubsTroubleshooting]: https://docs.microsoft.com/azure/event-hubs/troubleshooting-guide -[GetConnectionString]: https://docs.microsoft.com/azure/event-hubs/event-hubs-get-connection-string -[IoTHubDocs]: https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-endpoints -[IoTEventHubEndpoint]: https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-messages-read-builtin -[IoTHubSAS]: https://docs.microsoft.com/azure/iot-hub/iot-hub-dev-guide-sas#security-tokens -[RBAC]: https://docs.microsoft.com/azure/event-hubs/authorize-access-azure-active-directory -[SoftDeleteBlobStorage]: https://docs.microsoft.com/azure/storage/blobs/soft-delete-blob-overview -[VersioningBlobStorage]: https://docs.microsoft.com/azure/storage/blobs/versioning-overview -[TroubleshootAuthenticationAuthorization]: https://docs.microsoft.com/azure/event-hubs/troubleshoot-authentication-authorization -[UnauthorizedAccessException]: https://docs.microsoft.com/dotnet/api/system.unauthorizedaccessexception + +[AuthorizeSAS]: https://learn.microsoft.com/azure/event-hubs/authorize-access-shared-access-signature +[AzureSdkNetLogging]: https://learn.microsoft.com/dotnet/azure/sdk/logging#map-to-aspnet-core-logging +[DebugThreadPoolStarvation]: https://learn.microsoft.com/dotnet/core/diagnostics/debug-threadpool-starvation +[DependencyInjectionAzureFunctions]: https://learn.microsoft.com/azure/azure-functions/functions-dotnet-dependency-injection +[DependencyInjectionAzureSdk]: https://learn.microsoft.com/dotnet/azure/sdk/dependency-injection +[DiagnoseThreadPoolExhaustion]: https://learn.microsoft.com/shows/on-net/diagnosing-thread-pool-exhaustion-issues-in-net-core-apps +[EventHubsException]: https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventhubsexception +[EventHubsIPAddresses]: https://learn.microsoft.com/azure/event-hubs/troubleshooting-guide#what-ip-addresses-do-i-need-to-allow +[EventHubsMessagingExceptions]: https://learn.microsoft.com/azure/event-hubs/event-hubs-messaging-exceptions +[EventHubsQuotas]: https://learn.microsoft.com/azure/event-hubs/event-hubs-quotas +[EventHubsRetryOptions]: https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventhubsretryoptions +[EventHubsTroubleshooting]: https://learn.microsoft.com/azure/event-hubs/troubleshooting-guide +[GetConnectionString]: https://learn.microsoft.com/azure/event-hubs/event-hubs-get-connection-string +[IoTHubDocs]: https://learn.microsoft.com/azure/iot-hub/iot-hub-devguide-endpoints +[IoTEventHubEndpoint]: https://learn.microsoft.com/azure/iot-hub/iot-hub-devguide-messages-read-builtin +[IoTHubSAS]: https://learn.microsoft.com/azure/iot-hub/iot-hub-dev-guide-sas#security-tokens +[RBAC]: https://learn.microsoft.com/azure/event-hubs/authorize-access-azure-active-directory +[SoftDeleteBlobStorage]: https://learn.microsoft.com/azure/storage/blobs/soft-delete-blob-overview +[VersioningBlobStorage]: https://learn.microsoft.com/azure/storage/blobs/versioning-overview +[TroubleshootAuthenticationAuthorization]: https://learn.microsoft.com/azure/event-hubs/troubleshoot-authentication-authorization +[UnauthorizedAccessException]: https://learn.microsoft.com/dotnet/api/system.unauthorizedaccessexception [AmqpSpec]: https://docs.oasis-open.org/amqp/core/v1.0/os/amqp-core-types-v1.0-os.html diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/samples/README.md b/sdk/eventhub/Azure.Messaging.EventHubs/samples/README.md index 971ea3fdcb316..4c6018fcf3966 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/samples/README.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs/samples/README.md @@ -11,11 +11,11 @@ description: Samples for the Azure.Messaging.EventHubs client library # Azure.Messaging.EventHubs Samples -The Azure Event Hubs client library offers samples in two forms. Common application scenarios are presented as markdown documents, providing a detailed explanation of context while also demonstrating implementation details with snippets of code. More specialized scenarios are presented as stand-alone projects to both illustrate the deeper end-to-end context and allow exploring interactively. +The Azure Event Hubs client library offers samples in two forms. Common application scenarios are presented as markdown documents, providing a detailed explanation of context while also demonstrating implementation details with snippets of code. More specialized scenarios are presented as stand-alone projects to both illustrate the deeper end-to-end context and allow exploring interactively. The markdown-based samples are ordered by increasing complexity, starting with more basic scenarios to help get started quickly. Though each sample is independent, they will assume an understanding of the content discussed in earlier samples. -Each of the application samples are intended to be self-contained and focused on illustrating one specific scenario. The simplest way to begin is to launch the project for debugging in Visual Studio, or your preferred IDE, and provide the Event Hubs connection information in response to the prompts. Each of these sample applications is accompanied by a dedicated README, offering more specific detail about its hosting needs and operation. +Each of the application samples are intended to be self-contained and focused on illustrating one specific scenario. The simplest way to begin is to launch the project for debugging in Visual Studio, or your preferred IDE, and provide the Event Hubs connection information in response to the prompts. Each of these sample applications is accompanied by a dedicated README, offering more specific detail about its hosting needs and operation. ## Getting started @@ -23,13 +23,13 @@ Each of the application samples are intended to be self-contained and focused on - **Azure Subscription:** To use Azure services, including Azure Event Hubs, you'll need a subscription. If you do not have an existing Azure account, you may sign up for a [free trial](https://azure.microsoft.com/free/dotnet/) or use your [Visual Studio Subscription](https://visualstudio.microsoft.com/subscriptions/) benefits when you [create an account](https://azure.microsoft.com/account). -- **Event Hubs namespace with an Event Hub:** To interact with Azure Event Hubs, you'll also need to have a namespace and Event Hub available. If you are not familiar with creating Azure resources, you may wish to follow the step-by-step guide for [creating an Event Hub using the Azure portal](https://docs.microsoft.com/azure/event-hubs/event-hubs-create). There, you can also find detailed instructions for using the Azure CLI, Azure PowerShell, or Azure Resource Manager (ARM) templates to create an Event Hub. +- **Event Hubs namespace with an Event Hub:** To interact with Azure Event Hubs, you'll also need to have a namespace and Event Hub available. If you are not familiar with creating Azure resources, you may wish to follow the step-by-step guide for [creating an Event Hub using the Azure portal](https://learn.microsoft.com/azure/event-hubs/event-hubs-create). There, you can also find detailed instructions for using the Azure CLI, Azure PowerShell, or Azure Resource Manager (ARM) templates to create an Event Hub. -- **C# 8.0:** The Azure Event Hubs client library makes use of new features that were introduced in C# 8.0. In order to take advantage of the C# 8.0 syntax, it is recommended that you compile using the [.NET Core SDK](https://dotnet.microsoft.com/download) 3.0 or higher with a [language version](https://docs.microsoft.com/dotnet/csharp/language-reference/configure-language-version#override-a-default) of `latest`. +- **C# 8.0:** The Azure Event Hubs client library makes use of new features that were introduced in C# 8.0. In order to take advantage of the C# 8.0 syntax, it is recommended that you compile using the [.NET Core SDK](https://dotnet.microsoft.com/download) 3.0 or higher with a [language version](https://learn.microsoft.com/dotnet/csharp/language-reference/configure-language-version#override-a-default) of `latest`. Visual Studio users wishing to take full advantage of the C# 8.0 syntax will need to use Visual Studio 2019 or later. Visual Studio 2019, including the free Community edition, can be downloaded [here](https://visualstudio.microsoft.com). Users of Visual Studio 2017 can take advantage of the C# 8 syntax by making use of the [Microsoft.Net.Compilers NuGet package](https://www.nuget.org/packages/Microsoft.Net.Compilers/) and setting the language version, though the editing experience may not be ideal. - You can still use the library with previous C# language versions, but will need to manage asynchronous enumerable and asynchronous disposable members manually rather than benefiting from the new syntax. You may still target any framework version supported by your .NET Core SDK, including earlier versions of .NET Core or the .NET framework. For more information, see: [how to specify target frameworks](https://docs.microsoft.com/dotnet/standard/frameworks#how-to-specify-target-frameworks). + You can still use the library with previous C# language versions, but will need to manage asynchronous enumerable and asynchronous disposable members manually rather than benefiting from the new syntax. You may still target any framework version supported by your .NET Core SDK, including earlier versions of .NET Core or the .NET framework. For more information, see: [how to specify target frameworks](https://learn.microsoft.com/dotnet/standard/frameworks#how-to-specify-target-frameworks). To quickly create a basic set of Event Hubs resources in Azure and to receive a connection string for them, you can deploy our sample template by clicking: @@ -45,44 +45,44 @@ dotnet add package Azure.Messaging.EventHubs ### Authenticate the client -For the Event Hubs client library to interact with an Event Hub, it will need to understand how to connect and authorize with it. The easiest means for doing so is to use a connection string, which is created automatically when creating an Event Hubs namespace. If you aren't familiar with using connection strings with Event Hubs, you may wish to follow the step-by-step guide to [get an Event Hubs connection string](https://docs.microsoft.com/azure/event-hubs/event-hubs-get-connection-string). +For the Event Hubs client library to interact with an Event Hub, it will need to understand how to connect and authorize with it. The easiest means for doing so is to use a connection string, which is created automatically when creating an Event Hubs namespace. If you aren't familiar with using connection strings with Event Hubs, you may wish to follow the step-by-step guide to [get an Event Hubs connection string](https://learn.microsoft.com/azure/event-hubs/event-hubs-get-connection-string). ## Common samples -- [Hello world](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample01_HelloWorld.md) - An introduction to Event Hubs, illustrating the basic flow of events through an Event Hub, with the goal of quickly allowing you to view events being published and read from the Event Hubs service. - -- [Event Hubs Clients](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample02_EventHubsClients.md) - An overview of the Event Hubs clients, detailing the available client types, the scenarios they serve, and demonstrating options for customizing their configuration, such as specifying a proxy. - -- [Event Hubs Metadata](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample03_EventHubMetadata.md) - A discussion of the metadata available for an Event Hub instance and demonstration of how to query and inspect the information. - -- [Publishing Events](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample04_PublishingEvents.md) - A deep dive into publishing events using the Event Hubs client library, detailing the different options available and illustrating common scenarios. - -- [Reading Events](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample05_ReadingEvents.md) - A deep dive into reading events using the Event Hubs client library, detailing the different options available and illustrating common scenarios. - -- [Identity and Shared Access Credentials](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample06_IdentityAndSharedAccessCredentials.md) - A discussion of the different types of authorization supported, focusing on identity-based credentials for Azure Active Directory and use the of shared access signatures and keys. - -- [Earlier Language Versions](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample07_EarlierLanguageVersions.md) +- [Hello world](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample01_HelloWorld.md) + An introduction to Event Hubs, illustrating the basic flow of events through an Event Hub, with the goal of quickly allowing you to view events being published and read from the Event Hubs service. + +- [Event Hubs Clients](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample02_EventHubsClients.md) + An overview of the Event Hubs clients, detailing the available client types, the scenarios they serve, and demonstrating options for customizing their configuration, such as specifying a proxy. + +- [Event Hubs Metadata](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample03_EventHubMetadata.md) + A discussion of the metadata available for an Event Hub instance and demonstration of how to query and inspect the information. + +- [Publishing Events](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample04_PublishingEvents.md) + A deep dive into publishing events using the Event Hubs client library, detailing the different options available and illustrating common scenarios. + +- [Reading Events](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample05_ReadingEvents.md) + A deep dive into reading events using the Event Hubs client library, detailing the different options available and illustrating common scenarios. + +- [Identity and Shared Access Credentials](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample06_IdentityAndSharedAccessCredentials.md) + A discussion of the different types of authorization supported, focusing on identity-based credentials for Azure Active Directory and use the of shared access signatures and keys. + +- [Earlier Language Versions](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample07_EarlierLanguageVersions.md) A demonstration of how to interact with the client library using earlier versions of C#, where newer syntax for asynchronous enumeration and disposal are not available. -- [Building a Custom Event Processor using EventProcessor<TPartition>](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample08_CustomEventProcessor.md) +- [Building a Custom Event Processor using EventProcessor<TPartition>](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample08_CustomEventProcessor.md) An introduction to the `EventProcessor` base class which is used when building advanced processors which need full control over state management. -- [Observable Event Data Batch](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample09_ObservableEventBatch.md) +- [Observable Event Data Batch](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample09_ObservableEventBatch.md) A demonstration of how to write an `ObservableEventDataBatch` class that wraps an `EventDataBatch` in order to allow an application to read events that have been added to a batch. -- [Capturing Event Hubs logs using AzureEventSourceListener class](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample10_AzureEventSourceListener.md) +- [Capturing Event Hubs logs using AzureEventSourceListener class](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample10_AzureEventSourceListener.md) A demonstration of how to use the [`AzureEventSourceListener`](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/samples/Diagnostics.md#logging) from the `Azure.Core` package to capture logs emitted by the Event Hubs client library. - -- [Mocking Client Types](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample11_MockingClientTypes.md) + +- [Mocking Client Types](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample11_MockingClientTypes.md) A demonstration of how to mock the types in the Event Hubs client library, focusing on common application scenarios. -## Contributing +## Contributing This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com. diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample01_HelloWorld.md b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample01_HelloWorld.md index 56f67e85c7710..150f714509535 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample01_HelloWorld.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample01_HelloWorld.md @@ -15,9 +15,11 @@ To begin, please ensure that you're familiar with the items discussed in the [Ge To interact with Event Hubs, a client is needed for each area of functionality - such as publishing and reading of events. All clients are scoped to a single Event Hub instance under an Event Hubs namespace, and clients that read events are also scoped to a consumer group. For this example, we'll configure our clients using the set of information that follows. ```C# Snippet:EventHubs_SamplesCommon_ConsumerBasicConfig -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; + +var credential = new DefaultAzureCredential(); ``` Each of the Event Hubs client types are safe to cache and use for the lifetime of the application, which is best practice when the application publishes or reads events regularly or semi-regularly. The clients hold responsibility for efficient resource management, working to keep resource usage low during periods of inactivity and manage health during periods of higher use. Calling either the `CloseAsync` or `DisposeAsync` method on a client as the application is shutting down will ensure that network resources and other unmanaged objects are properly cleaned up. @@ -29,7 +31,7 @@ var consumer = new EventHubConsumerClient(consumerGroup, connectionString, event ## Publish events -To publish events, we will need the `EventHubsProducerClient` that was created. Because this is the only area of our sample that will be publishing events, we will close the client once publishing has completed. In the majority of real-world scenarios, closing the producer when the application exits is often the preferred pattern. +To publish events, we will need the `EventHubsProducerClient` that was created. Because this is the only area of our sample that will be publishing events, we will close the client once publishing has completed. In the majority of real-world scenarios, closing the producer when the application exits is often the preferred pattern. So that we have something to read, our example will publish a full batch of events. The `EventHubDataBatch` exists to ensure that a set of events can safely be published without exceeding the size allowed by the Event Hub. The `EventDataBatch` queries the service to understand the maximum size and is responsible for accurately measuring each event as it is added to the batch. When its `TryAdd` method returns `false`, the event is too large to fit into the batch. @@ -80,11 +82,11 @@ finally Now that the events have been published, we'll read back all events from the Event Hub using the `EventHubConsumerClient` that was created. It's important to note that because events are not removed when reading, if you're using an existing Event Hub, you are likely to see events that had been previously published as well as those from the batch that we just sent. -An Event Hub consumer is associated with a specific Event Hub and [consumer group](https://docs.microsoft.com/azure/event-hubs/event-hubs-features#consumer-groups). Conceptually, the consumer group is a label that identifies one or more event consumers as a set. Often, consumer groups are named after the responsibility of the consumer in an application, such as "Telemetry" or "OrderProcessing". When an Event Hub is created, a default consumer group is created for it, named "$Default." The default group is what we'll be using for illustration. +An Event Hub consumer is associated with a specific Event Hub and [consumer group](https://learn.microsoft.com/azure/event-hubs/event-hubs-features#consumer-groups). Conceptually, the consumer group is a label that identifies one or more event consumers as a set. Often, consumer groups are named after the responsibility of the consumer in an application, such as "Telemetry" or "OrderProcessing". When an Event Hub is created, a default consumer group is created for it, named "$Default." The default group is what we'll be using for illustration. Each consumer has a unique view of the events in a partition that it reads from, which means that events are available to all consumers and are not removed from the partition when read. This allows consumers to read and process events from the Event Hub at different speeds without interfering with one another. -When events are published, they will continue to exist in the Event Hub and be available for consuming until they reach an age where they are older than the [retention period](https://docs.microsoft.com//azure/event-hubs/event-hubs-faq#what-is-the-maximum-retention-period-for-events). Once removed, the events are no longer available to be read and cannot be recovered. Though the Event Hubs service is free to remove events older than the retention period, it does not do so deterministically; there is no guarantee of when events will be removed. +When events are published, they will continue to exist in the Event Hub and be available for consuming until they reach an age where they are older than the [retention period](https://learn.microsoft.com//azure/event-hubs/event-hubs-faq#what-is-the-maximum-retention-period-for-events). Once removed, the events are no longer available to be read and cannot be recovered. Though the Event Hubs service is free to remove events older than the retention period, it does not do so deterministically; there is no guarantee of when events will be removed. ```C# Snippet:EventHubs_Sample01_ReadEvents try @@ -125,6 +127,6 @@ finally } ``` -This example makes use of the `ReadEvents` method of the `EventHubConsumerClient`, which allows it to see events from all [partitions](https://docs.microsoft.com/azure/event-hubs/event-hubs-features#partitions) of an Event Hub. While this is convenient to use for exploration, we strongly recommend not using it for production scenarios. `ReadEvents` does not guarantee fairness amongst the partitions during iteration; each of the partitions compete to publish events to be read. Depending on how service communication takes place, there may be a clustering of events per partition and a noticeable bias for a given partition or subset of partitions. +This example makes use of the `ReadEvents` method of the `EventHubConsumerClient`, which allows it to see events from all [partitions](https://learn.microsoft.com/azure/event-hubs/event-hubs-features#partitions) of an Event Hub. While this is convenient to use for exploration, we strongly recommend not using it for production scenarios. `ReadEvents` does not guarantee fairness amongst the partitions during iteration; each of the partitions compete to publish events to be read. Depending on how service communication takes place, there may be a clustering of events per partition and a noticeable bias for a given partition or subset of partitions. -To read from all partitions in a production application, we recommend preferring the [EventProcessorClient](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples) or a custom [EventProcessor](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.primitives.eventprocessor-1?view=azure-dotnet) implementation. \ No newline at end of file +To read from all partitions in a production application, we recommend preferring the [EventProcessorClient](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples) or a custom [EventProcessor](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.primitives.eventprocessor-1?view=azure-dotnet) implementation. diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample02_EventHubsClients.md b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample02_EventHubsClients.md index f5f70c1d665f6..6dde7dbb860ae 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample02_EventHubsClients.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample02_EventHubsClients.md @@ -20,25 +20,25 @@ This sample details the client types available for the Event Hubs client library ## Hierarchy -Because each client provides the developer experience for an area of Event Hubs functionality, to provide the best experience, it is important that it offers an API focused on a concrete set of scenarios. Because applications have different needs, we wanted to offer support for more specialized scenarios without introducing additional complexity to the more common scenarios. To achieve this, the client hierarchy was designed to align with two general categories, mainstream and specialized. +Because each client provides the developer experience for an area of Event Hubs functionality, to provide the best experience, it is important that it offers an API focused on a concrete set of scenarios. Because applications have different needs, we wanted to offer support for more specialized scenarios without introducing additional complexity to the more common scenarios. To achieve this, the client hierarchy was designed to align with two general categories, mainstream and specialized. The mainstream set of clients provides an approachable onboarding experience for those new to Event Hubs with a clear step-up path to production use for the most common application scenarios. The specialized set of clients is focused on high-throughput and allowing developers to assert a higher degree of control, at the cost of more complexity in their use. This section will briefly introduce the clients in both categories, though samples will continue to focus heavily on the mainstream clients. **Mainstream** -- The [EventHubBufferedProducerClient](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.producer?view=azure-dotnet) publishes events using a deferred model where events are collected into a buffer and the producer has responsibility for implicitly batching and sending them. More on the design and philosophy behind this type can be found in its [design document](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs/design/proposal-event-hub-buffered-producer.md). +- The [EventHubBufferedProducerClient](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.producer?view=azure-dotnet) publishes events using a deferred model where events are collected into a buffer and the producer has responsibility for implicitly batching and sending them. More on the design and philosophy behind this type can be found in its [design document](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs/design/proposal-event-hub-buffered-producer.md). -- The [EventHubProducerClient](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.producer.eventhubproducerclient?view=azure-dotnet) publishes events with explicit model where callers have responsibility for management of batches and controlling when events are sent. - -- The [EventHubConsumerClient](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.consumer.eventhubconsumerclient?view=azure-dotnet) supports reading events from a single partition and also offers an easy way to familiarize yourself with Event Hubs by reading from all partitions without the rigor and complexity that you would need in a production application. For reading events from all partitions in a production scenario, we strongly recommend using the [EventProcessorClient](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples) from the [Azure.Messaging.EventHubs.Processor](https://www.nuget.org/packages/Azure.Messaging.EventHubs.Processor) package over the `EventHubConsumerClient`. +- The [EventHubProducerClient](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.producer.eventhubproducerclient?view=azure-dotnet) publishes events with explicit model where callers have responsibility for management of batches and controlling when events are sent. + +- The [EventHubConsumerClient](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.consumer.eventhubconsumerclient?view=azure-dotnet) supports reading events from a single partition and also offers an easy way to familiarize yourself with Event Hubs by reading from all partitions without the rigor and complexity that you would need in a production application. For reading events from all partitions in a production scenario, we strongly recommend using the [EventProcessorClient](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples) from the [Azure.Messaging.EventHubs.Processor](https://www.nuget.org/packages/Azure.Messaging.EventHubs.Processor) package over the `EventHubConsumerClient`. **Specialized** -- The [PartitionReceiver](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.primitives.partitionreceiver?view=azure-dotnet) is responsible for reading events from a specific partition of an Event Hub, with a greater level of control over communication with the Event Hubs service than is offered by other event consumers. More detail on the design and philosophy for the `PartitionReceiver` can be found in its [design document](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs/design/proposal-partition-receiver.md). +- The [PartitionReceiver](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.primitives.partitionreceiver?view=azure-dotnet) is responsible for reading events from a specific partition of an Event Hub, with a greater level of control over communication with the Event Hubs service than is offered by other event consumers. More detail on the design and philosophy for the `PartitionReceiver` can be found in its [design document](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs/design/proposal-partition-receiver.md). -- The [PluggableCheckpointStoreEventProcessor<TPartition>](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.primitives.PluggableCheckpointStoreEventProcessor-1?view=azure-dotnet) provides a base for creating a custom processor for reading and processing events from all partitions of an Event Hub, using the provided checkpoint store for state persistence. It fills a role similar to the [EventProcessorClient](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples) from the [Azure.Messaging.EventHubs.Processor](https://www.nuget.org/packages/Azure.Messaging.EventHubs.Processor) package, with cooperative load balancing and resiliency as its core features. However, `PluggableCheckpointStoreEventProcessor` also offers native batch processing, a greater level of control over communication with the Event Hubs service, and a less opinionated API. The caveat is that this comes with additional complexity and exists as an abstract base, which needs to be extended. +- The [PluggableCheckpointStoreEventProcessor<TPartition>](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.primitives.PluggableCheckpointStoreEventProcessor-1?view=azure-dotnet) provides a base for creating a custom processor for reading and processing events from all partitions of an Event Hub, using the provided checkpoint store for state persistence. It fills a role similar to the [EventProcessorClient](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples) from the [Azure.Messaging.EventHubs.Processor](https://www.nuget.org/packages/Azure.Messaging.EventHubs.Processor) package, with cooperative load balancing and resiliency as its core features. However, `PluggableCheckpointStoreEventProcessor` also offers native batch processing, a greater level of control over communication with the Event Hubs service, and a less opinionated API. The caveat is that this comes with additional complexity and exists as an abstract base, which needs to be extended. -- The [EventProcessor<TPartition>](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.primitives.eventprocessor-1?view=azure-dotnet) is our lowest-level base for creating a custom processor allowing the greatest degree of customizability. It fills a role similar to the [PluggableCheckpointStoreEventProcessor<TPartition>](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.primitives.PluggableCheckpointStoreEventProcessor-1?view=azure-dotnet), with cooperative load balancing, resiliency, and batch processing as its core features. However, `EventProcessor` also provides the ability to customize checkpoint storage, including using different stores for ownership and checkpoint data. `EventProcessor` exists as an abstract base, which needs to be extended. More on the design and philosophy behind this type can be found in its [design document](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs/design/proposal-event-processor%7BT%7D.md). +- The [EventProcessor<TPartition>](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.primitives.eventprocessor-1?view=azure-dotnet) is our lowest-level base for creating a custom processor allowing the greatest degree of customizability. It fills a role similar to the [PluggableCheckpointStoreEventProcessor<TPartition>](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.primitives.PluggableCheckpointStoreEventProcessor-1?view=azure-dotnet), with cooperative load balancing, resiliency, and batch processing as its core features. However, `EventProcessor` also provides the ability to customize checkpoint storage, including using different stores for ownership and checkpoint data. `EventProcessor` exists as an abstract base, which needs to be extended. More on the design and philosophy behind this type can be found in its [design document](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs/design/proposal-event-processor%7BT%7D.md). ## Lifetime @@ -48,15 +48,16 @@ Each of the Event Hubs client types is safe to cache and use as a singleton for Each of the Event Hubs client types in the library supports a set of options to configure its behavior. In addition to influencing a client's area of functionality, the options also support configuration common across all areas. These common options are focused on communication with the Event Hubs service and core functionality; they appear as members of the client options. -### Using web sockets +### Using web sockets Communication with the Event Hubs service can be configured by adjusting the `EventHubConfigurationOptions` that are exposed by the `ConnectionOptions` member of a client options type. By default, the Event Hubs clients communicate using the AMQP protocol over TCP. Some application host environments prefer to restrict raw TCP socket use, especially in many enterprise or VPN scenarios. In these environments, or when a proxy is in use, communication with the Event Hubs service can make use of web sockets by configuring the client's connection settings. For illustration, the `EventHubProducerClientOptions` are demonstrated, but the concept and form are common across the client options types. ```C# Snippet:EventHubs_Sample02_ProducerTransportFullConnectionOptions -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var producerOptions = new EventHubProducerClientOptions { @@ -67,34 +68,38 @@ var producerOptions = new EventHubProducerClientOptions }; var producer = new EventHubProducerClient( - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, producerOptions); ``` The connection options are populated by default; you may set just the desired properties rather than creating a new instance, if you prefer. ```C# Snippet:EventHubs_Sample02_ProducerTransportProperty -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var producerOptions = new EventHubProducerClientOptions(); producerOptions.ConnectionOptions.TransportType = EventHubsTransportType.AmqpWebSockets; var producer = new EventHubProducerClient( - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, producerOptions); ``` ### Setting a custom proxy -A common scenario for adjusting the connection options is configuring a proxy. Proxy support takes the form of the [IWebProxy](https://docs.microsoft.com/dotnet/api/system.net.iwebproxy?view=netcore-3.1) interface, of which [WebProxy](https://docs.microsoft.com/dotnet/api/system.net.webproxy?view=netcore-3.1) is the most common default implementation. Event Hubs supports a proxy only when using `AmqpWebSockets` as the transport type. +A common scenario for adjusting the connection options is configuring a proxy. Proxy support takes the form of the [IWebProxy](https://learn.microsoft.com/dotnet/api/system.net.iwebproxy?view=netcore-3.1) interface, of which [WebProxy](https://learn.microsoft.com/dotnet/api/system.net.webproxy?view=netcore-3.1) is the most common default implementation. Event Hubs supports a proxy only when using `AmqpWebSockets` as the transport type. For illustration, the `EventHubProducerClientOptions` are demonstrated, but the concept and form are common across the client options types. ```C# Snippet:EventHubs_Sample02_ProducerProxyFullConnectionOptions -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var producerOptions = new EventHubProducerClientOptions { @@ -106,30 +111,33 @@ var producerOptions = new EventHubProducerClientOptions }; var producer = new EventHubProducerClient( - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, producerOptions); ``` The connection options are populated by default; you may set just the desired properties rather than creating a new instance, if you prefer. ```C# Snippet:EventHubs_Sample02_ProducerProxyProperty -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var producerOptions = new EventHubProducerClientOptions(); producerOptions.ConnectionOptions.TransportType = EventHubsTransportType.AmqpWebSockets; producerOptions.ConnectionOptions.Proxy = new WebProxy("https://proxyserver:80", true); var producer = new EventHubProducerClient( - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, producerOptions); ``` ### Using the default system proxy -To use the default proxy for your environment, the recommended approach is to make use of [HttpClient.DefaultProxy](https://docs.microsoft.com/dotnet/api/system.net.http.httpclient.defaultproxy?view=netcore-3.1), which will attempt to detect proxy settings from the ambient environment in a manner consistent with expectations for the target platform. Unfortunately, this member was added for .NET Core 3.1 and is not supported for earlier target frameworks. +To use the default proxy for your environment, the recommended approach is to make use of [HttpClient.DefaultProxy](https://learn.microsoft.com/dotnet/api/system.net.http.httpclient.defaultproxy?view=netcore-3.1), which will attempt to detect proxy settings from the ambient environment in a manner consistent with expectations for the target platform. Unfortunately, this member was added for .NET Core 3.1 and is not supported for earlier target frameworks. ```C# Snippet:EventHubs_Sample02_ConnectionOptionsDefaultProxy var options = new EventHubConnectionOptions @@ -146,27 +154,30 @@ Connections to the Azure Event Hubs service are made using the fully qualified n Some environments using unconventional proxy configurations or with certain configurations of an Express Route circuit require a custom address be used for proper routing, leaving are unable to connect from their on-premises network to the Event Hubs service using the assigned endpoint address. To support these scenarios, a custom endpoint address may be specified as part of the connection options. This custom address will take precedence for establishing the connection to the Event Hubs service. ```C# Snippet:EventHubs_Sample02_ConnectionOptionsCustomEndpoint -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var producerOptions = new EventHubProducerClientOptions(); producerOptions.ConnectionOptions.CustomEndpointAddress = new Uri("amqps://app-gateway.mycompany.com"); var producer = new EventHubProducerClient( - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, producerOptions); ``` ### Influencing SSL certificate validation -For some environments using a proxy or custom gateway for routing traffic to Event Hubs, a certificate not trusted by the root certificate authorities may be issued. This can often be a self-signed certificate from the gateway or one issued by a company's internal certificate authority. +For some environments using a proxy or custom gateway for routing traffic to Event Hubs, a certificate not trusted by the root certificate authorities may be issued. This can often be a self-signed certificate from the gateway or one issued by a company's internal certificate authority. -By default, these certificates are not trusted by the Event Hubs client library and the connection will be refused. To enable these scenarios, a [RemoteCertificateValidationCallback](https://docs.microsoft.com/dotnet/api/system.net.security.remotecertificatevalidationcallback) can be registered to provide custom validation logic for remote certificates. This allows an application to override the default trust decision and assert responsibility for accepting or rejecting the certificate. +By default, these certificates are not trusted by the Event Hubs client library and the connection will be refused. To enable these scenarios, a [RemoteCertificateValidationCallback](https://learn.microsoft.com/dotnet/api/system.net.security.remotecertificatevalidationcallback) can be registered to provide custom validation logic for remote certificates. This allows an application to override the default trust decision and assert responsibility for accepting or rejecting the certificate. ```C# Snippet:EventHubs_Sample02_RemoteCertificateValidationCallback -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); static bool ValidateServerCertificate( object sender, @@ -189,8 +200,9 @@ var producerOptions = new EventHubProducerClientOptions(); producerOptions.ConnectionOptions.CertificateValidationCallback = ValidateServerCertificate; var producer = new EventHubProducerClient( - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, producerOptions); ``` @@ -201,8 +213,9 @@ The built-in retry policy offers an implementation for an exponential back-off s The values used as thresholds for the different aspects of these strategies can be configured by adjusting the `EventHubsRetryOptions` that are exposed by the `RetryOptions` member of a client options type. For illustration, the `EventHubConsumerClientOptions` are demonstrated, but the concept and form are common across the client options types. ```C# Snippet:EventHubs_Sample02_ConsumerRetryWithFullOptions -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumerOptions = new EventHubConsumerClientOptions @@ -218,16 +231,18 @@ var consumerOptions = new EventHubConsumerClientOptions var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, consumerOptions); ``` The retry options are populated by default; you may set just the desired properties rather than creating a new instance, if you prefer. ```C# Snippet:EventHubs_Sample02_ConsumerRetryByProperty -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumerOptions = new EventHubConsumerClientOptions(); @@ -236,8 +251,9 @@ consumerOptions.RetryOptions.MaximumRetries = 5; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, consumerOptions); ``` @@ -288,4 +304,4 @@ var options = new EventHubsRetryOptions { CustomRetryPolicy = new ExampleRetryPolicy() }; -``` \ No newline at end of file +``` diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample03_EventHubMetadata.md b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample03_EventHubMetadata.md index 198b62bb51ac2..85759f4524b03 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample03_EventHubMetadata.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample03_EventHubMetadata.md @@ -11,7 +11,7 @@ This sample discusses the metadata available for an Event Hub instance and demon # Client types -Querying and inspecting metadata is a common scenario when publishing and reading events. As a result, the core operations are available to the `EventHubProducerClient` and `EventHubConsumerClient`. +Querying and inspecting metadata is a common scenario when publishing and reading events. As a result, the core operations are available to the `EventHubProducerClient` and `EventHubConsumerClient`. Both the `EventHubProducerClient` and `EventHubConsumerClient` are safe to cache and use for the lifetime of an application, which is best practice when the application publishes or reads events regularly or semi-regularly. The clients are responsible for efficient resource management, working to keep resource usage low during periods of inactivity and manage health during periods of higher use. Calling either the `CloseAsync` or `DisposeAsync` method on a client as the application is shutting down will ensure that network resources and other unmanaged objects are properly cleaned up. @@ -20,10 +20,14 @@ Both the `EventHubProducerClient` and `EventHubConsumerClient` are safe to cache Because the Event Hubs clients operate on a specific Event Hub, it is often helpful for them to have knowledge of its context. In particular, it is common for clients to understand the partitions available. The ability to query the Event Hub properties is available using the `EventHubProducerClient` and `EventHubConsumerClient`. For illustration, the `EventHubProducerClient` is demonstrated, but the concept and form are common across both clients. ```C# Snippet:EventHubs_Sample03_InspectHub -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -45,10 +49,14 @@ finally Due to their importance, there is also a shorthand way to query the partitions of an Event Hub. This capability is available using the `EventHubProducerClient` and `EventHubConsumerClient`. For illustration, the `EventHubProducerClient` is demonstrated, but the concept and form are common across both clients. ```C# Snippet:EventHubs_Sample03_QueryPartitions -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -70,11 +78,16 @@ This query is useful for occasionally inspecting partitions, but should not be u For illustration, the `EventHubConsumerClient` is demonstrated, but the concept and form are common across both clients. ```C# Snippet:EventHubs_Sample03_InspectPartition -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; -var consumer = new EventHubConsumerClient(consumerGroup, connectionString, eventHubName); +var consumer = new EventHubConsumerClient( + consumerGroup, + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -94,4 +107,4 @@ finally { await consumer.CloseAsync(); } -``` \ No newline at end of file +``` diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample04_PublishingEvents.md b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample04_PublishingEvents.md index 523c0d66d6f7b..94ca65f799719 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample04_PublishingEvents.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample04_PublishingEvents.md @@ -33,11 +33,11 @@ The `EventHubBufferedProducerClient` aims to reduce complexity by owning the res ## Event lifetime -When events are published, they will continue to exist in the Event Hub and be available for consuming until they reach an age where they are older than the [retention period](https://docs.microsoft.com//azure/event-hubs/event-hubs-faq#what-is-the-maximum-retention-period-for-events). After that point in time, the Event Hubs service may chose to remove them from the partition. Once removed, an event is no longer available to be read and cannot be recovered. Though the Event Hubs service is free to remove events older than the retention period, it does not do so deterministically; there is no guarantee of when events will be removed. +When events are published, they will continue to exist in the Event Hub and be available for consuming until they reach an age where they are older than the [retention period](https://learn.microsoft.com//azure/event-hubs/event-hubs-faq#what-is-the-maximum-retention-period-for-events). After that point in time, the Event Hubs service may chose to remove them from the partition. Once removed, an event is no longer available to be read and cannot be recovered. Though the Event Hubs service is free to remove events older than the retention period, it does not do so deterministically; there is no guarantee of when events will be removed. ## Publishing size constraints -There is a limit to the size (in bytes) that can be published in a single operation. To accurately determine the size of an event, it must be measured in the format used by the active protocol in order to properly account for overhead. The size limit is controlled by the Event Hubs service and differs for different types of Event Hub instances. +There is a limit to the size (in bytes) that can be published in a single operation. To accurately determine the size of an event, it must be measured in the format used by the active protocol in order to properly account for overhead. The size limit is controlled by the Event Hubs service and differs for different types of Event Hub instances. Applications using the `EventHubBufferedProducerClient` do not need to track size limitations; the producer will ensure that batches are correctly sized when publishing. @@ -50,10 +50,14 @@ All of the events that belong to an `EventDataBatch` are considered part of a si To create an `EventDataBatch`, the `EventProducerClient` must be used, as the size limit is queried from the Event Hubs service the first time that a batch is created. After the size has been queried once, batch creation will not incur the cost of a service request. The `EventDataBatch` follows a `TryAdd` pattern; if the call returns `true` then the event was accepted into the batch. If not, then the event was unable to fit. To avoid accidentally losing events, it is recommended to check the return value when adding events. ```C# Snippet:EventHubs_Sample04_EventBatch -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -76,7 +80,7 @@ The `EventDataBatch` is scoped to a single publish operation. Once that operati ## Publishing and partitions -Every event that is published is sent to one of the [partitions](https://docs.microsoft.com/azure/architecture/reference-architectures/event-hubs/partitioning-in-event-hubs-and-kafka) of the Event Hub. The application may request publishing to a specific partition, grouped using a partition key, or allow the partition to be chosen automatically. +Every event that is published is sent to one of the [partitions](https://learn.microsoft.com/azure/architecture/reference-architectures/event-hubs/partitioning-in-event-hubs-and-kafka) of the Event Hub. The application may request publishing to a specific partition, grouped using a partition key, or allow the partition to be chosen automatically. When using the `EventHubProducerClient`, each batch must choose the partition assignment strategy at the time it is created, and that strategy is applied to all events in the batch. The `EventHubBufferedProducerClient` allows the partition assignment strategy to be chosen for each individual event that is enqueued, and the producer will ensure that batches are constructed with the proper strategy. @@ -89,10 +93,14 @@ Allowing automatic assignment to partitions is recommended when publishing needs When using the `EventHubBufferedProducerClient`, events enqueued with no options specified will be automatically routed. Because the producer manages publishing, there is no explicit call. When the producer is closed, it will ensure that any remaining enqueued events have been published. All of your event data will be published to one of the Event Hub partitions, though there may be a slight delay until it is available to be read. ```C# Snippet:EventHubs_Sample04_AutomaticRoutingBuffered -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubBufferedProducerClient(connectionString, eventHubName); +var producer = new EventHubBufferedProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); // The failure handler is required and invoked after all allowable // retries were applied. @@ -133,10 +141,14 @@ finally When using the `EventHubProducerClient` a batch is first created and then published. The `SendAsync` call will receive an acknowledgment from the Event Hubs service; so long as no exception is thrown, your application can consider publishing successful. All of your event data will be published to one of the Event Hub partitions, though there may be a slight delay until it is available to be read. ```C# Snippet:EventHubs_Sample04_AutomaticRouting -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -163,7 +175,7 @@ finally ## Publishing events with a partition key When publishing events, it may be desirable to request that the Event Hubs service keep the different event batches together on the same partition. This can be accomplished by setting a partition key when creating the batch. The partition key is NOT the identifier of a specific partition. Rather, it is an arbitrary piece of string data that Event Hubs uses as the basis to compute a hash value. Event Hubs will associate the hash value with a specific partition, ensuring that any events published with the same partition key are routed to the same partition. - + There is no means of predicting which partition will be associated with a given partition key; we can only be assured that it will be a consistent choice of partition. If you have a need to understand which exact partition an event is published to, you will need to specify the partition directly rather than using a partition key. ### Event Hub Buffered Producer Client @@ -173,10 +185,14 @@ When using the `EventHubBufferedProducerClient`, events are enqueued with a part **Note:** It is important to be aware that if you are using a partition key, you may not also specify a partition identifier; they are mutually exclusive. ```C# Snippet:EventHubs_Sample04_PartitionKeyBuffered -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubBufferedProducerClient(connectionString, eventHubName); +var producer = new EventHubBufferedProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); // The failure handler is required and invoked after all allowable // retries were applied. @@ -224,10 +240,14 @@ When using the `EventHubProducerClient` a batch is first created with a partitio **Note:** It is important to be aware that if you are using a partition key, you may not also specify a partition identifier; they are mutually exclusive. ```C# Snippet:EventHubs_Sample04_PartitionKey -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -258,7 +278,7 @@ finally ## Publishing events to a specific partition -When publishing, it may be desirable to request that the Event Hubs service place a batch on a specific partition, for organization and processing. For example, you may have designated one partition of your Event Hub as being responsible for all of your telemetry-related events. This can be accomplished by setting the identifier of the desired partition when creating the batch. +When publishing, it may be desirable to request that the Event Hubs service place a batch on a specific partition, for organization and processing. For example, you may have designated one partition of your Event Hub as being responsible for all of your telemetry-related events. This can be accomplished by setting the identifier of the desired partition when creating the batch. ### Event Hub Buffered Producer Client @@ -267,10 +287,14 @@ When using the `EventHubBufferedProducerClient`, events are enqueued with a part **Note:** It is important to be aware that if you are using a partition key, you may not also specify a partition identifier; they are mutually exclusive. ```C# Snippet:EventHubs_Sample04_PartitionIdBuffered -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubBufferedProducerClient(connectionString, eventHubName); +var producer = new EventHubBufferedProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); // The failure handler is required and invoked after all allowable // retries were applied. @@ -320,10 +344,14 @@ When using the `EventHubProducerClient` a batch is first created with a partitio **Note:** It is important to be aware that if you are using a partition identifier, you may not also specify a partition key; they are mutually exclusive. ```C# Snippet:EventHubs_Sample04_PartitionId -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -361,10 +389,14 @@ Because an event consists mainly of an opaque set of bytes, it may be difficult This metadata is not used by, or in any way meaningful to, the Event Hubs service; it exists only for coordination between event publishers and consumers. ```C# Snippet:EventHubs_Sample04_CustomMetadata -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubBufferedProducerClient(connectionString, eventHubName); +var producer = new EventHubBufferedProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); // The failure handler is required and invoked after all allowable // retries were applied. @@ -426,15 +458,15 @@ It is also important that you guard against exceptions in your handler code; it ## Tuning throughput for buffered publishing -To ensure consistent performance and throughput, it is common for applications to make decisions around the pattern of publishing that they use - adjusting the frequency that batches are sent and how many operations take place concurrently. Because the `EventHubBufferedProducerClient` manages batches and publishing in the background, your application cannot directly control these aspects. +To ensure consistent performance and throughput, it is common for applications to make decisions around the pattern of publishing that they use - adjusting the frequency that batches are sent and how many operations take place concurrently. Because the `EventHubBufferedProducerClient` manages batches and publishing in the background, your application cannot directly control these aspects. Because the handlers are awaited, it is strongly advised that you *not* invoke `CloseAsync` or `DisposeAsync` from the handlers; doing so is likely to result in a deadlock scenario. It is safe to attempt to resend events by adding them to the back of the buffer by calling `EnqueueEventAsync` or `EnqueueEventsAsync` -By default, the `EventHubBufferedProducerClient` uses a set of values that will perform well for general-case scenarios, balancing consistent performance with ensuring that the order of events is maintained. In the case where your application has different needs, it can provide a set of options when constructing the producer that will influence publishing behavior and help ensure that it is optimal for your specific scenarios. +By default, the `EventHubBufferedProducerClient` uses a set of values that will perform well for general-case scenarios, balancing consistent performance with ensuring that the order of events is maintained. In the case where your application has different needs, it can provide a set of options when constructing the producer that will influence publishing behavior and help ensure that it is optimal for your specific scenarios. The performance-related settings are: -- **MaximumWaitTime**: This is the longest that the producer will wait for a batch to be full before publishing. For applications that publish frequently, waiting longer for a full batch may improve efficiency. For applications that publish infrequently or sporadically, a lower value will ensure that events are not held in buffer waiting. The default wait time is 1 second. +- **MaximumWaitTime**: This is the longest that the producer will wait for a batch to be full before publishing. For applications that publish frequently, waiting longer for a full batch may improve efficiency. For applications that publish infrequently or sporadically, a lower value will ensure that events are not held in buffer waiting. The default wait time is 1 second. - **MaximumConcurrentSends**: The number of concurrent `SendAsync` calls that the producer will make. Each call is a network request that publishes a single batch. A higher degree of concurrency can improve throughput for applications that use an Event Hub with a large number of partitions. Because the producer is highly asynchronous and is running background tasks, we recommend being careful when selecting a value to avoid creating contention in the thread pool. Testing under normal load is essential. The default concurrency is equal to the number of cores in the host environment. @@ -442,13 +474,14 @@ The performance-related settings are: - **MaximumEventBufferLengthPerPartition**: The maximum number of events that can be buffered for each individual partition. This is intended to ensure that your application does not run out of memory if buffering happens more frequently than events can be published. When this limit is reached, your application can continue to call `EnqueueEventAsync` or `EnqueueEventsAsync` without an error; the call will block until space is available. For applications that publish a high number of smaller-sized events, increasing this limit may help to improve throughput. For scenarios where the application is buffering large events and needs to control memory use, lowering this limit may be helpful. The default buffer length is 1500 events per partition. -- **EnableIdempotentRetries**: Indicates whether or not events should be published using idempotent semantics for retries. If enabled, retries during publishing will attempt to avoid duplication with a small cost to overall performance and throughput. +- **EnableIdempotentRetries**: Indicates whether or not events should be published using idempotent semantics for retries. If enabled, retries during publishing will attempt to avoid duplication with a small cost to overall performance and throughput. **_NOTE:_** Enabling idempotent retries does not guarantee exactly-once semantics. The Event Hubs at-least-once delivery contract still applies; duplicates are still possible but the chance of them occurring is much lower when idempotent retries are enabled. ```C# Snippet:EventHubs_Sample04_BufferedConfiguration -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var options = new EventHubBufferedProducerClientOptions { @@ -459,7 +492,11 @@ var options = new EventHubBufferedProducerClientOptions EnableIdempotentRetries = true }; -var producer = new EventHubBufferedProducerClient(connectionString, eventHubName, options); +var producer = new EventHubBufferedProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential, + options); // The failure handler is required and invoked after all allowable // retries were applied. @@ -497,17 +534,22 @@ finally ## Creating and publishing multiple batches -Because an `EventDataBatch` is scoped to a single publish operation, it is often necessary to more than a single batch to publish events. This can take many forms, with varying levels of sophistication and complexity, depending on an application's needs. One common approach is to stage the events to be published in a `Queue` and use that as a source for building batches. +Because an `EventDataBatch` is scoped to a single publish operation, it is often necessary to more than a single batch to publish events. This can take many forms, with varying levels of sophistication and complexity, depending on an application's needs. One common approach is to stage the events to be published in a `Queue` and use that as a source for building batches. The following illustration breaks the process into discrete steps, transforming the queue of events into a set of batches to be published. This is done to help isolate the logic of creating batches for readability. Production applications may wish to publish batches as they become full to make more efficient use of resources. **Note:** The batch is responsible for unmanaged resources; it is recommended that you `Dispose` the batch after it has been published. ```C# Snippet:EventHubs_Sample04_MultipleBatches -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); + +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); -var producer = new EventHubProducerClient(connectionString, eventHubName); var batches = default(IEnumerable); var eventsToSend = new Queue(); @@ -576,17 +618,21 @@ private static async Task> BuildBatchesAsync( ## Publishing events with an implicit batch -In scenarios where an application using the `EventProducerClient` wishes to publish events more frequently and is not concerned with exceeding the size limitation, it is reasonable to bypass the safety offered by using the `EventDataBatch` to offer minor throughput gains and fewer memory allocations. In support of this scenario, the `EventProducerClient` offers a `SendAsync` overload that accepts a set of events. This method delegates validation to the Event Hubs service to avoid the performance cost of a client-side measurement. If the set of events that was published exceeds the size limit, an [EventHubsException](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventhubsexception?view=azure-dotnet) will be surfaced with its `Reason` set to [MessageSizeExceeded](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventhubsexception.failurereason?view=azure-dotnet). +In scenarios where an application using the `EventProducerClient` wishes to publish events more frequently and is not concerned with exceeding the size limitation, it is reasonable to bypass the safety offered by using the `EventDataBatch` to offer minor throughput gains and fewer memory allocations. In support of this scenario, the `EventProducerClient` offers a `SendAsync` overload that accepts a set of events. This method delegates validation to the Event Hubs service to avoid the performance cost of a client-side measurement. If the set of events that was published exceeds the size limit, an [EventHubsException](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventhubsexception?view=azure-dotnet) will be surfaced with its `Reason` set to [MessageSizeExceeded](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.eventhubsexception.failurereason?view=azure-dotnet). When events are passed in this form, the `EventProducerClient` will package them as a single publishing operation. When the set is published, the result is atomic; either publishing was successful for all events, or it has failed for all events. Partial success or failure when publishing a batch is not possible. When published, the `EventHubProducerClient` will receive an acknowledgment from the Event Hubs service; so long as no exception is thrown by this call, your application can consider publishing successful. The service assumes responsibility for delivery of the set. All of your event data will be published to one of the Event Hub partitions, though there may be a slight delay until it is available to be read. ```C# Snippet:EventHubs_Sample04_NoBatch -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -611,10 +657,14 @@ finally In some scenarios, such as when bandwidth is limited or publishers need to maintain control over how much data is transmitted at a time, a custom size limit (in bytes) may be specified when creating an `EventDataBatch`. This will override the default limit specified by the Event Hub and allows an application to use the `EventDataBatch` to ensure that the size of events can be measured accurately and deterministically. It is important to note that the custom limit may not exceed the limit specified by the Event Hub. ```C# Snippet:EventHubs_Sample04_CustomBatchSize -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -641,4 +691,4 @@ finally { await producer.CloseAsync(); } -``` \ No newline at end of file +``` diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample05_ReadingEvents.md b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample05_ReadingEvents.md index 445232b74daf3..7350b783ebd02 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample05_ReadingEvents.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample05_ReadingEvents.md @@ -27,37 +27,39 @@ Each of the event consumer client types are safe to cache and use for the lifeti ## Event lifetime -When events are published, they will continue to exist in the Event Hub and be available for consuming until they reach an age where they are older than the [retention period](https://docs.microsoft.com//azure/event-hubs/event-hubs-faq#what-is-the-maximum-retention-period-for-events). After that point in time, the Event Hubs service may chose to remove them from the partition. Once removed, an event is no longer available to be read and cannot be recovered. Though the Event Hubs service is free to remove events older than the retention period, it does not do so deterministically; there is no guarantee of when events will be removed. +When events are published, they will continue to exist in the Event Hub and be available for consuming until they reach an age where they are older than the [retention period](https://learn.microsoft.com//azure/event-hubs/event-hubs-faq#what-is-the-maximum-retention-period-for-events). After that point in time, the Event Hubs service may chose to remove them from the partition. Once removed, an event is no longer available to be read and cannot be recovered. Though the Event Hubs service is free to remove events older than the retention period, it does not do so deterministically; there is no guarantee of when events will be removed. ## Reading and consumer groups -An Event Hub consumer is associated with a specific Event Hub and [consumer group](https://docs.microsoft.com/azure/event-hubs/event-hubs-features#consumer-groups). Conceptually, the consumer group is a label that identifies one or more event consumers as a set. Often, consumer groups are named after the responsibility of the consumer in an application, such as "Telemetry" or "OrderProcessing". When an Event Hub is created, a default consumer group is created for it, named "$Default." These examples will make use of the default consumer group for illustration. +An Event Hub consumer is associated with a specific Event Hub and [consumer group](https://learn.microsoft.com/azure/event-hubs/event-hubs-features#consumer-groups). Conceptually, the consumer group is a label that identifies one or more event consumers as a set. Often, consumer groups are named after the responsibility of the consumer in an application, such as "Telemetry" or "OrderProcessing". When an Event Hub is created, a default consumer group is created for it, named "$Default." These examples will make use of the default consumer group for illustration. Each consumer has a unique view of the events in a partition that it reads from, which means that events are available to all consumers and are not removed from the partition when read. This allows consumers to read and process events from the Event Hub at different speeds without interfering with one another. ## Reading and partitions -Every event that is published is sent to one of the [partitions](https://docs.microsoft.com/azure/architecture/reference-architectures/event-hubs/partitioning-in-event-hubs-and-kafka) of the Event Hub. When reading events, an application may be interested in reading events from all partitions or limiting to a single partition, depending on the application scenarios and throughput needs. The `EventHubConsumerClient` is not associated with any specific partition and the same instance can be used for reading from multiple partitions. +Every event that is published is sent to one of the [partitions](https://learn.microsoft.com/azure/architecture/reference-architectures/event-hubs/partitioning-in-event-hubs-and-kafka) of the Event Hub. When reading events, an application may be interested in reading events from all partitions or limiting to a single partition, depending on the application scenarios and throughput needs. The `EventHubConsumerClient` is not associated with any specific partition and the same instance can be used for reading from multiple partitions. The `EventHubConsumerClient` supports reading events from a single partition and also offers an easy way to familiarize yourself with Event Hubs by reading from all partitions without the rigor and complexity that you would need in a production application. For reading events from all partitions in a production scenario, we strongly recommend using the [EventProcessorClient](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs.Processor/samples) from the [Azure.Messaging.EventHubs.Processor](https://www.nuget.org/packages/Azure.Messaging.EventHubs.Processor) package over the `EventHubConsumerClient`. ## Read events from all partitions -The `ReadEventsAsync` method of the `EventHubConsumerClient` allows events to be read from each partition for prototyping and exploring, but is not a recommended approach for production scenarios. Events are consumed as an [Async Enumerable](https://docs.microsoft.com/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8), where enumeration will emit events one-by-one. By default, reading starts from the beginning of partitions and all events present will be surfaced. +The `ReadEventsAsync` method of the `EventHubConsumerClient` allows events to be read from each partition for prototyping and exploring, but is not a recommended approach for production scenarios. Events are consumed as an [Async Enumerable](https://learn.microsoft.com/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8), where enumeration will emit events one-by-one. By default, reading starts from the beginning of partitions and all events present will be surfaced. -Because an Event Hub represents a potentially infinite series of events, the enumerator will not exit when no events are available in the Event Hub partitions. Instead, it will wait for more events to be published. To stop reading, applications will need to either signal a [CancellationToken](https://docs.microsoft.com/dotnet/api/system.threading.cancellationtoken?view=netcore-3.1) or call `break` from the body of the loop. +Because an Event Hub represents a potentially infinite series of events, the enumerator will not exit when no events are available in the Event Hub partitions. Instead, it will wait for more events to be published. To stop reading, applications will need to either signal a [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken?view=netcore-3.1) or call `break` from the body of the loop. This example illustrates stopping after either 3 events have been read or 45 seconds has elapsed, whichever occurs first. ```C# Snippet:EventHubs_Sample05_ReadAllPartitions -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -94,19 +96,21 @@ finally ## Read events from all partitions with a maximum wait time -When using `ReadEventAsync`, it can sometimes be advantageous to ensure that the [Async Enumerable](https://docs.microsoft.com/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8) returns control to the application's code in the loop body periodically, whether an event was available or not. This allows for the application to detect when events are no longer being published and is often used for emitting heartbeat data as a health check for consumers. +When using `ReadEventAsync`, it can sometimes be advantageous to ensure that the [Async Enumerable](https://learn.microsoft.com/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8) returns control to the application's code in the loop body periodically, whether an event was available or not. This allows for the application to detect when events are no longer being published and is often used for emitting heartbeat data as a health check for consumers. This example illustrates waiting for a maximum of one second for an event to be read; if no event was available in that time, the loop ticks with an empty `PartitionEvent`. Once the example loop has ticked a total of 10 times, with or without an event available, it will exit. ```C# Snippet:EventHubs_Sample05_ReadAllPartitionsWaitTime -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -152,14 +156,16 @@ By default, reading starts from the beginning of partitions. It is possible to This example illustrates reading from the end of each partition, and will do so for 30 seconds regardless of how many events have been read. ```C# Snippet:EventHubs_Sample05_ReadAllPartitionsFromLatest -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -189,21 +195,23 @@ finally ## Read events from a partition -The `ReadEventsFromPartitionAsync` method of the `EventHubConsumerClient` allows events to be read from a specific partition and is suitable for production scenarios. Events are consumed as an [Async Enumerable](https://docs.microsoft.com/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8), where enumeration will emit events one-by-one. `ReadEventsFromPartitionAsync` targets a single partition, allowing consumers to request reading from a specific location in the partition's event stream by creating an [EventPosition](https://docs.microsoft.com/dotnet/api/azure.messaging.eventhubs.consumer.eventposition?view=azure-dotnet). +The `ReadEventsFromPartitionAsync` method of the `EventHubConsumerClient` allows events to be read from a specific partition and is suitable for production scenarios. Events are consumed as an [Async Enumerable](https://learn.microsoft.com/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8), where enumeration will emit events one-by-one. `ReadEventsFromPartitionAsync` targets a single partition, allowing consumers to request reading from a specific location in the partition's event stream by creating an [EventPosition](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.consumer.eventposition?view=azure-dotnet). -Because an Event Hub represents a potentially infinite series of events, the enumerator will not exit when no further events are available in the Event Hub partitions. Instead, it will wait for more events to be published. To stop reading, applications will need to either signal a [CancellationToken](https://docs.microsoft.com/dotnet/api/system.threading.cancellationtoken?view=netcore-3.1) or call `break` from the body of the loop. +Because an Event Hub represents a potentially infinite series of events, the enumerator will not exit when no further events are available in the Event Hub partitions. Instead, it will wait for more events to be published. To stop reading, applications will need to either signal a [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken?view=netcore-3.1) or call `break` from the body of the loop. This example illustrates the `CancellationToken` approach, reading from the beginning of the partition for only 30 seconds, regardless of how many events are read. ```C# Snippet:EventHubs_Sample05_ReadPartition -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -237,19 +245,21 @@ finally ## Read events from a partition with a maximum wait time -When using `ReadEventsFromPartitionAsync`, it can sometimes be advantageous to ensure that the [Async Enumerable](https://docs.microsoft.com/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8) returns control to the application's code in the loop body periodically, whether an event was available or not. This allows for the application to detect when events are no longer being published and is often used for emitting heartbeat data as a health check for consumers. +When using `ReadEventsFromPartitionAsync`, it can sometimes be advantageous to ensure that the [Async Enumerable](https://learn.microsoft.com/archive/msdn-magazine/2019/november/csharp-iterating-with-async-enumerables-in-csharp-8) returns control to the application's code in the loop body periodically, whether an event was available or not. This allows for the application to detect when events are no longer being published and is often used for emitting heartbeat data as a health check for consumers. This example illustrates waiting for a maximum of one second for an event to be read; if no event was available, the loop ticks with an empty `PartitionEvent`. Once the example loop has ticked a total of 10 times, with or without an event available, it will exit. ```C# Snippet:EventHubs_Sample05_ReadPartitionWaitTime -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -308,14 +318,16 @@ finally When reading event from a partition, consumers can request to begin reading from the partition's event stream at a specific point in time. This example illustrates reading events starting with an hour prior to the current time, and will continue reading for a duration of 30 seconds before cancellation is triggered. ```C# Snippet:EventHubs_Sample05_ReadPartitionFromDate -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -356,14 +368,16 @@ When reading event from a partition, consumers can request to begin reading from This example illustrates reading events starting with the last offset that was published to the partition, and will do so for 30 seconds regardless of how many events have been read. ```C# Snippet:EventHubs_Sample05_ReadPartitionFromOffset -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -398,19 +412,21 @@ finally ## Read events from a partition, starting from a specific sequence number -When reading event from a partition, consumers can request to begin reading from the partition's event stream at a specific sequence number. This is often used when a consumer has already processed some events from the partition and would like to resume from that point rather than reprocessing. Sequence numbers follow a consistent pattern within the context of a specific partition; they will be contiguous and in increasing order. +When reading event from a partition, consumers can request to begin reading from the partition's event stream at a specific sequence number. This is often used when a consumer has already processed some events from the partition and would like to resume from that point rather than reprocessing. Sequence numbers follow a consistent pattern within the context of a specific partition; they will be contiguous and in increasing order. This example illustrates reading events starting with the last sequence number that was published to the partition, and will do so for 30 seconds regardless of how many events have been read. ```C# Snippet:EventHubs_Sample05_ReadPartitionFromSequence -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -445,21 +461,23 @@ finally ## Query partition information while reading -Some application scenarios call for understanding the "backlog" of events in an Event Hub, where an event being consumed is compared with the latest event available in the partition to understand how many events have accumulated and have yet to be processed. This allows applications to make reasoned decisions about scaling consumers or throttling publishers to ensure that event processing does not fall too far behind. +Some application scenarios call for understanding the "backlog" of events in an Event Hub, where an event being consumed is compared with the latest event available in the partition to understand how many events have accumulated and have yet to be processed. This allows applications to make reasoned decisions about scaling consumers or throttling publishers to ensure that event processing does not fall too far behind. While the `EventHubConsumerClient` can be used to directly query the partition, doing so frequently is likely to impact performance. When partition information is needed often, an option can be set when reading events to query the last published event information for the partition in real-time and surface it with events being processed. This example illustrates requesting information on the last published event for the partition while reading events. Reading will be performed for 30 seconds regardless of how many events have been read. ```C# Snippet:EventHubs_Sample05_ReadPartitionTrackLastEnqueued -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -505,12 +523,13 @@ finally When an application is working at a high volume and is willing to accept additional complexity to maximize throughput, the `PartitionReceiver` is worthy of consideration. It provides a very thin wrapper over the Event Hubs transport, allowing events to be read in batches as well as supporting options to control transport behavior. More detail on the design and philosophy for the `PartitionReceiver` can be found in its [design document](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/eventhub/Azure.Messaging.EventHubs/design/proposal-partition-receiver.md). -Because the receiver endeavors to avoid adding overhead, it does not follow the patterns established in the `EventHubConsumerClient` nor offer some of its convenience. Of particular note is that the model for reading events is based on polling with its `ReceiveBatchAsync` method instead of an iterator. It is also important to be aware that the transport library is timeout-based and will not honor cancellation when a service operation is active. +Because the receiver endeavors to avoid adding overhead, it does not follow the patterns established in the `EventHubConsumerClient` nor offer some of its convenience. Of particular note is that the model for reading events is based on polling with its `ReceiveBatchAsync` method instead of an iterator. It is also important to be aware that the transport library is timeout-based and will not honor cancellation when a service operation is active. This example illustrates the basic flow of reading events and will do so for 30 seconds regardless of how many events have been read. ```C# Snippet:EventHubs_Sample05_ReadPartitionWithReceiver -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; using CancellationTokenSource cancellationSource = new CancellationTokenSource(); @@ -518,7 +537,10 @@ cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); string firstPartition; -await using (var producer = new EventHubProducerClient(connectionString, eventHubName)) +await using (var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential)) { firstPartition = (await producer.GetPartitionIdsAsync()).First(); } @@ -527,8 +549,9 @@ var receiver = new PartitionReceiver( consumerGroup, firstPartition, EventPosition.Earliest, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample06_IdentityAndSharedAccessCredentials.md b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample06_IdentityAndSharedAccessCredentials.md index 01ab385b5b05a..6fd231158eee7 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample06_IdentityAndSharedAccessCredentials.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample06_IdentityAndSharedAccessCredentials.md @@ -23,29 +23,29 @@ Depending on the type of authorization that you wish to use, additional setup ma ### Identity authorization -**Azure.Identity** +**Azure.Identity** -The `Azure.Identity` library is recommended for identity-based authentication across the different sources supported by the Azure platform for [role-based access control (RBAC)](https://docs.microsoft.com/azure/role-based-access-control/overview). This includes Azure Active Directory principals and Managed Identities. To allow for the best developer experience, and one that supports promoting applications between environments without code changes, this sample will concentrate on the `DefaultAzureCredential`. Please see the [Azure.Identity README](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/README.md#defaultazurecredential) for details on configuring your environment for `DefaultAzureCredential` integration. +The `Azure.Identity` library is recommended for identity-based authentication across the different sources supported by the Azure platform for [role-based access control (RBAC)](https://learn.microsoft.com/azure/role-based-access-control/overview). This includes Azure Active Directory principals and Managed Identities. To allow for the best developer experience, and one that supports promoting applications between environments without code changes, this sample will concentrate on the `DefaultAzureCredential`. Please see the [Azure.Identity README](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/README.md#defaultazurecredential) for details on configuring your environment for `DefaultAzureCredential` integration. -**Role Assignments** +**Role Assignments** -Once your environment is configured, you'll need to ensure that the principal that you've chosen has access to your Event Hubs resources in Azure. To do so, they will need to be assigned the appropriate role. For those unfamiliar with role assignments, it is recommended to follow [these steps](https://docs.microsoft.com/azure/event-hubs/authenticate-managed-identity?tabs=latest#to-assign-azure-roles-using-the-azure-portal) in the Azure portal for the most intuitive experience. Roles may also be assigned via the [Azure CLI](https://docs.microsoft.com/cli/azure/role/assignment?view=azure-cli-latest#az_role_assignment_create) or [PowerShell](https://docs.microsoft.com/powershell/module/az.resources/new-azroleassignment), though these require more in-depth knowledge of the Azure platform and may be difficult for developers exploring Azure for the first time. +Once your environment is configured, you'll need to ensure that the principal that you've chosen has access to your Event Hubs resources in Azure. To do so, they will need to be assigned the appropriate role. For those unfamiliar with role assignments, it is recommended to follow [these steps](https://learn.microsoft.com/azure/event-hubs/authenticate-managed-identity?tabs=latest#to-assign-azure-roles-using-the-azure-portal) in the Azure portal for the most intuitive experience. Roles may also be assigned via the [Azure CLI](https://learn.microsoft.com/cli/azure/role/assignment?view=azure-cli-latest#az_role_assignment_create) or [PowerShell](https://learn.microsoft.com/powershell/module/az.resources/new-azroleassignment), though these require more in-depth knowledge of the Azure platform and may be difficult for developers exploring Azure for the first time. -The available role choices for Event Hubs are: +The available role choices for Event Hubs are: -- [Azure Event Hubs Data Owner](https://docs.microsoft.com/azure/role-based-access-control/built-in-roles#azure-event-hubs-data-owner) for full access to read and publish events. -- [Azure Event Hubs Data Receiver](https://docs.microsoft.com/azure/role-based-access-control/built-in-roles#azure-event-hubs-data-receiver) for the ability to read events but not publish them. -- [Azure Event Hubs Data Sender](https://docs.microsoft.com/azure/role-based-access-control/built-in-roles#azure-event-hubs-data-sender) for the ability to publish events but not read them. +- [Azure Event Hubs Data Owner](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles#azure-event-hubs-data-owner) for full access to read and publish events. +- [Azure Event Hubs Data Receiver](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles#azure-event-hubs-data-receiver) for the ability to read events but not publish them. +- [Azure Event Hubs Data Sender](https://learn.microsoft.com/azure/role-based-access-control/built-in-roles#azure-event-hubs-data-sender) for the ability to publish events but not read them. ### Event Hubs Shared Access Signature authorization Shared access signatures (SAS) are recommended over shared access keys when RBAC cannot be used. A shared access signature allows for granular and time-limited access to Event Hubs resources. In order to use SAS-based authorization, a token needs to be generated and the associated Event Hubs resource needs to be configured to authorize its use. -The steps to generate a SAS token can be found in the [example below](#generating-sas-tokens) and are detailed in the article "[Authenticate access to Event Hubs resources using shared access signatures (SAS)](https://docs.microsoft.com/azure/event-hubs/authenticate-shared-access-signature)". Details for for some additional languages are discussed in the article "[Generate SAS token](https://docs.microsoft.com/rest/api/eventhub/generate-sas-token)". Information about configuring SAS authorization can be found in the article "[Authorizing access to Event Hubs resources using Shared Access Signatures](https://docs.microsoft.com/azure/event-hubs/authorize-access-shared-access-signature)". +The steps to generate a SAS token can be found in the [example below](#generating-sas-tokens) and are detailed in the article "[Authenticate access to Event Hubs resources using shared access signatures (SAS)](https://learn.microsoft.com/azure/event-hubs/authenticate-shared-access-signature)". Details for for some additional languages are discussed in the article "[Generate SAS token](https://learn.microsoft.com/rest/api/eventhub/generate-sas-token)". Information about configuring SAS authorization can be found in the article "[Authorizing access to Event Hubs resources using Shared Access Signatures](https://learn.microsoft.com/azure/event-hubs/authorize-access-shared-access-signature)". ### Event Hubs Shared Access Key authorization -Shared access keys for Event Hubs authorization are generated when access policies are created for an Event Hubs namespace or one of its Event Hub instances. Since these keys are most often used in association with a connection string, the article "[Get an Event Hubs connection string](https://docs.microsoft.com/azure/event-hubs/event-hubs-get-connection-string#get-connection-string-from-the-portal)" is the best source of information on generating and accessing them. +Shared access keys for Event Hubs authorization are generated when access policies are created for an Event Hubs namespace or one of its Event Hub instances. Since these keys are most often used in association with a connection string, the article "[Get an Event Hubs connection string](https://learn.microsoft.com/azure/event-hubs/event-hubs-get-connection-string#get-connection-string-from-the-portal)" is the best source of information on generating and accessing them. In step 6 of the article, the policy that you select will be the name of your shared access key when used for credential authorization. In step 7, you'll want to copy the "Primary key" rather than connection string. diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample07_EarlierLanguageVersions.md b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample07_EarlierLanguageVersions.md index f63525cf3146e..b10c08f00868f 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample07_EarlierLanguageVersions.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample07_EarlierLanguageVersions.md @@ -1,25 +1,29 @@ # Using Earlier Versions of C# and Visual Studio -The Azure Event Hubs client library makes use of new features that were introduced in C# 8.0. In order to take advantage of the C# 8.0 syntax, it is recommended that you compile using the [.NET Core SDK](https://dotnet.microsoft.com/download) 3.0 or higher with a [language version](https://docs.microsoft.com/dotnet/csharp/language-reference/configure-language-version#override-a-default) of `latest`. It is also possible to compile with the .NET Core SDK 2.1.x using a language version of `preview`. +The Azure Event Hubs client library makes use of new features that were introduced in C# 8.0. In order to take advantage of the C# 8.0 syntax, it is recommended that you compile using the [.NET Core SDK](https://dotnet.microsoft.com/download) 3.0 or higher with a [language version](https://learn.microsoft.com/dotnet/csharp/language-reference/configure-language-version#override-a-default) of `latest`. It is also possible to compile with the .NET Core SDK 2.1.x using a language version of `preview`. Visual Studio users wishing to take full advantage of the C# 8.0 syntax will need to use Visual Studio 2019 or later. Visual Studio 2019, including the free Community edition, can be downloaded [here](https://visualstudio.microsoft.com). Users of Visual Studio 2017 can take advantage of the C# 8 syntax by making use of the [Microsoft.Net.Compilers NuGet package](https://www.nuget.org/packages/Microsoft.Net.Compilers/) and setting the language version, though the editing experience may not be ideal. - You can still use the Event Hubs client library with previous C# language versions, by managing asynchronous enumerable and asynchronous disposable members manually rather than benefiting from the new syntax. You may still target any framework version that can consume a `netstandard2.0` package, including earlier versions of .NET Core or the .NET framework. For more information, see the [.NET Standard](https://docs.microsoft.com/dotnet/standard/net-standard) documentation and [how to specify target frameworks](https://docs.microsoft.com/dotnet/standard/frameworks#how-to-specify-target-frameworks). - + You can still use the Event Hubs client library with previous C# language versions, by managing asynchronous enumerable and asynchronous disposable members manually rather than benefiting from the new syntax. You may still target any framework version that can consume a `netstandard2.0` package, including earlier versions of .NET Core or the .NET framework. For more information, see the [.NET Standard](https://learn.microsoft.com/dotnet/standard/net-standard) documentation and [how to specify target frameworks](https://learn.microsoft.com/dotnet/standard/frameworks#how-to-specify-target-frameworks). + ## Table of contents - [Publish a batch of events using C# 7](#publish-a-batch-of-events-using-c-7) - [Read events from all partitions using C# 7](#read-events-from-all-partitions-using-c-7) ## Publish a batch of events using C# 7 - + This example illustrates publishing a batch with a single event, allowing the Event Hubs service to assign the partition to which it will be published. For more information on publishing, see: [Sample04_PublishingEvents](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample04_PublishingEvents.md). - + ```C# Snippet:EventHubs_Sample07_Publish -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -47,14 +51,16 @@ The `ReadEventsAsync` method of the `EventHubConsumerClient` allows events to be This example illustrates reading either 50 events or stopping after 30 seconds has elapsed, whichever occurs first. For more information on publishing, see: [Sample05_ReadingEvents](https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample05_ReadingEvents.md). ```C# Snippet:EventHubs_Sample07_ReadAllPartitions -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -101,6 +107,6 @@ finally await consumer.CloseAsync(); } ``` - - + + diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample08_CustomEventProcessor.md b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample08_CustomEventProcessor.md index 38db6ff2f12cf..4bee9d82a794e 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample08_CustomEventProcessor.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample08_CustomEventProcessor.md @@ -58,15 +58,17 @@ public class CustomProcessor : PluggableCheckpointStoreEventProcessor diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample09_ObservableEventBatch.md b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample09_ObservableEventBatch.md index cc41ffb6798f6..687f3c2805f35 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample09_ObservableEventBatch.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample09_ObservableEventBatch.md @@ -93,10 +93,14 @@ An `EventHubProducerClient` is safe to cache and use for the lifetime of the app ## Accessing the EventData Instances ```C# Snippet:Sample09_AccessingEventData -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -135,10 +139,14 @@ finally This sample demonstrates how to add an `EventData` identification property that can be used to verify that a given event ID was added to the observable batch. ```C# Snippet:Sample09_CheckingBatch -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; +var credential = new DefaultAzureCredential(); -var producer = new EventHubProducerClient(connectionString, eventHubName); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample10_AzureEventSourceListener.md b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample10_AzureEventSourceListener.md index d9b9be2f36651..b1e656b278b4a 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample10_AzureEventSourceListener.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample10_AzureEventSourceListener.md @@ -1,6 +1,6 @@ # Capturing Event Hubs logs using the AzureEventSourceListener -The Event Hubs client library is instrumented using the .NET [`EventSource`](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventsource) mechanism for logging. When instrumenting or diagnosing issues with applications that consume the library, it is often helpful to have access to the Event Hubs logs. The following scenarios demonstrate how to use the [`AzureEventSourceListener`](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/samples/Diagnostics.md#logging) from the `Azure.Core` package to capture logs emitted by the Event Hubs client library. +The Event Hubs client library is instrumented using the .NET [`EventSource`](https://learn.microsoft.com/dotnet/api/system.diagnostics.tracing.eventsource) mechanism for logging. When instrumenting or diagnosing issues with applications that consume the library, it is often helpful to have access to the Event Hubs logs. The following scenarios demonstrate how to use the [`AzureEventSourceListener`](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/samples/Diagnostics.md#logging) from the `Azure.Core` package to capture logs emitted by the Event Hubs client library. ## Table of contents @@ -28,9 +28,14 @@ The following snippet demonstrates an example of capturing all log information f This example captures all Azure SDK logs from any client library in use, writing them to the standard `Console` output stream. ```C# Snippet:EventHubs_Sample10_ConsoleListener -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; -var producer = new EventHubProducerClient(connectionString, eventHubName); +var credential = new DefaultAzureCredential(); + +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); using AzureEventSourceListener consoleListener = AzureEventSourceListener.CreateConsoleLogger(EventLevel.LogAlways); @@ -52,12 +57,17 @@ finally ## Capture all events and write them to `Trace` -Similar to the previous example, this snippet captures all logs, but writes them to [`Trace`](https://docs.microsoft.com/dotnet/api/system.diagnostics.trace) output. This approach may be desirable for applications that do not have the `Console` available. +Similar to the previous example, this snippet captures all logs, but writes them to [`Trace`](https://learn.microsoft.com/dotnet/api/system.diagnostics.trace) output. This approach may be desirable for applications that do not have the `Console` available. ```C# Snippet:EventHubs_Sample10_TraceListener -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; -var producer = new EventHubProducerClient(connectionString, eventHubName); +var credential = new DefaultAzureCredential(); + +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); using AzureEventSourceListener traceListener = AzureEventSourceListener.CreateTraceLogger(EventLevel.LogAlways); @@ -83,12 +93,17 @@ This examples demonstrates using a callback with the listener to allow custom lo In the snippet below, the `Verbose` messages for the `Azure-Identity` event source are captured and written to `Trace` output. Log messages for the `Azure-Messaging-EventHubs` event source are filtered to capture only a specific set to aid in debugging publishing, which are then written to the standard `Console` output. -More information about the `args` parameter for the callback can be found in the [EventWrittenEventArgs](https://docs.microsoft.com/dotnet/api/system.diagnostics.tracing.eventwritteneventargs) documentation.. +More information about the `args` parameter for the callback can be found in the [EventWrittenEventArgs](https://learn.microsoft.com/dotnet/api/system.diagnostics.tracing.eventwritteneventargs) documentation.. ```C# Snippet:EventHubs_Sample10_CustomListenerWithFilter -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; -var producer = new EventHubProducerClient(connectionString, eventHubName); +var credential = new DefaultAzureCredential(); + +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); using AzureEventSourceListener customListener = new AzureEventSourceListener((args, message) => { @@ -130,12 +145,17 @@ finally For scenarios where capturing logs to `Trace` or `Console` outputs isn't ideal, log information can be streamed into a variety of targets, such as Azure Storage, databases, and files for durable persistence. This example demonstrates capturing error logs to a text file so that they can be analyzed later, while capturing non-error information to `Console` output. ```C# Snippet:EventHubs_Sample10_CustomListenerWithFile -var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; -var producer = new EventHubProducerClient(connectionString, eventHubName); +var credential = new DefaultAzureCredential(); using Stream stream = new FileStream("<< PATH TO THE FILE >>", FileMode.OpenOrCreate, FileAccess.Write); +var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); + using StreamWriter streamWriter = new StreamWriter(stream) { AutoFlush = true diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample11_MockingClientTypes.md b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample11_MockingClientTypes.md index 261fe72ca2432..e148dd792149c 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample11_MockingClientTypes.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample11_MockingClientTypes.md @@ -20,8 +20,8 @@ For more general information and examples on mocking with the Azure SDK, please ## Publishing events with the `EventHubProducerClient` -When using batches to publish to Event Hubs, the key interactions with the `EventHubProducerClient` are calling `CreateBatchAsync` to create the batch and `SendAsync` to publish it. - Mocked batches accept a `List` that is used as a backing store and can be inspected to verify that the application is adding events to the batch as expected. The custom `TryAdd` callback can be used to control the decision for whether an event is accepted into the batch or is rejected. +When using batches to publish to Event Hubs, the key interactions with the `EventHubProducerClient` are calling `CreateBatchAsync` to create the batch and `SendAsync` to publish it. + Mocked batches accept a `List` that is used as a backing store and can be inspected to verify that the application is adding events to the batch as expected. The custom `TryAdd` callback can be used to control the decision for whether an event is accepted into the batch or is rejected. This snippet demonstrates mocking the `EventHubProducerClient`, and creating `EventDataBatch` instances using the `EventHubsModelFactory`. @@ -321,7 +321,7 @@ await foreach (PartitionEvent receivedEvent in consumer.ReadEventsFromPartitionA ## Consuming events using the `PartitionReceiver` -The sample below illustrates how to mock a `PartitionReceiver`, and set up its `ReceiveBatchAsync` method to return a simple data batch. +The sample below illustrates how to mock a `PartitionReceiver`, and set up its `ReceiveBatchAsync` method to return a simple data batch. Given the purpose of the `PartitionReceiver`, it is anticipated that most applications will have complex code surrounding their receivers, so this snippet is intentionally simple, with the focus being on using the `EventHubsModelFactory` to mock events being returned from the broker. @@ -493,4 +493,4 @@ string[] consumerPartitions = new string[] { "0", "1", "2" }; mockConsumer .Setup(p => p.GetPartitionIdsAsync(It.IsAny())) .ReturnsAsync(consumerPartitions); -``` \ No newline at end of file +``` diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Connection/EventHubConnectionLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Connection/EventHubConnectionLiveTests.cs index 39a8be6f94af2..bd9bb804f9228 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Connection/EventHubConnectionLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Connection/EventHubConnectionLiveTests.cs @@ -198,9 +198,11 @@ public async Task ConnectionTransportCanRetrieveProperties(EventHubsTransportTyp await using (EventHubScope scope = await EventHubScope.CreateAsync(partitionCount)) { - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - - await using (var connection = new TestConnectionWithRetryPolicy(connectionString, scope.EventHubName, new EventHubConnectionOptions { TransportType = transportType })) + await using (var connection = new TestConnectionWithRetryPolicy( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + new EventHubConnectionOptions { TransportType = transportType })) { EventHubProperties properties = await connection.GetPropertiesAsync(); @@ -228,18 +230,11 @@ public async Task ConnectionTransportCanRetrievePartitionProperties(EventHubsTra { var options = new EventHubConnectionOptions(); - var credential = new SharedAccessCredential - ( - new SharedAccessSignature - ( - $"{ options.TransportType.GetUriScheme() }://{ EventHubsTestEnvironment.Instance.FullyQualifiedNamespace }/{ scope.EventHubName }".ToLowerInvariant(), - EventHubsTestEnvironment.Instance.SharedAccessKeyName, - EventHubsTestEnvironment.Instance.SharedAccessKey, - TimeSpan.FromHours(4) - ) - ); - - await using (var connection = new TestConnectionWithRetryPolicy(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, credential, new EventHubConnectionOptions { TransportType = transportType })) + await using (var connection = new TestConnectionWithRetryPolicy( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + new EventHubConnectionOptions { TransportType = transportType })) { var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(20)); var properties = await connection.GetPropertiesAsync(); @@ -266,9 +261,10 @@ public async Task ConnectionTransportPartitionIdsMatchPartitionProperties() { await using (EventHubScope scope = await EventHubScope.CreateAsync(4)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var connection = new TestConnectionWithRetryPolicy(connectionString)) + await using (var connection = new TestConnectionWithRetryPolicy( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { EventHubProperties properties = await connection.GetPropertiesAsync(); var partitions = await connection.GetPartitionIdsAsync(); @@ -291,9 +287,10 @@ public async Task ConnectionTransportCannotRetrieveMetadataWhenClosed() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var connection = new TestConnectionWithRetryPolicy(connectionString)) + await using (var connection = new TestConnectionWithRetryPolicy( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await connection.GetPartitionIdsAsync()).First(); @@ -324,9 +321,10 @@ public async Task ConnectionTransportCannotRetrievePartitionPropertiesWhenPartit { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var connection = new TestConnectionWithRetryPolicy(connectionString)) + await using (var connection = new TestConnectionWithRetryPolicy( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { Assert.That(async () => await connection.GetPartitionPropertiesAsync(invalidPartition), Throws.TypeOf()); } @@ -343,7 +341,6 @@ public async Task ConnectionTransportCannotRetrieveMetadataWhenProxyIsInvalid() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var retryOptions = new EventHubsRetryOptions { TryTimeout = TimeSpan.FromMinutes(2) }; var clientOptions = new EventHubConnectionOptions @@ -352,8 +349,16 @@ public async Task ConnectionTransportCannotRetrieveMetadataWhenProxyIsInvalid() TransportType = EventHubsTransportType.AmqpWebSockets }; - await using (var connection = new TestConnectionWithRetryPolicy(connectionString)) - await using (var invalidProxyConnection = new TestConnectionWithRetryPolicy(connectionString, clientOptions)) + await using (var connection = new TestConnectionWithRetryPolicy( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) + + await using (var invalidProxyConnection = new TestConnectionWithRetryPolicy( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + clientOptions)) { connection.RetryPolicy = new BasicRetryPolicy(retryOptions); invalidProxyConnection.RetryPolicy = new BasicRetryPolicy(retryOptions); @@ -377,7 +382,6 @@ public async Task ConnectionTransportCannotRetrieveMetadataWhenCustomValidationR { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var retryOptions = new EventHubsRetryOptions { TryTimeout = TimeSpan.FromMinutes(2) }; var clientOptions = new EventHubConnectionOptions @@ -385,8 +389,16 @@ public async Task ConnectionTransportCannotRetrieveMetadataWhenCustomValidationR CertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) => false }; - await using (var connection = new TestConnectionWithRetryPolicy(connectionString)) - await using (var certificateRejectingConnection = new TestConnectionWithRetryPolicy(connectionString, clientOptions)) + await using (var connection = new TestConnectionWithRetryPolicy( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) + + await using (var certificateRejectingConnection = new TestConnectionWithRetryPolicy( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + clientOptions)) { connection.RetryPolicy = new BasicRetryPolicy(retryOptions); certificateRejectingConnection.RetryPolicy = new BasicRetryPolicy(retryOptions); @@ -410,7 +422,6 @@ public async Task ConnectionTransportCanRetrieveMetadataWhenCustomValidationAcce { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var retryOptions = new EventHubsRetryOptions { TryTimeout = TimeSpan.FromMinutes(2) }; var clientOptions = new EventHubConnectionOptions @@ -418,7 +429,11 @@ public async Task ConnectionTransportCanRetrieveMetadataWhenCustomValidationAcce CertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) => true }; - await using (var connection = new TestConnectionWithRetryPolicy(connectionString, clientOptions)) + await using (var connection = new TestConnectionWithRetryPolicy( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + clientOptions)) { connection.RetryPolicy = new BasicRetryPolicy(retryOptions); diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs index 4188aa6467ab5..012672d024e4e 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs @@ -56,9 +56,11 @@ public async Task ConsumerWithNoOptionsCanRead(EventHubsTransportType transportT using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var connection = new EventHubConnection(connectionString, new EventHubConnectionOptions { TransportType = transportType })) + await using (var connection = new EventHubConnection( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + new EventHubConnectionOptions { TransportType = transportType })) { var partition = (await connection.GetPartitionIdsAsync(new EventHubsRetryOptions().ToRetryPolicy(), cancellationSource.Token)).First(); @@ -91,7 +93,12 @@ public async Task ConsumerWithOptionsCanRead(EventHubsTransportType transportTyp options.RetryOptions.MaximumRetries = 7; options.ConnectionOptions.TransportType = transportType; - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, options)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); Assert.That(async () => await ReadNothingAsync(consumer, partition, cancellationSource.Token, EventPosition.Latest), Throws.Nothing); @@ -125,7 +132,12 @@ public async Task ConsumerWithCustomBufferSizesCanRead(EventHubsTransportType tr } }; - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, options)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); Assert.That(async () => await ReadNothingAsync(consumer, partition, cancellationSource.Token, EventPosition.Latest), Throws.Nothing); @@ -148,13 +160,16 @@ public async Task ConsumerCanReadSingleZeroLengthEvent() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var singleEvent = EventGenerator.CreateEventFromBody(Array.Empty()); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, new EventData[] { singleEvent }, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, new EventData[] { singleEvent }, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -182,13 +197,16 @@ public async Task ConsumerCanReadSingleEvent() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var singleEvent = EventGenerator.CreateEvents(1).Single(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, new EventData[] { singleEvent }, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, new EventData[] { singleEvent }, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -220,12 +238,15 @@ public async Task ConsumerCanReadSingleLargeEvent() new Random().NextBytes(buffer); var singleEvent = EventGenerator.CreateEventFromBody(buffer); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, new EventData[] { singleEvent }, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, new EventData[] { singleEvent }, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -253,17 +274,19 @@ public async Task ConsumerCanReadBatchOfZeroLengthEvents() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var sourceEvents = Enumerable .Range(0, 25) .Select(index => EventGenerator.CreateEventFromBody(Array.Empty())) .ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -295,13 +318,16 @@ public async Task ConsumerCanReadBatchOfEvents() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(200).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -333,13 +359,16 @@ public async Task ConsumerWithAnIdentifierCanReadEvents() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(200).ToList(); - - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString, new EventHubConsumerClientOptions { Identifier = "BobTheConsumer" })) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + new EventHubConsumerClientOptions { Identifier = "BobTheConsumer" })) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -371,13 +400,16 @@ public async Task ConsumerCanReadBatchOfEventsWithCustomPrefetchAndBatchCounts() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(200).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -410,13 +442,16 @@ public async Task ConsumerCanReadBatchOfEventsWithCustomPrefetchAndBatchCountsAn using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(200).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -449,13 +484,16 @@ public async Task ConsumerCanReadEventsWithPrefetchDisabled() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(200).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -487,8 +525,6 @@ [Test]public async Task ConsumerCanReadEventsWithCustomProperties() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var sourceEvents = EventGenerator.CreateEvents(50) .Select(current => { @@ -499,10 +535,14 @@ [Test]public async Task ConsumerCanReadEventsWithCustomProperties() }) .ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -533,8 +573,6 @@ [Test]public async Task ConsumerCanReadEventsWithBinaryProperties() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var sourceEvents = EventGenerator.CreateEvents(5) .Select(current => { @@ -545,10 +583,14 @@ [Test]public async Task ConsumerCanReadEventsWithBinaryProperties() }) .ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -573,22 +615,19 @@ [Test]public async Task ConsumerCanReadEventsWithBinaryProperties() /// /// [Test] - public async Task ConsumerCanReadEventsUsingAnIdentityCredential() + public async Task ConsumerCanReadEventsUsingTheConnectionString() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var credential = EventHubsTestEnvironment.Instance.Credential; var sourceEvents = EventGenerator.CreateEvents(50).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, credential)) + await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -626,9 +665,7 @@ public async Task ConsumerCanReadEventsUsingTheSharedKeyCredential() await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -669,9 +706,7 @@ public async Task ConsumerCanReadEventsUsingTheSasCredential() await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, credential, options)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -703,13 +738,16 @@ public async Task ConsumerCanReadFromEarliest() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(200).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -741,15 +779,18 @@ public async Task ConsumerCanReadFromLatest() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(200).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { // Send a set of seed events to the partition, which should not be read. var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, EventGenerator.CreateEvents(50), new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, EventGenerator.CreateEvents(50), new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Begin reading though no events have been published. This is necessary to open the connection and // ensure that the consumer is watching the partition. @@ -759,7 +800,7 @@ public async Task ConsumerCanReadFromLatest() // Give the consumer a moment to ensure that it is established and then send events for it to read. await Task.Delay(250); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Await reading of the events and validate the resulting state. @@ -794,11 +835,14 @@ public async Task ConsumerCanReadFromOffset(bool isInclusive) using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var seedEvents = EventGenerator.CreateEvents(50).ToList(); var sourceEvents = EventGenerator.CreateEvents(100).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { // Seed the partition with a set of events prior to reading. When the send call returns, all events were // accepted by the Event Hubs service and should be available in the partition. Provide a minor delay to @@ -806,7 +850,7 @@ public async Task ConsumerCanReadFromOffset(bool isInclusive) var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, seedEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, seedEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); await Task.Delay(250); // Query the partition and determine the offset of the last enqueued event, then send the new set @@ -815,7 +859,7 @@ public async Task ConsumerCanReadFromOffset(bool isInclusive) var lastOffset = (await consumer.GetPartitionPropertiesAsync(partition, cancellationSource.Token)).LastEnqueuedOffset; var startingPosition = EventPosition.FromOffset(lastOffset, isInclusive); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -861,11 +905,14 @@ public async Task ConsumerCanReadFromSequenceNumber(bool isInclusive) using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var seedEvents = EventGenerator.CreateEvents(50).ToList(); var sourceEvents = EventGenerator.CreateEvents(100).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { // Seed the partition with a set of events prior to reading. When the send call returns, all events were // accepted by the Event Hubs service and should be available in the partition. Provide a minor delay to @@ -873,7 +920,7 @@ public async Task ConsumerCanReadFromSequenceNumber(bool isInclusive) var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, seedEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, seedEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); await Task.Delay(250); // Query the partition and determine the offset of the last enqueued event, then send the new set @@ -882,7 +929,7 @@ public async Task ConsumerCanReadFromSequenceNumber(bool isInclusive) var lastSequence = (await consumer.GetPartitionPropertiesAsync(partition, cancellationSource.Token)).LastEnqueuedSequenceNumber; var startingPosition = EventPosition.FromSequenceNumber(lastSequence, isInclusive); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -926,11 +973,14 @@ public async Task ConsumerCanReadFromEnqueuedTime() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var seedEvents = EventGenerator.CreateEvents(50).ToList(); var sourceEvents = EventGenerator.CreateEvents(100).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { // Seed the partition with a set of events prior to reading. When the send call returns, all events were // accepted by the Event Hubs service and should be available in the partition. Provide a minor delay to @@ -938,7 +988,7 @@ public async Task ConsumerCanReadFromEnqueuedTime() var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, seedEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, seedEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); await Task.Delay(TimeSpan.FromSeconds(2)); // Query the partition and determine the offset of the last enqueued event, then send the new set @@ -947,7 +997,7 @@ public async Task ConsumerCanReadFromEnqueuedTime() var lastEnqueuedTime = (await consumer.GetPartitionPropertiesAsync(partition, cancellationSource.Token)).LastEnqueuedTime; var startingPosition = EventPosition.FromEnqueuedTime(lastEnqueuedTime); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -984,18 +1034,22 @@ public async Task ConsumerCanReadConcurrentlyFromMultiplePartitions() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(200).ToList(); var expectedEvents = sourceEvents.Select(evt => evt.MessageId); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString, new EventHubConsumerClientOptions { Identifier = "BobTheConsumer" })) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + new EventHubConsumerClientOptions { Identifier = "BobTheConsumer" })) { var partitions = await consumer.GetPartitionIdsAsync(cancellationSource.Token); await Task.WhenAll ( - SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partitions[0] }, cancellationSource.Token), - SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partitions[1] }, cancellationSource.Token) + SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partitions[0] }, cancellationSource.Token), + SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partitions[1] }, cancellationSource.Token) ); // Read the events and validate the resulting state. @@ -1041,15 +1095,23 @@ public async Task ConsumerCanReadFromMultipleConsumerGroups() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(100).ToList(); var expectedEvents = sourceEvents.Select(evt => evt.MessageId); - await using (var customConsumer = new EventHubConsumerClient(customConsumerGroup, connectionString)) - await using (var defaultConsumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var customConsumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) + + await using (var defaultConsumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await defaultConsumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read the events and validate the resulting state. @@ -1089,15 +1151,16 @@ public async Task ConsumerCannotReadAcrossPartitions() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var credential = EventHubsTestEnvironment.Instance.Credential; var sourceEvents = EventGenerator.CreateEvents(50).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, credential)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partitions = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).ToArray(); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partitions[0] }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partitions[0] }, cancellationSource.Token); // Attempt to read from the empty partition and verify that no events are observed. Because no events are expected, the // read operation will not naturally complete; limit the read to only a couple of seconds and trigger cancellation. @@ -1129,13 +1192,16 @@ public async Task ConsumerCannotReadWhenClosed() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(100).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Create a local function that will close the consumer after five events have // been read. Because the close happens in the middle of iteration, allow for a short @@ -1175,14 +1241,13 @@ public async Task ConsumerCannotReadWhenSharedConnectionIsClosed() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(100).ToList(); - await using (var connection = new EventHubConnection(connectionString)) + await using (var connection = new EventHubConnection(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connection)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Create a local function that will close the connection after five events have // been read. Because the close happens in the middle of iteration, allow for a short @@ -1222,7 +1287,11 @@ public async Task ConsumerCannotReadFromInvalidPartition() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var invalidPartition = "-1"; var readTask = ReadNothingAsync(consumer, invalidPartition, cancellationSource.Token); @@ -1250,8 +1319,8 @@ public async Task ConsumerCannotReadFromInvalidConsumerGroup() var invalidConsumerGroup = "ThisIsFake"; - await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName)) - await using (var consumer = new EventHubConsumerClient(invalidConsumerGroup, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) + await using (var consumer = new EventHubConsumerClient(invalidConsumerGroup, EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { var partition = (await producer.GetPartitionIdsAsync(cancellationSource.Token)).First(); var readTask = ReadNothingAsync(consumer, partition, cancellationSource.Token); @@ -1284,8 +1353,8 @@ public async Task ConsumerCannotReadWithInvalidProxy() clientOptions.ConnectionOptions.Proxy = new WebProxy("http://1.2.3.4:9999"); clientOptions.ConnectionOptions.TransportType = EventHubsTransportType.AmqpWebSockets; - await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName)) - await using (var invalidProxyConsumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, clientOptions)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) + await using (var invalidProxyConsumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, clientOptions)) { var partition = (await producer.GetPartitionIdsAsync(cancellationSource.Token)).First(); @@ -1316,13 +1385,16 @@ public async Task ConsumerCannotReadAsNonExclusiveWhenAnExclusiveReaderIsActive( exclusiveOptions.PrefetchCount = LowPrefetchCount; exclusiveOptions.OwnerLevel = 20; - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(200).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); var exclusiveMonitor = MonitorReadingEventsFromPartition(consumer, partition, null, cancellationSource.Token, readOptions: exclusiveOptions); await Task.WhenAny(exclusiveMonitor.StartCompletion.Task, Task.Delay(Timeout.Infinite, cancellationSource.Token)); @@ -1359,13 +1431,16 @@ public async Task ConsumerCannotReadWithLowerOwnerLevelThanActiveReader() lowerOptions.PrefetchCount = LowPrefetchCount; lowerOptions.OwnerLevel = 20; - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(200).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); var higherMonitor = MonitorReadingEventsFromPartition(consumer, partition, null, cancellationSource.Token, readOptions: higherOptions); await Task.WhenAny(higherMonitor.StartCompletion.Task, Task.Delay(Timeout.Infinite, cancellationSource.Token)); @@ -1402,11 +1477,14 @@ public async Task ConsumerCanReadFromMultiplePartitionsWithDifferentActiveOwnerL lowerOptions.PrefetchCount = LowPrefetchCount; lowerOptions.OwnerLevel = 20; - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(100).ToList(); var expectedEvents = sourceEvents.Select(evt => evt.MessageId); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partitions = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).Take(2).ToArray(); @@ -1414,8 +1492,8 @@ public async Task ConsumerCanReadFromMultiplePartitionsWithDifferentActiveOwnerL await Task.WhenAll ( - SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partitions[0] }, cancellationSource.Token), - SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partitions[1] }, cancellationSource.Token) + SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partitions[0] }, cancellationSource.Token), + SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partitions[1] }, cancellationSource.Token) ); // Read from each partition, allowing the higher level operation to begin first. Both read operations should be @@ -1462,15 +1540,23 @@ public async Task ConsumerCanReadFromMultipleConsumerGroupsWithDifferentActiveOw lowerOptions.PrefetchCount = LowPrefetchCount; lowerOptions.OwnerLevel = 20; - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(100).ToList(); var expectedEvents = sourceEvents.Select(evt => evt.MessageId); - await using (var firstGroupConsumer = new EventHubConsumerClient(scope.ConsumerGroups[0], connectionString)) - await using (var secondGroupConsumer = new EventHubConsumerClient(scope.ConsumerGroups[1], connectionString)) + await using (var firstGroupConsumer = new EventHubConsumerClient( + consumerGroups[0], + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) + + await using (var secondGroupConsumer = new EventHubConsumerClient( + consumerGroups[1], + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await firstGroupConsumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Read from each partition, allowing the higher level operation to begin first. Both read operations should be // successful and read all events from their respective partition. @@ -1515,14 +1601,17 @@ public async Task ExclusiveConsumerSupersedesNonExclusiveActiveReader() nonExclusiveOptions.CacheEventCount = 10; nonExclusiveOptions.MaximumWaitTime = TimeSpan.FromMilliseconds(150); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(2500).ToList(); var expectedEvents = sourceEvents.Select(evt => evt.MessageId); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Start the non-exclusive read, waiting until at least some events were read before starting the exclusive reader. @@ -1581,14 +1670,17 @@ public async Task ConsumerWithHigherOwnerLevelSupersedesActiveReader() lowerOptions.OwnerLevel = 20; lowerOptions.MaximumWaitTime = TimeSpan.FromMilliseconds(150); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(2500).ToList(); var expectedEvents = sourceEvents.Select(evt => evt.MessageId); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Start the lower level read, waiting until at least some events were read before starting the higher reader. @@ -1640,11 +1732,14 @@ public async Task ExclusiveConsumerDoesNotSupersedeNonExclusiveActiveReaderOnAno exclusiveOptions.PrefetchCount = LowPrefetchCount; exclusiveOptions.OwnerLevel = 20; - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(100).ToList(); var expectedEvents = sourceEvents.Select(evt => evt.MessageId); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partitions = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).Take(2).ToArray(); @@ -1652,8 +1747,8 @@ public async Task ExclusiveConsumerDoesNotSupersedeNonExclusiveActiveReaderOnAno await Task.WhenAll ( - SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partitions[0] }, cancellationSource.Token), - SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partitions[1] }, cancellationSource.Token) + SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partitions[0] }, cancellationSource.Token), + SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partitions[1] }, cancellationSource.Token) ); // Start the non-exclusive read, waiting until at least some events were read before starting the exclusive reader. @@ -1707,15 +1802,23 @@ public async Task ExclusiveConsumerDoesNotSupersedeNonExclusiveActiveReaderOnAno exclusiveOptions.PrefetchCount = LowPrefetchCount; exclusiveOptions.OwnerLevel = 20; - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(200).ToList(); var expectedEvents = sourceEvents.Select(evt => evt.MessageId); - await using (var nonExclusiveConsumer = new EventHubConsumerClient(scope.ConsumerGroups[0], connectionString)) - await using (var exclusiveConsumer = new EventHubConsumerClient(scope.ConsumerGroups[1], connectionString)) + await using (var nonExclusiveConsumer = new EventHubConsumerClient( + consumerGroups[0], + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) + + await using (var exclusiveConsumer = new EventHubConsumerClient( + consumerGroups[1], + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await exclusiveConsumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Start the non-exclusive read, waiting until at least some events were read before starting the exclusive reader. @@ -1762,13 +1865,16 @@ public async Task ConsumerIsNotCompromisedByFailureToReadFromInvalidPartition() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(50).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Attempt to read from an invalid partition and confirm failure. @@ -1816,11 +1922,14 @@ public async Task ConsumerIsNotCompromisedByBeingSupersededByAnotherReaderWithHi lowerOptions.CacheEventCount = 10; lowerOptions.MaximumWaitTime = TimeSpan.FromMilliseconds(150); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(2500).ToList(); var expectedEvents = sourceEvents.Select(evt => evt.MessageId); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partitions = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).Take(2).ToArray(); @@ -1828,8 +1937,8 @@ public async Task ConsumerIsNotCompromisedByBeingSupersededByAnotherReaderWithHi await Task.WhenAll ( - SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partitions[0] }, cancellationSource.Token), - SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partitions[1] }, cancellationSource.Token) + SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partitions[0] }, cancellationSource.Token), + SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partitions[1] }, cancellationSource.Token) ); // Start the lower level read, waiting until at least some events were read before starting the higher reader. @@ -1885,7 +1994,11 @@ public async Task ConsumerRespectsTheWaitTimeWhenReading() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); var options = new ReadEventOptions { MaximumWaitTime = TimeSpan.FromMilliseconds(100) }; @@ -1931,7 +2044,12 @@ public async Task ConsumerCanQueryEventHubProperties(EventHubsTransportType tran using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, clientOptions)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + clientOptions)) { var properties = await consumer.GetEventHubPropertiesAsync(cancellationSource.Token); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); @@ -1961,10 +2079,14 @@ public async Task ConsumerCanQueryPartitionProperties(EventHubsTransportType tra using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var clientOptions = new EventHubConsumerClientOptions { ConnectionOptions = new EventHubConnectionOptions { TransportType = transportType } }; - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString, scope.EventHubName, clientOptions)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + clientOptions)) { var properties = await consumer.GetEventHubPropertiesAsync(); var partition = properties.PartitionIds.First(); @@ -1995,7 +2117,11 @@ public async Task ConnectionTransportPartitionIdsMatchPartitionProperties() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var properties = await consumer.GetEventHubPropertiesAsync(cancellationSource.Token); var partitions = await consumer.GetPartitionIdsAsync(cancellationSource.Token); @@ -2022,7 +2148,11 @@ public async Task ConsumerCannotRetrieveMetadataWhenClosed() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); @@ -2058,7 +2188,11 @@ public async Task ConsumerCannotRetrievePartitionPropertiesWithInvalidPartitionI using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { Assert.That(async () => await consumer.GetPartitionPropertiesAsync(invalidPartition, cancellationSource.Token), Throws.TypeOf()); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); @@ -2079,8 +2213,6 @@ public async Task ConsumerCannotRetrieveMetadataWithInvalidProxy() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var invalidProxyOptions = new EventHubConsumerClientOptions(); invalidProxyOptions.RetryOptions.MaximumRetries = 0; invalidProxyOptions.RetryOptions.MaximumDelay = TimeSpan.FromMilliseconds(5); @@ -2088,8 +2220,18 @@ public async Task ConsumerCannotRetrieveMetadataWithInvalidProxy() invalidProxyOptions.ConnectionOptions.Proxy = new WebProxy("http://1.2.3.4:9999"); invalidProxyOptions.ConnectionOptions.TransportType = EventHubsTransportType.AmqpWebSockets; - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) - await using (var invalidProxyConsumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString, invalidProxyOptions)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) + + await using (var invalidProxyConsumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + invalidProxyOptions)) { var partition = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).First(); @@ -2118,14 +2260,17 @@ public async Task ConsumerCanReadFromAllPartitions() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(100).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partitions = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).ToArray(); - var sendCount = await SendEventsToAllPartitionsAsync(connectionString, sourceEvents, partitions, cancellationSource.Token); + var sendCount = await SendEventsToAllPartitionsAsync(scope.EventHubName, sourceEvents, partitions, cancellationSource.Token); Assert.That(sendCount, Is.EqualTo(sourceEvents.Count), "All of the events should have been sent."); // Read the events and validate the resulting state. @@ -2158,20 +2303,23 @@ public async Task ConsumerCanReadFromAllPartitionsWithCustomPrefetchAndBatchCoun using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(100).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var partitions = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).ToArray(); - var sendCount = await SendEventsToAllPartitionsAsync(connectionString, sourceEvents, partitions, cancellationSource.Token); + var sendCount = await SendEventsToAllPartitionsAsync(scope.EventHubName, sourceEvents, partitions, cancellationSource.Token); Assert.That(sendCount, Is.EqualTo(sourceEvents.Count), "All of the events should have been sent."); // Read the events and validate the resulting state. var readOptions = new ReadEventOptions { PrefetchCount = 50, CacheEventCount = 50 }; - var readState = await ReadEventsFromAllPartitionsAsync(consumer,sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token, readOptions: readOptions); + var readState = await ReadEventsFromAllPartitionsAsync(consumer, sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token, readOptions: readOptions); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); foreach (var sourceEvent in sourceEvents) @@ -2192,22 +2340,21 @@ public async Task ConsumerCanReadFromAllPartitionsWithCustomPrefetchAndBatchCoun /// /// [Test] - public async Task ConsumerCanReadFromAllPartitionsUsingAnIdentityCredential() + public async Task ConsumerCanReadFromAllPartitionsUsingTheConnectionString() { await using (EventHubScope scope = await EventHubScope.CreateAsync(4)) { using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var credential = EventHubsTestEnvironment.Instance.Credential; + var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var sourceEvents = EventGenerator.CreateEvents(100).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, credential)) + await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString, scope.EventHubName)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var partitions = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).ToArray(); + var sendCount = await SendEventsToAllPartitionsAsync(scope.EventHubName, sourceEvents, partitions, cancellationSource.Token); - var sendCount = await SendEventsToAllPartitionsAsync(connectionString, sourceEvents, partitions, cancellationSource.Token); Assert.That(sendCount, Is.EqualTo(sourceEvents.Count), "All of the events should have been sent."); // Read the events and validate the resulting state. @@ -2245,10 +2392,9 @@ public async Task ConsumerCanReadFromAllPartitionsUsingTheSharedKeyCredential() await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, credential)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var partitions = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).ToArray(); + var sendCount = await SendEventsToAllPartitionsAsync(scope.EventHubName, sourceEvents, partitions, cancellationSource.Token); - var sendCount = await SendEventsToAllPartitionsAsync(connectionString, sourceEvents, partitions, cancellationSource.Token); Assert.That(sendCount, Is.EqualTo(sourceEvents.Count), "All of the events should have been sent."); // Read the events and validate the resulting state. @@ -2289,10 +2435,9 @@ public async Task ConsumerCanReadFromAllPartitionsUsingTheSasCredential() await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, credential, options)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var partitions = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).ToArray(); + var sendCount = await SendEventsToAllPartitionsAsync(scope.EventHubName, sourceEvents, partitions, cancellationSource.Token); - var sendCount = await SendEventsToAllPartitionsAsync(connectionString, sourceEvents, partitions, cancellationSource.Token); Assert.That(sendCount, Is.EqualTo(sourceEvents.Count), "All of the events should have been sent."); // Read the events and validate the resulting state. @@ -2325,15 +2470,18 @@ public async Task ConsumerCanReadFromAllPartitionsStartingWithLatest() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(100).ToList(); - await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString)) + await using (var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { // Send a set of seed events, which should not be read. var partitions = (await consumer.GetPartitionIdsAsync(cancellationSource.Token)).ToArray(); - await SendEventsToAllPartitionsAsync(connectionString, EventGenerator.CreateEvents(50), partitions, cancellationSource.Token); + await SendEventsToAllPartitionsAsync(scope.EventHubName, EventGenerator.CreateEvents(50), partitions, cancellationSource.Token); // Begin reading though no events have been published. This is necessary to open the connection and // ensure that the consumer is watching the partition. @@ -2343,7 +2491,7 @@ public async Task ConsumerCanReadFromAllPartitionsStartingWithLatest() // Give the consumer a moment to ensure that it is established and then send events for it to read. await Task.Delay(250); - await SendEventsToAllPartitionsAsync(connectionString, sourceEvents, partitions, cancellationSource.Token); + await SendEventsToAllPartitionsAsync(scope.EventHubName, sourceEvents, partitions, cancellationSource.Token); // Read the events and validate the resulting state. @@ -2537,21 +2685,24 @@ private async Task ReadNothingAsync(EventHubConsumerClient consumer, /// Sends a set of events using a new producer to do so. /// /// - /// The connection string to use when creating the producer. + /// The name of the Event Hub to use when creating the producer. /// The set of events to send. /// The set of options to apply when creating batches. /// The token used to signal a cancellation request. /// /// The count of events that were sent. /// - private async Task SendEventsAsync(string connectionString, + private async Task SendEventsAsync(string eventHubName, IEnumerable sourceEvents, CreateBatchOptions batchOptions = default, CancellationToken cancellationToken = default) { var sentCount = 0; - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + eventHubName, + EventHubsTestEnvironment.Instance.Credential)) { foreach (var batch in (await EventGenerator.BuildBatchesAsync(sourceEvents, producer, batchOptions, cancellationToken))) { @@ -2570,14 +2721,14 @@ private async Task SendEventsAsync(string connectionString, /// distribution with no guaranteed ordering. /// /// - /// The connection string to use when creating the producer. + /// The Event Hub name to use when creating the producer. /// The set of events to send. /// The set of partitions to send events to. /// The token used to signal a cancellation request. /// /// The count of events that were sent. /// - private async Task SendEventsToAllPartitionsAsync(string connectionString, + private async Task SendEventsToAllPartitionsAsync(string eventHubName, IEnumerable sourceEvents, string[] partitionIds, CancellationToken cancellationToken = default) @@ -2587,7 +2738,7 @@ private async Task SendEventsToAllPartitionsAsync(string connectionString, .Select(eventGroup => { var options = new CreateBatchOptions { PartitionId = partitionIds[eventGroup.Key] }; - return SendEventsAsync(connectionString, eventGroup, options, cancellationToken); + return SendEventsAsync(eventHubName, eventGroup, options, cancellationToken); }); var sendCounts = await Task.WhenAll(sendTasks).ConfigureAwait(false); diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Primitives/PartitionReceiverLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Primitives/PartitionReceiverLiveTests.cs index 4389704f6148e..ef02b92dff63b 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Primitives/PartitionReceiverLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Primitives/PartitionReceiverLiveTests.cs @@ -56,13 +56,21 @@ public async Task ReceiverWithNoOptionsCanRead(EventHubsTransportType transportT using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var connection = new EventHubConnection(connectionString, new EventHubConnectionOptions { TransportType = transportType })) + await using (var connection = new EventHubConnection( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + new EventHubConnectionOptions { TransportType = transportType })) { var partition = (await connection.GetPartitionIdsAsync(new EventHubsRetryOptions().ToRetryPolicy(), cancellationSource.Token)).First(); - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { Assert.That(async () => await ReadNothingAsync(receiver, cancellationSource.Token), Throws.Nothing); } @@ -91,10 +99,16 @@ public async Task ReceiverWithOptionsCanRead(EventHubsTransportType transportTyp options.RetryOptions.MaximumRetries = 7; options.ConnectionOptions.TransportType = transportType; - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, options)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options)) { Assert.That(async () => await ReadNothingAsync(receiver, cancellationSource.Token), Throws.Nothing); } @@ -116,13 +130,18 @@ public async Task ReceiverCanReadSingleZeroLengthEvent() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var singleEvent = EventGenerator.CreateEventFromBody(Array.Empty()); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, new EventData[] { singleEvent }, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, new EventData[] { singleEvent }, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var readState = await ReadEventsAsync(receiver, new HashSet { singleEvent.MessageId }, cancellationSource.Token); @@ -148,13 +167,18 @@ public async Task ReceiverCanReadSingleEvent() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var singleEvent = EventGenerator.CreateEvents(1).Single(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, new EventData[] { singleEvent }, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, new EventData[] { singleEvent }, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var readState = await ReadEventsAsync(receiver, new HashSet { singleEvent.MessageId }, cancellationSource.Token); @@ -184,12 +208,17 @@ public async Task ReceiverCanReadSingleLargeEvent() new Random().NextBytes(buffer); var singleEvent = EventGenerator.CreateEventFromBody(buffer); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, new EventData[] { singleEvent }, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, new EventData[] { singleEvent }, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var readState = await ReadEventsAsync(receiver, new HashSet { singleEvent.MessageId }, cancellationSource.Token); @@ -220,13 +249,18 @@ public async Task ReceiverCanReadBatchOfZeroLengthEvents() .Select(index => EventGenerator.CreateEventFromBody(Array.Empty())) .ToList(); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { - var readState = await ReadEventsAsync(receiver,sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); + var readState = await ReadEventsAsync(receiver, sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); foreach (var sourceEvent in sourceEvents) @@ -254,15 +288,20 @@ public async Task ReceiverCanReadBatchOfEvents() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(200).ToList(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { - var readState = await ReadEventsAsync(receiver,sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); + var readState = await ReadEventsAsync(receiver, sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); foreach (var sourceEvent in sourceEvents) @@ -290,20 +329,26 @@ public async Task ReceiverCanReadBatchOfEventsWithPrefetchSize() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(200).ToList(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); var recieverOptions = new PartitionReceiverOptions { PrefetchSizeInBytes = 64 }; - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, recieverOptions)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + recieverOptions)) { - var readState = await ReadEventsAsync(receiver,sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); + var readState = await ReadEventsAsync(receiver, sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); foreach (var sourceEvent in sourceEvents) @@ -341,13 +386,18 @@ public async Task ReceiverCanReadEventsWithCustomProperties() }) .ToList(); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { - var readState = await ReadEventsAsync(receiver,sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); + var readState = await ReadEventsAsync(receiver, sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); foreach (var sourceEvent in sourceEvents) @@ -368,7 +418,7 @@ public async Task ReceiverCanReadEventsWithCustomProperties() /// /// [Test] - public async Task ReceiverCanReadEventsUsingAnIdentityCredential() + public async Task ReceiverCanReadEventsUsingTheConnectionString() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { @@ -379,12 +429,12 @@ public async Task ReceiverCanReadEventsUsingAnIdentityCredential() var sourceEvents = EventGenerator.CreateEvents(50).ToList(); var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, credential)) + await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString)) { - var readState = await ReadEventsAsync(receiver,sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); + var readState = await ReadEventsAsync(receiver, sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); foreach (var sourceEvent in sourceEvents) @@ -415,13 +465,12 @@ public async Task ReceiverCanReadEventsUsingTheSharedKeyCredential() var credential = new AzureNamedKeyCredential(EventHubsTestEnvironment.Instance.SharedAccessKeyName, EventHubsTestEnvironment.Instance.SharedAccessKey); var sourceEvents = EventGenerator.CreateEvents(50).ToList(); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, credential)) { - var readState = await ReadEventsAsync(receiver,sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); + var readState = await ReadEventsAsync(receiver, sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); foreach (var sourceEvent in sourceEvents) @@ -455,13 +504,12 @@ public async Task ReceiverCanReadEventsUsingTheSasCredential() var credential = new AzureSasCredential(signature.Value); var sourceEvents = EventGenerator.CreateEvents(50).ToList(); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, credential, options)) { - var readState = await ReadEventsAsync(receiver,sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); + var readState = await ReadEventsAsync(receiver, sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); foreach (var sourceEvent in sourceEvents) @@ -489,15 +537,20 @@ public async Task ReceiverCanReadFromEarliest() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(200).ToList(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { - var readState = await ReadEventsAsync(receiver,sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); + var readState = await ReadEventsAsync(receiver, sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); foreach (var sourceEvent in sourceEvents) @@ -525,25 +578,30 @@ public async Task ReceiverCanReadFromLatest() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); var sourceEvents = EventGenerator.CreateEvents(200).ToList(); - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Latest, connectionString)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Latest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { // Send a set of seed events to the partition, which should not be read. - await SendEventsAsync(connectionString, EventGenerator.CreateEvents(50), new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, EventGenerator.CreateEvents(50), new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Begin reading though no events have been published. This is necessary to open the connection and // ensure that the receiver is watching the partition. - var readTask = ReadEventsAsync(receiver,sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); + var readTask = ReadEventsAsync(receiver, sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); // Give the receiver a moment to ensure that it is established and then send events for it to read. await Task.Delay(250); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Await reading of the events and validate the resulting state. @@ -578,8 +636,7 @@ public async Task ReceiverCanReadFromOffset(bool isInclusive) using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); var seedEvents = EventGenerator.CreateEvents(50).ToList(); var sourceEvents = EventGenerator.CreateEvents(100).ToList(); @@ -593,20 +650,29 @@ public async Task ReceiverCanReadFromOffset(bool isInclusive) long lastOffset; EventPosition startingPosition; - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { - await SendEventsAsync(connectionString, seedEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, seedEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); await Task.Delay(250); lastOffset = (await producer.GetPartitionPropertiesAsync(partition, cancellationSource.Token)).LastEnqueuedOffset; startingPosition = EventPosition.FromOffset(lastOffset, isInclusive); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); } // Read the events and validate the resulting state. - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, startingPosition, connectionString)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + startingPosition, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var expectedCount = sourceEvents.Count; var expectedEvents = sourceEvents.Select(evt => evt.MessageId); @@ -650,8 +716,7 @@ public async Task ReceiverCanReadFromSequenceNumber(bool isInclusive) using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); var seedEvents = EventGenerator.CreateEvents(50).ToList(); var sourceEvents = EventGenerator.CreateEvents(100).ToList(); @@ -665,20 +730,29 @@ public async Task ReceiverCanReadFromSequenceNumber(bool isInclusive) long lastSequence; EventPosition startingPosition; - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { - await SendEventsAsync(connectionString, seedEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, seedEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); await Task.Delay(250); lastSequence = (await producer.GetPartitionPropertiesAsync(partition, cancellationSource.Token)).LastEnqueuedSequenceNumber; startingPosition = EventPosition.FromSequenceNumber(lastSequence, isInclusive); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); } // Read the events and validate the resulting state. - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, startingPosition, connectionString)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + startingPosition, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var expectedCount = sourceEvents.Count; var expectedEvents = sourceEvents.Select(evt => evt.MessageId); @@ -720,8 +794,7 @@ public async Task ReceiverCanReadFromEnqueuedTime() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); var seedEvents = EventGenerator.CreateEvents(50).ToList(); var sourceEvents = EventGenerator.CreateEvents(100).ToList(); @@ -735,22 +808,31 @@ public async Task ReceiverCanReadFromEnqueuedTime() DateTimeOffset lastEnqueuedTime; EventPosition startingPosition; - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { - await SendEventsAsync(connectionString, seedEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, seedEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); await Task.Delay(TimeSpan.FromSeconds(2)); lastEnqueuedTime = (await producer.GetPartitionPropertiesAsync(partition, cancellationSource.Token)).LastEnqueuedTime; startingPosition = EventPosition.FromEnqueuedTime(lastEnqueuedTime); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); } // Read the events and validate the resulting state. - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, startingPosition, connectionString)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + startingPosition, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { - var readState = await ReadEventsAsync(receiver,sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); + var readState = await ReadEventsAsync(receiver, sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); // The exact number of events returned by the service may vary due to clock skew and how reader is positioned; ensure that @@ -785,14 +867,26 @@ public async Task ReceiverCanReadFromMultipleConsumerGroups() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateEvents(50).ToList(); - - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - - await using (var customReceiver = new PartitionReceiver(customConsumerGroup, partition, EventPosition.Earliest, connectionString)) - await using (var defaultReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString)) + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + + await using (var customReceiver = new PartitionReceiver( + customConsumerGroup, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) + + await using (var defaultReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var expectedEvents = sourceEvents.Select(evt => evt.MessageId); @@ -833,10 +927,20 @@ public async Task ReceiverCannotReadFromInvalidConsumerGroup() cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); var invalidConsumerGroup = "ThisIsFake"; - var partition = (await QueryPartitionsAsync(EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName), cancellationSource.Token)).First(); - - await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName)) - await using (var receiver = new PartitionReceiver(invalidConsumerGroup, partition, EventPosition.Earliest, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName)) + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + + await using (var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) + + await using (var receiver = new PartitionReceiver( + invalidConsumerGroup, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var readTask = ReadNothingAsync(receiver, cancellationSource.Token); @@ -868,9 +972,16 @@ public async Task ReceiverCannotReadWithInvalidProxy() clientOptions.ConnectionOptions.Proxy = new WebProxy("http://1.2.3.4:9999"); clientOptions.ConnectionOptions.TransportType = EventHubsTransportType.AmqpWebSockets; - var partition = (await QueryPartitionsAsync(EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName), cancellationSource.Token)).First(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); - await using (var invalidProxyReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, clientOptions)) + await using (var invalidProxyReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + clientOptions)) { // The sockets implementation in .NET Core on some platforms, such as Linux, does not trigger a specific socket exception and // will, instead, hang indefinitely. The try timeout is intentionally set to a value smaller than the cancellation token to @@ -895,16 +1006,20 @@ public async Task ReceiverCannotReadAcrossPartitions() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var credential = EventHubsTestEnvironment.Instance.Credential; var sourceEvents = EventGenerator.CreateEvents(50).ToList(); // Send events to the second partition, which should not be visible to the receiver. - var partitions = await QueryPartitionsAsync(connectionString, cancellationSource.Token); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partitions[1] }, cancellationSource.Token); + var partitions = await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partitions[1] }, cancellationSource.Token); - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partitions[0], EventPosition.Earliest, EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, credential)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partitions[0], + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { // Attempt to read from the empty partition and verify that no events are observed. Because no events are expected, the // read operation will not naturally complete; limit the read to only a couple of seconds and trigger cancellation. @@ -912,7 +1027,7 @@ public async Task ReceiverCannotReadAcrossPartitions() using var readCancellation = CancellationTokenSource.CreateLinkedTokenSource(cancellationSource.Token); readCancellation.CancelAfter(TimeSpan.FromSeconds(15)); - var readState = await ReadEventsAsync(receiver,sourceEvents.Select(evt => evt.MessageId), readCancellation.Token, waitTime: TimeSpan.FromMilliseconds(250)); + var readState = await ReadEventsAsync(receiver, sourceEvents.Select(evt => evt.MessageId), readCancellation.Token, waitTime: TimeSpan.FromMilliseconds(250)); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The main cancellation token should not have been signaled."); Assert.That(readState.Events.Count, Is.Zero, "No events should have been read from the empty partition."); @@ -936,13 +1051,19 @@ public async Task ReceiverCannotReadWhenClosed() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(100).ToList(); - - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, LowPrefetchOptions)) + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + LowPrefetchOptions)) { // Create a local function that will close the receiver after five events have // been read. Because the close happens during the read loop, allow for a short @@ -959,7 +1080,7 @@ async Task closeAfterFewRead(ReadState state) return true; } - var readTask = ReadEventsAsync(receiver,sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token, iterationCallback: closeAfterFewRead); + var readTask = ReadEventsAsync(receiver, sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token, iterationCallback: closeAfterFewRead); Assert.That(async () => await readTask, Throws.InstanceOf().And.Property(nameof(EventHubsException.Reason)).EqualTo(EventHubsException.FailureReason.ClientClosed)); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); @@ -982,14 +1103,22 @@ public async Task ReceiverCannotReadWhenSharedConnectionIsClosed() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(100).ToList(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await using (var connection = new EventHubConnection( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) - await using (var connection = new EventHubConnection(connectionString)) - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connection, LowPrefetchOptions)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + connection, + LowPrefetchOptions)) { // Create a local function that will close the connection after five events have // been read. Because the close happens during the read loop, allow for a short @@ -1006,7 +1135,7 @@ async Task closeAfterFewRead(ReadState state) return true; } - var readTask = ReadEventsAsync(receiver,sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token, iterationCallback: closeAfterFewRead); + var readTask = ReadEventsAsync(receiver, sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token, iterationCallback: closeAfterFewRead); Assert.That(async () => await readTask, Throws.InstanceOf().And.Property(nameof(EventHubsException.Reason)).EqualTo(EventHubsException.FailureReason.ClientClosed)); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); @@ -1029,7 +1158,13 @@ public async Task ReceiverCannotReadFromInvalidPartition() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, "-1", EventPosition.Earliest, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + "-1", + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var readTask = ReadNothingAsync(receiver, cancellationSource.Token); @@ -1054,13 +1189,19 @@ public async Task ReceiversWithAnIdentityCanRead() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(200).ToList(); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, new PartitionReceiverOptions { Identifier = "first" })) + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + new PartitionReceiverOptions { Identifier = "first" })) { var monitor = MonitorReadingEvents(receiver,sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token); @@ -1093,18 +1234,32 @@ public async Task MultipleReceiversCanReadConcurrently() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(200).ToList(); - var partitions = await QueryPartitionsAsync(connectionString, cancellationSource.Token); + var partitions = await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token); await Task.WhenAll ( - SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partitions[0] }, cancellationSource.Token), - SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partitions[1] }, cancellationSource.Token) + SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partitions[0] }, cancellationSource.Token), + SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partitions[1] }, cancellationSource.Token) ); - await using (var firstReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partitions[0], EventPosition.Earliest, connectionString, new PartitionReceiverOptions { Identifier = "first" })) - await using (var secondReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partitions[1], EventPosition.Earliest, connectionString, new PartitionReceiverOptions { Identifier = "second" })) + await using (var firstReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partitions[0], + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + new PartitionReceiverOptions { Identifier = "first" })) + + await using (var secondReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partitions[1], + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + new PartitionReceiverOptions { Identifier = "second" })) { var expectedEvents = sourceEvents.Select(evt => evt.MessageId); var firstMonitor = MonitorReadingEvents(firstReceiver, expectedEvents, cancellationSource.Token); @@ -1147,14 +1302,28 @@ public async Task ReceiverCannotReadAsNonExclusiveWhenAnExclusiveReaderIsActive( cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); var exclusiveOptions = new PartitionReceiverOptions { OwnerLevel = 20, PrefetchCount = LowPrefetchCount }; - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(200).ToList(); - - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - - await using (var exclusiveReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, exclusiveOptions)) - await using (var nonExclusiveReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, LowPrefetchOptions)) + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + + await using (var exclusiveReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + exclusiveOptions)) + + await using (var nonExclusiveReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + LowPrefetchOptions)) { var exclusiveMonitor = MonitorReadingEvents(exclusiveReceiver, null, cancellationSource.Token); await Task.WhenAny(exclusiveMonitor.StartCompletion.Task, Task.Delay(Timeout.Infinite, cancellationSource.Token)); @@ -1185,14 +1354,28 @@ public async Task ReceiverCannotReadWithLowerOwnerLevelThanActiveReader() var higherOptions = new PartitionReceiverOptions { OwnerLevel = 40, PrefetchCount = LowPrefetchCount }; var lowerOptions = new PartitionReceiverOptions { OwnerLevel = 20, PrefetchCount = LowPrefetchCount }; - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(200).ToList(); - - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - - await using (var higherReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, higherOptions)) - await using (var lowerReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, lowerOptions)) + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + + await using (var higherReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + higherOptions)) + + await using (var lowerReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + lowerOptions)) { var expectedEvents = sourceEvents.Select(evt => evt.MessageId); @@ -1225,23 +1408,37 @@ public async Task ReceiverCanReadFromMultiplePartitionsWithDifferentActiveOwnerL var higherOptions = new PartitionReceiverOptions { OwnerLevel = 40, PrefetchCount = LowPrefetchCount }; var lowerOptions = new PartitionReceiverOptions { OwnerLevel = 20, PrefetchCount = LowPrefetchCount }; - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(200).ToList(); - var partitions = await QueryPartitionsAsync(connectionString, cancellationSource.Token); + var partitions = await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token); // Send the same set of events to both partitions. await Task.WhenAll ( - SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partitions[0] }, cancellationSource.Token), - SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partitions[1] }, cancellationSource.Token) + SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partitions[0] }, cancellationSource.Token), + SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partitions[1] }, cancellationSource.Token) ); // Read from each partition, allowing the higher level operation to begin first. Both read operations should be // successful and read all events from their respective partition. - await using (var higherReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partitions[0], EventPosition.Earliest, connectionString, higherOptions)) - await using (var lowerReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partitions[1], EventPosition.Earliest, connectionString, lowerOptions)) + await using (var higherReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partitions[0], + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + higherOptions)) + + await using (var lowerReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partitions[1], + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + lowerOptions)) { var expectedEvents = sourceEvents.Select(evt => evt.MessageId); var higherMonitor = MonitorReadingEvents(higherReceiver, expectedEvents, cancellationSource.Token); @@ -1279,14 +1476,28 @@ public async Task ReceiverCanReadFromMultipleConsumerGroupsWithDifferentActiveOw var higherOptions = new PartitionReceiverOptions { OwnerLevel = 40, PrefetchCount = LowPrefetchCount }; var lowerOptions = new PartitionReceiverOptions { OwnerLevel = 20, PrefetchCount = LowPrefetchCount }; - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(200).ToList(); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - - await using (var higherReceiver = new PartitionReceiver(scope.ConsumerGroups[0], partition, EventPosition.Earliest, connectionString, higherOptions)) - await using (var lowerReceiver = new PartitionReceiver(scope.ConsumerGroups[1], partition, EventPosition.Earliest, connectionString, lowerOptions)) + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + + await using (var higherReceiver = new PartitionReceiver( + scope.ConsumerGroups[0], + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + higherOptions)) + + await using (var lowerReceiver = new PartitionReceiver( + scope.ConsumerGroups[1], + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + lowerOptions)) { // Read from each partition, allowing the higher level operation to begin first. Both read operations should be // successful and read all events from their respective partition. @@ -1324,15 +1535,29 @@ public async Task ExclusiveReceiverSupercedesNonExclusiveActiveReader() cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); var exclusiveOptions = new PartitionReceiverOptions { OwnerLevel = 20, PrefetchCount = LowPrefetchCount }; - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(200).ToList(); var expectedEvents = sourceEvents.Select(evt => evt.MessageId); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - - await using (var nonExclusiveReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, LowPrefetchOptions)) - await using (var exclusiveReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, exclusiveOptions)) + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + + await using (var nonExclusiveReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + LowPrefetchOptions)) + + await using (var exclusiveReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + exclusiveOptions)) { // Start the non-exclusive read, waiting until at least some events were read before starting the exclusive reader. @@ -1382,15 +1607,29 @@ public async Task ReceiverWithHigherOwnerLevelSupercedesActiveReader() var higherOptions = new PartitionReceiverOptions { OwnerLevel = 40, PrefetchCount = LowPrefetchCount }; var lowerOptions = new PartitionReceiverOptions { OwnerLevel = 20, PrefetchCount = LowPrefetchCount }; - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(200).ToList(); var expectedEvents = sourceEvents.Select(evt => evt.MessageId); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - - await using (var higherReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, higherOptions)) - await using (var lowerReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, lowerOptions)) + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + + await using (var higherReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + higherOptions)) + + await using (var lowerReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + lowerOptions)) { // Start the lower level read, waiting until at least some events were read before starting the higher reader. @@ -1431,7 +1670,7 @@ public async Task ReceiverWithHigherOwnerLevelSupercedesActiveReader() /// /// [Test] - public async Task ExclusiveReceiverDoesNotSupercedNonExclusiveActiveReaderOnAnotherPartition() + public async Task ExclusiveReceiverDoesNotSupersedeNonExclusiveActiveReaderOnAnotherPartition() { await using (EventHubScope scope = await EventHubScope.CreateAsync(2)) { @@ -1439,21 +1678,35 @@ public async Task ExclusiveReceiverDoesNotSupercedNonExclusiveActiveReaderOnAnot cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); var exclusiveOptions = new PartitionReceiverOptions { OwnerLevel = 20, PrefetchCount = LowPrefetchCount }; - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(200).ToList(); var expectedEvents = sourceEvents.Select(evt => evt.MessageId); - var partitions = await QueryPartitionsAsync(connectionString, cancellationSource.Token); + var partitions = await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token); // Send the same set of events to both partitions. await Task.WhenAll ( - SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partitions[0] }, cancellationSource.Token), - SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partitions[1] }, cancellationSource.Token) + SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partitions[0] }, cancellationSource.Token), + SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partitions[1] }, cancellationSource.Token) ); - await using (var nonExclusiveReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partitions[0], EventPosition.Earliest, connectionString, LowPrefetchOptions)) - await using (var exclusiveReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partitions[1], EventPosition.Earliest, connectionString, exclusiveOptions)) + await using (var nonExclusiveReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partitions[0], + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + LowPrefetchOptions)) + + await using (var exclusiveReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partitions[1], + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + exclusiveOptions)) { // Start the non-exclusive read, waiting until at least some events were read before starting the exclusive reader. @@ -1493,7 +1746,7 @@ await Task.WhenAll /// /// [Test] - public async Task ExclusiveReceiverDoesNotSupercedNonExclusiveActiveReaderOnAnotherConsumerGroup() + public async Task ExclusiveReceiverDoesNotSupersedeNonExclusiveActiveReaderOnAnotherConsumerGroup() { var ConsumerGroups = new[] { "customGroup", "customTwo" }; @@ -1503,15 +1756,29 @@ public async Task ExclusiveReceiverDoesNotSupercedNonExclusiveActiveReaderOnAnot cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); var exclusiveOptions = new PartitionReceiverOptions { OwnerLevel = 20, PrefetchCount = LowPrefetchCount }; - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(200).ToList(); var expectedEvents = sourceEvents.Select(evt => evt.MessageId); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - - await using (var nonExclusiveReceiver = new PartitionReceiver(scope.ConsumerGroups[0], partition, EventPosition.Earliest, connectionString, LowPrefetchOptions)) - await using (var exclusiveReceiver = new PartitionReceiver(scope.ConsumerGroups[1], partition, EventPosition.Earliest, connectionString, exclusiveOptions)) + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + + await using (var nonExclusiveReceiver = new PartitionReceiver( + scope.ConsumerGroups[0], + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + LowPrefetchOptions)) + + await using (var exclusiveReceiver = new PartitionReceiver( + scope.ConsumerGroups[1], + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + exclusiveOptions)) { // Start the non-exclusive read, waiting until at least some events were read before starting the exclusive reader. @@ -1560,15 +1827,29 @@ public async Task ReceiverIsNotCompromisedByBeingSupercededByAnotherReaderWithHi var higherOptions = new PartitionReceiverOptions { OwnerLevel = 40, PrefetchCount = LowPrefetchCount }; var lowerOptions = new PartitionReceiverOptions { OwnerLevel = 20, PrefetchCount = LowPrefetchCount }; - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var sourceEvents = EventGenerator.CreateSmallEvents(200).ToList(); var expectedEvents = sourceEvents.Select(evt => evt.MessageId); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - await SendEventsAsync(connectionString, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); - - await using (var higherReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, higherOptions)) - await using (var lowerReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, lowerOptions)) + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + await SendEventsAsync(scope.EventHubName, sourceEvents, new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + + await using (var higherReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + higherOptions)) + + await using (var lowerReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + lowerOptions)) { // Start the lower level read, waiting until at least some events were read before starting the higher reader. @@ -1619,12 +1900,11 @@ public async Task ExclusiveReceiverDetectsAnotherExclusiveReaderWithSameLevel() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); // Seed the partition with events. - await SendEventsAsync(connectionString, EventGenerator.CreateSmallEvents(250), new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, EventGenerator.CreateSmallEvents(250), new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Create the receivers and read concurrently in the background until the initial receiver recognizes the partition has been stolen. @@ -1633,8 +1913,23 @@ public async Task ExclusiveReceiverDetectsAnotherExclusiveReaderWithSameLevel() var capturedException = default(Exception); var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - await using var firstReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, receiverOptions); - await using var secondReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, receiverOptions); + await using var firstReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + receiverOptions); + + await using var secondReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + receiverOptions); var firstReceiverTask = Task.Run(async () => { @@ -1709,12 +2004,11 @@ public async Task ExclusiveReceiverCanReassertOwnershipFromAnotherExclusiveReade using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); // Seed the partition with events. - await SendEventsAsync(connectionString, EventGenerator.CreateSmallEvents(250), new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); + await SendEventsAsync(scope.EventHubName, EventGenerator.CreateSmallEvents(250), new CreateBatchOptions { PartitionId = partition }, cancellationSource.Token); // Create the receivers and read concurrently in the background until the initial receiver recognizes the partition has been stolen. @@ -1723,8 +2017,23 @@ public async Task ExclusiveReceiverCanReassertOwnershipFromAnotherExclusiveReade var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var secondReceiverStolen = false; - await using var firstReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, receiverOptions); - await using var secondReceiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, receiverOptions); + await using var firstReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + receiverOptions); + + await using var secondReceiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + receiverOptions); var firstReceiverTask = Task.Run(async () => { @@ -1826,10 +2135,15 @@ public async Task ReceiverRespectsTheWaitTimeWhenReading() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential)) { var waitTime = TimeSpan.FromMilliseconds(100); var desiredEmptyBatches = 10; @@ -1869,8 +2183,7 @@ public async Task ReceiverCanReadEventsWithAFullyPopulatedAmqpMessage() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); var message = new AmqpAnnotatedMessage(AmqpMessageBody.FromData(new ReadOnlyMemory[] { new byte[] { 0x11, 0x22, 0x33 } })); var eventData = new EventData(message); @@ -1921,10 +2234,21 @@ public async Task ReceiverCanReadEventsWithAFullyPopulatedAmqpMessage() // Publish the event and then read it back. - await using var producer = new EventHubProducerClient(connectionString); + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential); + await producer.SendAsync(new[] { eventData }, new SendEventOptions { PartitionId = partition }); - await using var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString); + await using var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential); + var readState = await ReadEventsAsync(receiver, new HashSet { eventData.MessageId }, cancellationSource.Token); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); @@ -1980,8 +2304,7 @@ public async Task ReceiverCanReadEventsWithAValueBody() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); var value = new Dictionary { { "key", "value" } }; var message = new AmqpAnnotatedMessage(AmqpMessageBody.FromValue(value)); var eventData = new EventData(message) { MessageId = Guid.NewGuid().ToString() }; @@ -1990,10 +2313,21 @@ public async Task ReceiverCanReadEventsWithAValueBody() // Publish the event and then read it back. - await using var producer = new EventHubProducerClient(connectionString); + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential); + await producer.SendAsync(new[] { eventData }, new SendEventOptions { PartitionId = partition }); - await using var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString); + await using var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential); + var readState = await ReadEventsAsync(receiver, new HashSet { eventData.MessageId }, cancellationSource.Token); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); @@ -2024,8 +2358,7 @@ public async Task ReceiverCanReadEventsWithASequenceBody() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); var value = new[] { new List { "1", 2 } }; var message = new AmqpAnnotatedMessage(AmqpMessageBody.FromSequence(value)); var eventData = new EventData(message) { MessageId = Guid.NewGuid().ToString() }; @@ -2034,10 +2367,21 @@ public async Task ReceiverCanReadEventsWithASequenceBody() // Publish the event and then read it back. - await using var producer = new EventHubProducerClient(connectionString); + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential); + await producer.SendAsync(new[] { eventData }, new SendEventOptions { PartitionId = partition }); - await using var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString); + await using var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential); + var readState = await ReadEventsAsync(receiver, new HashSet { eventData.MessageId }, cancellationSource.Token); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); @@ -2072,11 +2416,17 @@ public async Task ReceiverCanRetrievePartitionProperties(EventHubsTransportType using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var receiverOptions = new PartitionReceiverOptions { ConnectionOptions = new EventHubConnectionOptions { TransportType = transportType } }; - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); - - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, receiverOptions)) + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); + + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + receiverOptions)) { var partitionProperties = await receiver.GetPartitionPropertiesAsync(cancellationSource.Token); Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); @@ -2104,14 +2454,20 @@ public async Task ReceiverCannotRetrievePartitionPropertiesWhenConnectionIsClose using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var connection = new EventHubConnection(connectionString); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); + var connection = new EventHubConnection( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential); + + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connection)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + connection)) { Assert.That(async () => await receiver.GetPartitionPropertiesAsync(cancellationSource.Token), Throws.Nothing); - await connection.CloseAsync(cancellationSource.Token); Assert.That(async () => await receiver.GetPartitionPropertiesAsync(cancellationSource.Token), Throws.InstanceOf().And.Property(nameof(EventHubsException.Reason)).EqualTo(EventHubsException.FailureReason.ClientClosed)); @@ -2133,8 +2489,7 @@ public async Task ReceiverCannotRetrieveMetadataWithInvalidProxy() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var partition = (await QueryPartitionsAsync(connectionString, cancellationSource.Token)).First(); + var partition = (await QueryPartitionsAsync(scope.EventHubName, cancellationSource.Token)).First(); var invalidProxyOptions = new PartitionReceiverOptions(); invalidProxyOptions.RetryOptions.MaximumRetries = 0; @@ -2143,7 +2498,14 @@ public async Task ReceiverCannotRetrieveMetadataWithInvalidProxy() invalidProxyOptions.ConnectionOptions.Proxy = new WebProxy("http://1.2.3.4:9999"); invalidProxyOptions.ConnectionOptions.TransportType = EventHubsTransportType.AmqpWebSockets; - await using (var receiver = new PartitionReceiver(EventHubConsumerClient.DefaultConsumerGroupName, partition, EventPosition.Earliest, connectionString, invalidProxyOptions)) + await using (var receiver = new PartitionReceiver( + EventHubConsumerClient.DefaultConsumerGroupName, + partition, + EventPosition.Earliest, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + invalidProxyOptions)) { // The sockets implementation in .NET Core on some platforms, such as Linux, does not trigger a specific socket exception and // will, instead, hang indefinitely. The try timeout is intentionally set to a value smaller than the cancellation token to @@ -2159,15 +2521,18 @@ public async Task ReceiverCannotRetrieveMetadataWithInvalidProxy() /// Reads the list of partition identifiers for an Event Hub instance. /// /// - /// The connection string to use when creating the producer. + /// The Event Hub Name to use when creating the producer. /// The token used to signal a cancellation request. /// /// The set of partition identifiers. /// - private async Task QueryPartitionsAsync(string connectionString, + private async Task QueryPartitionsAsync(string eventHubName, CancellationToken cancellationToken = default) { - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + eventHubName, + EventHubsTestEnvironment.Instance.Credential)) { return await producer.GetPartitionIdsAsync(cancellationToken); } @@ -2177,21 +2542,24 @@ private async Task QueryPartitionsAsync(string connectionString, /// Sends a set of events using a new producer to do so. /// /// - /// The connection string to use when creating the producer. + /// The Event Hub Name to use when creating the producer. /// The set of events to send. /// The set of options to apply when creating batches. /// The token used to signal a cancellation request. /// /// The count of events that were sent. /// - private async Task SendEventsAsync(string connectionString, + private async Task SendEventsAsync(string eventHubName, IEnumerable sourceEvents, CreateBatchOptions batchOptions = default, CancellationToken cancellationToken = default) { var sentCount = 0; - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + eventHubName, + EventHubsTestEnvironment.Instance.Credential)) { foreach (var batch in (await EventGenerator.BuildBatchesAsync(sourceEvents, producer, batchOptions, cancellationToken))) { diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Producer/EventHubBufferedProducerClientLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Producer/EventHubBufferedProducerClientLiveTests.cs index e7cfd9cf875f1..18882e31e5301 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Producer/EventHubBufferedProducerClientLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Producer/EventHubBufferedProducerClientLiveTests.cs @@ -53,7 +53,7 @@ public async Task ProducerCanPublishRoundRobinWithDefaultOptions() var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); producer.SendEventBatchSucceededAsync += args => { @@ -103,7 +103,10 @@ public async Task ProducerCanPublishRoundRobinWithDefaultOptions() // Read back the events and ensure all were successfully published. - await using var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var consumerClient = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); await foreach (var partitionEvent in consumerClient.ReadEventsAsync(cancellationSource.Token)) { @@ -148,7 +151,7 @@ public async Task ProducerCanPublishUsingPartitionKeysWithDefaultOptions() var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); producer.SendEventBatchSucceededAsync += args => { @@ -206,7 +209,10 @@ public async Task ProducerCanPublishUsingPartitionKeysWithDefaultOptions() // Read back the events and ensure all were successfully published. - await using var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var consumerClient = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); await foreach (var partitionEvent in consumerClient.ReadEventsAsync(cancellationSource.Token)) { @@ -251,7 +257,7 @@ public async Task ProducerCanPublishToPartitionIdsWithDefaultOptions() var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); var partitions = await producer.GetPartitionIdsAsync(cancellationSource.Token); @@ -311,7 +317,10 @@ public async Task ProducerCanPublishToPartitionIdsWithDefaultOptions() // Read back the events and ensure all were successfully published. - await using var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var consumerClient = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); await foreach (var partitionEvent in consumerClient.ReadEventsAsync(cancellationSource.Token)) { @@ -355,7 +364,7 @@ public async Task ProducerCanPublishHeterogeneousEventsWithDefaultOptions() var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); var partitions = await producer.GetPartitionIdsAsync(cancellationSource.Token); @@ -421,7 +430,10 @@ public async Task ProducerCanPublishHeterogeneousEventsWithDefaultOptions() // Read back the events and ensure all were successfully published. - await using var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var consumerClient = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); await foreach (var partitionEvent in consumerClient.ReadEventsAsync(cancellationSource.Token)) { @@ -467,7 +479,7 @@ public async Task ProducerCanPublishWithRestrictedConcurrency() var options = new EventHubBufferedProducerClientOptions { MaximumConcurrentSends = concurrentSends }; await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, options); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, options); var partitions = await producer.GetPartitionIdsAsync(cancellationSource.Token); @@ -533,7 +545,10 @@ public async Task ProducerCanPublishWithRestrictedConcurrency() // Read back the events and ensure all were successfully published. - await using var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var consumerClient = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); await foreach (var partitionEvent in consumerClient.ReadEventsAsync(cancellationSource.Token)) { @@ -582,7 +597,7 @@ public async Task ProducerCanPublishWithConcurrentPartitions() }; await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, options); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, options); producer.SendEventBatchSucceededAsync += args => { @@ -632,7 +647,10 @@ public async Task ProducerCanPublishWithConcurrentPartitions() // Read back the events and ensure all were successfully published. - await using var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var consumerClient = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); await foreach (var partitionEvent in consumerClient.ReadEventsAsync(cancellationSource.Token)) { @@ -686,7 +704,7 @@ public async Task ProducerCanPublishAfterIdle() .Callback(() => idleCompletionSource.TrySetResult(true)); await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); var partitions = await producer.GetPartitionIdsAsync(cancellationSource.Token); @@ -760,7 +778,10 @@ public async Task ProducerCanPublishAfterIdle() // Read back the events and ensure all were successfully published. - await using var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var consumerClient = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); await foreach (var partitionEvent in consumerClient.ReadEventsAsync(cancellationSource.Token)) { @@ -806,7 +827,7 @@ public async Task ProducerCanPublishAfterFlush() var options = new EventHubBufferedProducerClientOptions { MaximumConcurrentSends = eventSetCount }; await using var scope = await EventHubScope.CreateAsync(1); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, options); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, options); producer.SendEventBatchSucceededAsync += args => { @@ -846,7 +867,10 @@ public async Task ProducerCanPublishAfterFlush() // Read back the events and ensure all were successfully published. - await using var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var consumerClient = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); await foreach (var partitionEvent in consumerClient.ReadEventsAsync(cancellationSource.Token)) { @@ -894,7 +918,7 @@ public async Task FlushSendsAllEventsAndWaitsForHandlersWithDefaultOptions() var options = new EventHubBufferedProducerClientOptions { MaximumConcurrentSends = partitionCount }; await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, options); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, options); producer.SendEventBatchSucceededAsync += args => { @@ -940,7 +964,10 @@ public async Task FlushSendsAllEventsAndWaitsForHandlersWithDefaultOptions() // Read back the events and ensure all were successfully published. - await using var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var consumerClient = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); await foreach (var partitionEvent in consumerClient.ReadEventsAsync(cancellationSource.Token)) { @@ -995,7 +1022,7 @@ public async Task FlushSendsAllEventsAndWaitsForHandlersWithConcurrentPartitions }; await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, options); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, options); producer.SendEventBatchSucceededAsync += args => { @@ -1041,7 +1068,10 @@ public async Task FlushSendsAllEventsAndWaitsForHandlersWithConcurrentPartitions // Read back the events and ensure all were successfully published. - await using var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var consumerClient = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); await foreach (var partitionEvent in consumerClient.ReadEventsAsync(cancellationSource.Token)) { @@ -1089,7 +1119,7 @@ public async Task CloseSendsAllEventsAndWaitsForHandlersWhenFlushingWithDefaultO var options = new EventHubBufferedProducerClientOptions { MaximumConcurrentSends = partitionCount }; await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, options); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, options); producer.SendEventBatchSucceededAsync += args => { @@ -1135,7 +1165,10 @@ public async Task CloseSendsAllEventsAndWaitsForHandlersWhenFlushingWithDefaultO // Read back the events and ensure all were successfully published. - await using var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var consumerClient = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); await foreach (var partitionEvent in consumerClient.ReadEventsAsync(cancellationSource.Token)) { @@ -1185,7 +1218,7 @@ public async Task CloseSendsAllEventsAndWaitsForHandlersWhenFlushingWithConcurre }; await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, options); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, options); producer.SendEventBatchSucceededAsync += args => { @@ -1231,7 +1264,10 @@ public async Task CloseSendsAllEventsAndWaitsForHandlersWhenFlushingWithConcurre // Read back the events and ensure all were successfully published. - await using var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var consumerClient = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); await foreach (var partitionEvent in consumerClient.ReadEventsAsync(cancellationSource.Token)) { @@ -1273,7 +1309,7 @@ public async Task CloseAbandonsEventsAndHandlersWhenClearingWithDefaultOptions() var options = new EventHubBufferedProducerClientOptions { MaximumConcurrentSends = partitionCount }; await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, options); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, options); producer.SendEventBatchFailedAsync += args => { @@ -1319,7 +1355,7 @@ public async Task CloseAbandonsEventsAndHandlersWhenClearingWithConcurrentPartit }; await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, options); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, options); producer.SendEventBatchFailedAsync += args => { @@ -1373,7 +1409,7 @@ public async Task CloseSendsEventsWhenFlushingAfterIdle() .Callback(() => idleCompletionSource.TrySetResult(true)); await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, options); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, options); producer.Logger = mockLogger.Object; @@ -1433,7 +1469,10 @@ public async Task CloseSendsEventsWhenFlushingAfterIdle() // Read back the events and ensure all were successfully published. - await using var consumerClient = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var consumerClient = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); await foreach (var partitionEvent in consumerClient.ReadEventsAsync(cancellationSource.Token)) { @@ -1483,7 +1522,7 @@ public async Task CloseIsSuccessfulWhileIdle() .Callback(() => completionSource.TrySetResult(true)); await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, options); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, options); producer.Logger = mockLogger.Object; producer.SendEventBatchSucceededAsync += args => Task.CompletedTask; @@ -1523,11 +1562,10 @@ public async Task CloseIsSuccessfulWhileIdle() public async Task ProducerCanRetrieveEventHubProperties(EventHubsTransportType transportType) { var partitionCount = 4; - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var producerOptions = new EventHubBufferedProducerClientOptions { ConnectionOptions = new EventHubConnectionOptions { TransportType = transportType } }; await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(connectionString, scope.EventHubName, producerOptions); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, producerOptions); var properties = await producer.GetEventHubPropertiesAsync(); @@ -1548,11 +1586,10 @@ public async Task ProducerCanRetrieveEventHubProperties(EventHubsTransportType t public async Task ProducerCanRetrievePartitionProperties(EventHubsTransportType transportType) { var partitionCount = 4; - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var producerOptions = new EventHubBufferedProducerClientOptions { ConnectionOptions = new EventHubConnectionOptions { TransportType = transportType } }; await using var scope = await EventHubScope.CreateAsync(partitionCount); - await using var producer = new EventHubBufferedProducerClient(connectionString, scope.EventHubName, producerOptions); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, producerOptions); var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(20)); var properties = await producer.GetEventHubPropertiesAsync(); @@ -1576,7 +1613,7 @@ public async Task ProducerCanRetrievePartitionProperties(EventHubsTransportType public async Task ConnectionTransportPartitionIdsMatchPartitionProperties() { await using var scope = await EventHubScope.CreateAsync(4); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); var properties = await producer.GetEventHubPropertiesAsync(); var partitions = await producer.GetPartitionIdsAsync(); @@ -1596,7 +1633,7 @@ public async Task ConnectionTransportPartitionIdsMatchPartitionProperties() public async Task ProducerCannotRetrieveMetadataWhenClosed() { await using var scope = await EventHubScope.CreateAsync(1); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); var partition = (await producer.GetPartitionIdsAsync()).First(); @@ -1624,7 +1661,7 @@ public async Task ProducerCannotRetrieveMetadataWhenClosed() public async Task ProducerCannotRetrievePartitionPropertiesWhenPartitionIdIsInvalid(string invalidPartition) { await using var scope = await EventHubScope.CreateAsync(1); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); Assert.That(async () => await producer.GetPartitionPropertiesAsync(invalidPartition), Throws.TypeOf()); } @@ -1649,8 +1686,8 @@ public async Task ProducerCannotRetrieveMetadataWhenProxyIsInvalid() }; await using var scope = await EventHubScope.CreateAsync(1); - await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); - await using var invalidProxyProducer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName, invalidProxyOptions); + await using var producer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); + await using var invalidProxyProducer = new EventHubBufferedProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, invalidProxyOptions); var partition = (await producer.GetPartitionIdsAsync()).First(); diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Producer/EventHubProducerClientLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Producer/EventHubProducerClientLiveTests.cs index 05cdb4dcf1f5d..38bb0890967f1 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Producer/EventHubProducerClientLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Producer/EventHubProducerClientLiveTests.cs @@ -14,7 +14,6 @@ using Azure.Messaging.EventHubs.Consumer; using Azure.Messaging.EventHubs.Core; using Azure.Messaging.EventHubs.Producer; -using Microsoft.Azure.Amqp.Framing; using NUnit.Framework; namespace Azure.Messaging.EventHubs.Tests @@ -52,9 +51,7 @@ public async Task ProducerWithNoOptionsCanSend(EventHubsTransportType transportT { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var connection = new EventHubConnection(connectionString, new EventHubConnectionOptions { TransportType = transportType })) + await using (var connection = new EventHubConnection(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, new EventHubConnectionOptions { TransportType = transportType })) await using (var producer = new EventHubProducerClient(connection)) { EventData[] events = new[] { new EventData(Encoding.UTF8.GetBytes("AWord")) }; @@ -75,15 +72,13 @@ public async Task ProducerWithOptionsCanSend(EventHubsTransportType transportTyp { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var producerOptions = new EventHubProducerClientOptions { RetryOptions = new EventHubsRetryOptions { MaximumRetries = 5 }, ConnectionOptions = new EventHubConnectionOptions { TransportType = transportType } }; - await using (var producer = new EventHubProducerClient(connectionString, producerOptions)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, producerOptions)) { EventData[] events = new[] { new EventData(Encoding.UTF8.GetBytes("AWord")) }; Assert.That(async () => await producer.SendAsync(events), Throws.Nothing); @@ -103,8 +98,6 @@ public async Task ProducerWithCustomBufferSizesCanSend(EventHubsTransportType tr { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var producerOptions = new EventHubProducerClientOptions { ConnectionOptions = new EventHubConnectionOptions @@ -114,7 +107,7 @@ public async Task ProducerWithCustomBufferSizesCanSend(EventHubsTransportType tr } }; - await using (var producer = new EventHubProducerClient(connectionString, producerOptions)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, producerOptions)) { EventData[] events = new[] { new EventData(Encoding.UTF8.GetBytes("AWord")) }; Assert.That(async () => await producer.SendAsync(events), Throws.Nothing); @@ -132,9 +125,7 @@ public async Task ProducerWithIdentifierCanSend() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var producer = new EventHubProducerClient(connectionString, new EventHubProducerClientOptions { Identifier = "CustomIdentif13r!" })) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, new EventHubProducerClientOptions { Identifier = "CustomIdentif13r!" })) { var events = new[] { new EventData(Encoding.UTF8.GetBytes("AWord")) }; Assert.That(async () => await producer.SendAsync(events), Throws.Nothing); @@ -151,7 +142,7 @@ public async Task ProducerWithIdentifierCanSend() public async Task ProducerCanSendToASpecificPartition() { await using EventHubScope scope = await EventHubScope.CreateAsync(4); - await using var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); @@ -177,8 +168,9 @@ public async Task ProducerCanSendToASpecificPartition() await using var consumer = new EventHubConsumerClient( EventHubConsumerClient.DefaultConsumerGroupName, - EventHubsTestEnvironment.Instance.EventHubsConnectionString, - scope.EventHubName); + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential); try { @@ -212,7 +204,7 @@ public async Task ProducerCanSendToASpecificPartition() public async Task ProducerCanSendAnEventBatchToASpecificPartition() { await using EventHubScope scope = await EventHubScope.CreateAsync(4); - await using var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); @@ -245,8 +237,9 @@ public async Task ProducerCanSendAnEventBatchToASpecificPartition() await using var consumer = new EventHubConsumerClient( EventHubConsumerClient.DefaultConsumerGroupName, - EventHubsTestEnvironment.Instance.EventHubsConnectionString, - scope.EventHubName); + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential); try { @@ -295,9 +288,7 @@ public async Task ProducerCanSendEventsWithCustomProperties() events[index].Properties["Type"] = $"com.microsoft.test.Type{ index }"; } - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { Assert.That(async () => await producer.SendAsync(events), Throws.Nothing); } @@ -313,7 +304,7 @@ public async Task ProducerCanSendEventsWithCustomProperties() public async Task ProducerCanSendEventsUsingAPartitionHashKey() { await using EventHubScope scope = await EventHubScope.CreateAsync(4); - await using var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); @@ -339,8 +330,9 @@ public async Task ProducerCanSendEventsUsingAPartitionHashKey() await using var consumer = new EventHubConsumerClient( EventHubConsumerClient.DefaultConsumerGroupName, - EventHubsTestEnvironment.Instance.EventHubsConnectionString, - scope.EventHubName); + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential); try { @@ -379,7 +371,7 @@ public async Task ProducerCanSendEventsUsingAPartitionHashKey() public async Task ProducerCanSendAnEventBatchUsingAPartitionHashKey() { await using EventHubScope scope = await EventHubScope.CreateAsync(4); - await using var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName); + await using var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); @@ -412,8 +404,9 @@ public async Task ProducerCanSendAnEventBatchUsingAPartitionHashKey() await using var consumer = new EventHubConsumerClient( EventHubConsumerClient.DefaultConsumerGroupName, - EventHubsTestEnvironment.Instance.EventHubsConnectionString, - scope.EventHubName); + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential); try { @@ -453,13 +446,14 @@ public async Task ProducerCanSendSingleLargeEventInASet() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var producer = new EventHubProducerClient(connectionString, new EventHubProducerClientOptions { RetryOptions = new EventHubsRetryOptions { TryTimeout = TimeSpan.FromMinutes(5) } })) + await using (var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + new EventHubProducerClientOptions { RetryOptions = new EventHubsRetryOptions { TryTimeout = TimeSpan.FromMinutes(5) } })) { // Actual limit is 1046520 for a single event. EventData[] eventSet = new[] { new EventData(new byte[100000]) }; - Assert.That(async () => await producer.SendAsync(eventSet), Throws.Nothing); } } @@ -475,9 +469,7 @@ public async Task ProducerCanSendASetOfEvents() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { EventData[] events = new[] { @@ -501,9 +493,7 @@ public async Task ProducerCanSendZeroLengthSet() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { EventData[] events = new[] { @@ -527,9 +517,11 @@ public async Task ProducerCanSendLargeSet() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var producer = new EventHubProducerClient(connectionString, new EventHubProducerClientOptions { RetryOptions = new EventHubsRetryOptions { TryTimeout = TimeSpan.FromMinutes(5) } })) + await using (var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + new EventHubProducerClientOptions { RetryOptions = new EventHubsRetryOptions { TryTimeout = TimeSpan.FromMinutes(5) } })) { // Actual limit is 1046520 for a single event. EventData[] events = new[] @@ -554,9 +546,7 @@ public async Task ProducerCanSendAnEventBatch() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { using EventDataBatch batch = await producer.CreateBatchAsync(); @@ -576,13 +566,13 @@ public async Task ProducerCanSendAnEventBatch() /// /// [Test] - public async Task ProducerCanSendAnEventBatchUsingAnIdentityCredential() + public async Task ProducerCanSendAnEventBatchUsingAConnectionString() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { var credential = EventHubsTestEnvironment.Instance.Credential; - await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, credential)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.EventHubsConnectionString, scope.EventHubName)) { using EventDataBatch batch = await producer.CreateBatchAsync(); @@ -667,9 +657,7 @@ public async Task ProducerCanSendZeroLengthEventBatch() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { using EventDataBatch batch = await producer.CreateBatchAsync(); batch.TryAdd(new EventData(new BinaryData(Array.Empty()))); @@ -690,9 +678,11 @@ public async Task ProducerCanSendLargeEventBatch() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var producer = new EventHubProducerClient(connectionString, new EventHubProducerClientOptions { RetryOptions = new EventHubsRetryOptions { TryTimeout = TimeSpan.FromMinutes(5) } })) + await using (var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + new EventHubProducerClientOptions { RetryOptions = new EventHubsRetryOptions { TryTimeout = TimeSpan.FromMinutes(5) } })) { using EventDataBatch batch = await producer.CreateBatchAsync(); @@ -718,9 +708,7 @@ public async Task ProducerCanSendWithBinaryApplicationProperties() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using var producer = new EventHubProducerClient(connectionString); + await using var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); var eventData = new EventData(Encoding.UTF8.GetBytes("AWord")); eventData.Properties["TestByteArray"] = new byte[] { 0x12, 0x34, 0x56, 0x78 }; @@ -740,9 +728,7 @@ public async Task ProducerCannotSendSetLargerThanMaximumSize() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { // Actual limit is 1046520 for a single event. @@ -768,9 +754,7 @@ public async Task ProducerCanSendWhenPartitionIsNull() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { EventData[] events = new[] { new EventData(Encoding.UTF8.GetBytes("Will it work")) }; Assert.That(async () => await producer.SendAsync(events, new SendEventOptions { PartitionId = null }), Throws.Nothing); @@ -788,9 +772,7 @@ public async Task ProducerCannotSendWhenClosed() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { EventData[] events = new[] { new EventData(Encoding.UTF8.GetBytes("Dummy event")) }; Assert.That(async () => await producer.SendAsync(events), Throws.Nothing); @@ -811,9 +793,7 @@ public async Task ProducerCannotSendWhenSharedConnectionIsClosed() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var connection = new EventHubConnection(connectionString)) + await using (var connection = new EventHubConnection(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) await using (var producer = new EventHubProducerClient(connection)) { EventData[] events = new[] { new EventData(Encoding.UTF8.GetBytes("Dummy event")) }; @@ -839,9 +819,7 @@ public async Task ProducerCannotSendToInvalidPartition(string invalidPartition) { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var connection = new EventHubConnection(connectionString)) + await using (var connection = new EventHubConnection(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { EventData[] events = new[] { new EventData(Encoding.UTF8.GetBytes("Lorem Ipsum")) }; @@ -863,9 +841,7 @@ public async Task SendSetUpdatesPartitionProperties() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var connection = new EventHubConnection(connectionString)) + await using (var connection = new EventHubConnection(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { var partition = (await connection.GetPartitionIdsAsync(DefaultRetryPolicy)).First(); EventData[] events = new[] { new EventData(Encoding.UTF8.GetBytes("I should update stuff")) }; @@ -877,13 +853,11 @@ public async Task SendSetUpdatesPartitionProperties() await producer.SendAsync(events, new SendEventOptions { PartitionId = partition }); PartitionProperties oldPartitionProperties = await producer.GetPartitionPropertiesAsync(partition); - Assert.That(oldPartitionProperties, Is.Not.Null, "A set of partition properties should have been returned."); await producer.SendAsync(events); PartitionProperties newPartitionProperties = await producer.GetPartitionPropertiesAsync(partition); - Assert.That(newPartitionProperties, Is.Not.Null, "A set of partition properties should have been returned."); // The following properties should not have been altered. @@ -911,9 +885,7 @@ public async Task SendBatchUpdatesPartitionProperties() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var connection = new EventHubConnection(connectionString)) + await using (var connection = new EventHubConnection(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { var partition = (await connection.GetPartitionIdsAsync(DefaultRetryPolicy)).First(); @@ -964,9 +936,7 @@ public async Task SendDoesNotUpdatePartitionPropertiesWhenSendingToDifferentPart { await using (EventHubScope scope = await EventHubScope.CreateAsync(2)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var connection = new EventHubConnection(connectionString)) + await using (var connection = new EventHubConnection(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { var partitionIds = await connection.GetPartitionIdsAsync(DefaultRetryPolicy); EventData[] events = new[] { new EventData(Encoding.UTF8.GetBytes("I should not update stuff")) }; @@ -1015,9 +985,7 @@ public async Task ProducerDoesNotSendToSpecificPartitionWhenPartitionIdIsNotSpec await using (EventHubScope scope = await EventHubScope.CreateAsync(partitions)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var connection = new EventHubConnection(connectionString)) + await using (var connection = new EventHubConnection(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { await using (var producer = new EventHubProducerClient(connection)) await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connection)) @@ -1089,9 +1057,7 @@ public async Task ProducerSendsEventsInTheSameSetToTheSamePartition() await using (EventHubScope scope = await EventHubScope.CreateAsync(partitions)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var connection = new EventHubConnection(connectionString)) + await using (var connection = new EventHubConnection(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) await using (var producer = new EventHubProducerClient(connection)) await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connection)) { @@ -1158,9 +1124,7 @@ public async Task ProducerSendsEventsWithTheSamePartitionHashKeyToTheSamePartiti await using (EventHubScope scope = await EventHubScope.CreateAsync(partitions)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var connection = new EventHubConnection(connectionString)) + await using (var connection = new EventHubConnection(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) await using (var producer = new EventHubProducerClient(connection)) await using (var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connection)) { @@ -1225,8 +1189,6 @@ public async Task ProducerCannotSendWhenProxyIsInvalid() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var producerOptions = new EventHubProducerClientOptions { RetryOptions = new EventHubsRetryOptions { TryTimeout = TimeSpan.FromMinutes(2) }, @@ -1238,7 +1200,11 @@ public async Task ProducerCannotSendWhenProxyIsInvalid() } }; - await using (var invalidProxyProducer = new EventHubProducerClient(connectionString, producerOptions)) + await using (var invalidProxyProducer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + producerOptions)) { Assert.That(async () => await invalidProxyProducer.SendAsync(new[] { new EventData(new byte[1]) }), Throws.InstanceOf().Or.InstanceOf()); } @@ -1304,7 +1270,7 @@ public async Task ProducerCanSendEventsWithAFullyPopulatedAmqpMessage() // Attempt to send and validate the operation was not rejected. - await using var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName)); + await using var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); Assert.That(async () => await producer.SendAsync(new[] { eventData }), Throws.Nothing); } } @@ -1325,7 +1291,7 @@ public async Task ProducerCanSendEventsWithValueBodies() // Attempt to send and validate the operation was not rejected. - await using var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName)); + await using var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); Assert.That(async () => await producer.SendAsync(new[] { eventData }), Throws.Nothing); } } @@ -1346,7 +1312,7 @@ public async Task ProducerCanSendEventsWithSequenceBodies() // Attempt to send and validate the operation was not rejected. - await using var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName)); + await using var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential); Assert.That(async () => await producer.SendAsync(new[] { eventData }), Throws.Nothing); } } @@ -1368,7 +1334,7 @@ public async Task ProducerCanRetrieveEventHubProperties(EventHubsTransportType t var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var producerOptions = new EventHubProducerClientOptions { ConnectionOptions = new EventHubConnectionOptions { TransportType = transportType } }; - await using (var producer = new EventHubProducerClient(connectionString, scope.EventHubName, producerOptions)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, producerOptions)) { EventHubProperties properties = await producer.GetEventHubPropertiesAsync(); @@ -1395,10 +1361,9 @@ public async Task ProducerCanRetrievePartitionProperties(EventHubsTransportType await using (EventHubScope scope = await EventHubScope.CreateAsync(partitionCount)) { var options = new EventHubConnectionOptions(); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var producerOptions = new EventHubProducerClientOptions { ConnectionOptions = new EventHubConnectionOptions { TransportType = transportType } }; - await using (var producer = new EventHubProducerClient(connectionString, scope.EventHubName, producerOptions)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, producerOptions)) { var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(20)); var properties = await producer.GetEventHubPropertiesAsync(); @@ -1425,9 +1390,7 @@ public async Task ConnectionTransportPartitionIdsMatchPartitionProperties() { await using (EventHubScope scope = await EventHubScope.CreateAsync(4)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { EventHubProperties properties = await producer.GetEventHubPropertiesAsync(); var partitions = await producer.GetPartitionIdsAsync(); @@ -1450,9 +1413,7 @@ public async Task ProducerCannotRetrieveMetadataWhenClosed() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { var partition = (await producer.GetPartitionIdsAsync()).First(); @@ -1483,9 +1444,7 @@ public async Task ProducerCannotRetrievePartitionPropertiesWhenPartitionIdIsInva { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - - await using (var producer = new EventHubProducerClient(connectionString)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) { Assert.That(async () => await producer.GetPartitionPropertiesAsync(invalidPartition), Throws.TypeOf()); } @@ -1502,8 +1461,6 @@ public async Task ProducerCannotRetrieveMetadataWhenProxyIsInvalid() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var invalidProxyOptions = new EventHubProducerClientOptions { RetryOptions = new EventHubsRetryOptions { TryTimeout = TimeSpan.FromMinutes(2) }, @@ -1515,8 +1472,8 @@ public async Task ProducerCannotRetrieveMetadataWhenProxyIsInvalid() } }; - await using (var producer = new EventHubProducerClient(connectionString)) - await using (var invalidProxyProducer = new EventHubProducerClient(connectionString, invalidProxyOptions)) + await using (var producer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential)) + await using (var invalidProxyProducer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, invalidProxyOptions)) { var partition = (await producer.GetPartitionIdsAsync()).First(); diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Producer/IdempotentPublishingLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Producer/IdempotentPublishingLiveTests.cs index ef92884946624..b9db032af87ca 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Producer/IdempotentPublishingLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Producer/IdempotentPublishingLiveTests.cs @@ -36,13 +36,17 @@ public async Task ProducerCanOptIntoIdempotentPublishing() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; - var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - await using var producer = new EventHubProducerClient(connectionString, options); + var options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; + + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); + Assert.That(async () => await producer.GetPartitionIdsAsync(cancellationSource.Token), Throws.Nothing); } } @@ -59,13 +63,16 @@ public async Task ProducerCanPublishEvents(EventHubsTransportType transportType) { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true, ConnectionOptions = new EventHubConnectionOptions { TransportType = transportType } }; + var cancellationSource = new CancellationTokenSource(); + cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - await using var producer = new EventHubProducerClient(connectionString, options); + var options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true, ConnectionOptions = new EventHubConnectionOptions { TransportType = transportType } }; - var cancellationSource = new CancellationTokenSource(); - cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); var partition = (await producer.GetPartitionIdsAsync(cancellationSource.Token)).First(); var sendOptions = new SendEventOptions { PartitionId = partition }; @@ -87,14 +94,17 @@ public async Task ProducerCanPublishBatches(EventHubsTransportType transportType { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true, ConnectionOptions = new EventHubConnectionOptions { TransportType = transportType } }; - - await using var producer = new EventHubProducerClient(connectionString, options); - var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); + var options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true, ConnectionOptions = new EventHubConnectionOptions { TransportType = transportType } }; + + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); + var partition = (await producer.GetPartitionIdsAsync()).First(); var batchOptions = new CreateBatchOptions { PartitionId = partition }; @@ -123,10 +133,13 @@ public async Task ProducerCanPublishEventsAfterAnException() var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; - await using var producer = new EventHubProducerClient(connectionString, options); + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); var partition = (await producer.GetPartitionIdsAsync()).First(); var sendOptions = new SendEventOptions { PartitionId = partition }; @@ -167,10 +180,13 @@ public async Task ProducerCanPublishBatchesAfterAnException() var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; - await using var producer = new EventHubProducerClient(connectionString, options); + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); var partition = (await producer.GetPartitionIdsAsync()).First(); var batchOptions = new CreateBatchOptions { PartitionId = partition }; @@ -214,14 +230,17 @@ public async Task ProducerInitializesPropertiesWhenRequested() { 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 options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; + + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); + var partition = (await producer.GetPartitionIdsAsync(cancellationSource.Token)).Last(); var partitionProperties = await producer.GetPartitionPublishingPropertiesAsync(partition); @@ -243,14 +262,17 @@ public async Task ProducerInitializesPropertiesWhenPublishing() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - 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 options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; + + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); + var partition = (await producer.GetPartitionIdsAsync(cancellationSource.Token)).First(); var sendOptions = new SendEventOptions { PartitionId = partition }; @@ -276,14 +298,17 @@ public async Task ProducerManagesConcurrencyWhenPublishingEvents() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - 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 options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; + + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); + var partition = (await producer.GetPartitionIdsAsync(cancellationSource.Token)).First(); var sendOptions = new SendEventOptions { PartitionId = partition }; @@ -313,14 +338,17 @@ public async Task ProducerManagesConcurrencyWhenPublishingBatches() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - 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 options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; + + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); + var partition = (await producer.GetPartitionIdsAsync(cancellationSource.Token)).First(); var batchOptions = new CreateBatchOptions { PartitionId = partition }; @@ -356,13 +384,16 @@ public async Task ProducerAllowsPublishingConcurrentlyToDifferentPartitions() { await using (EventHubScope scope = await EventHubScope.CreateAsync(4)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); - var options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; + var cancellationSource = new CancellationTokenSource(); + cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - await using var producer = new EventHubProducerClient(connectionString, options); + var options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; - var cancellationSource = new CancellationTokenSource(); - cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); async Task sendEvents(string partition, int delayMilliseconds) { @@ -393,14 +424,17 @@ 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 options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; + + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); + var partition = (await producer.GetPartitionIdsAsync(cancellationSource.Token)).Last(); var sendOptions = new SendEventOptions { PartitionId = partition }; @@ -430,14 +464,17 @@ public async Task ProducerSequencesBatches() { 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 options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; + + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); + var partition = (await producer.GetPartitionIdsAsync(cancellationSource.Token)).Last(); var batchOptions = new CreateBatchOptions { PartitionId = partition }; @@ -479,14 +516,17 @@ public async Task ProducerUpdatesPropertiesAfterPublishingEvents() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - 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 options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; + + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); + var partition = (await producer.GetPartitionIdsAsync(cancellationSource.Token)).First(); var initialPartitionProperties = await producer.GetPartitionPublishingPropertiesAsync(partition); @@ -512,14 +552,17 @@ public async Task ProducerUpdatesPropertiesAfterPublishingBatches() { await using (EventHubScope scope = await EventHubScope.CreateAsync(1)) { - 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 options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; + + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); + var partition = (await producer.GetPartitionIdsAsync(cancellationSource.Token)).First(); var initialPartitionProperties = await producer.GetPartitionPublishingPropertiesAsync(partition); var batchOptions = new CreateBatchOptions { PartitionId = partition }; @@ -549,7 +592,6 @@ public async Task ProducerCanInitializeWithPartitionOptions() { await using (EventHubScope scope = await EventHubScope.CreateAsync(2)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; var cancellationSource = new CancellationTokenSource(); @@ -560,7 +602,7 @@ public async Task ProducerCanInitializeWithPartitionOptions() // Create a producer for a small scope that will Send some events and read the properties. - await using (var initialProducer = new EventHubProducerClient(connectionString, options)) + await using (var initialProducer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, options)) { partition = (await initialProducer.GetPartitionIdsAsync(cancellationSource.Token)).Last(); @@ -577,7 +619,12 @@ public async Task ProducerCanInitializeWithPartitionOptions() StartingSequenceNumber = partitionProperties.LastPublishedSequenceNumber }); - await using var producer = new EventHubProducerClient(connectionString, options); + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); + Assert.That(async () => await producer.SendAsync(EventGenerator.CreateEvents(10), new SendEventOptions { PartitionId = partition }, cancellationSource.Token), Throws.Nothing); } } @@ -592,7 +639,6 @@ public async Task ProducerCanInitializeWithPartialPartitionOptions() { await using (EventHubScope scope = await EventHubScope.CreateAsync(2)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; var cancellationSource = new CancellationTokenSource(); @@ -603,7 +649,7 @@ public async Task ProducerCanInitializeWithPartialPartitionOptions() // Create a producer for a small scope that will Send some events and read the properties. - await using (var initialProducer = new EventHubProducerClient(connectionString, options)) + await using (var initialProducer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, options)) { partition = (await initialProducer.GetPartitionIdsAsync(cancellationSource.Token)).Last(); @@ -620,7 +666,12 @@ public async Task ProducerCanInitializeWithPartialPartitionOptions() }); Assert.That(options.PartitionOptions[partition].StartingSequenceNumber.HasValue, Is.False, "The partition options should not specifiy a starting sequence number."); - await using var producer = new EventHubProducerClient(connectionString, options); + + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); // Verify that the properties were fully initialized when using partial options. @@ -647,7 +698,6 @@ public async Task ProducerIsRejectedWithPartitionOptionsForInvalidState() { await using (EventHubScope scope = await EventHubScope.CreateAsync(2)) { - var connectionString = EventHubsTestEnvironment.Instance.BuildConnectionStringForEventHub(scope.EventHubName); var options = new EventHubProducerClientOptions { EnableIdempotentPartitions = true }; var cancellationSource = new CancellationTokenSource(); @@ -658,7 +708,7 @@ public async Task ProducerIsRejectedWithPartitionOptionsForInvalidState() // Create a producer for a small scope that will Send some events and read the properties. - await using (var initialProducer = new EventHubProducerClient(connectionString, options)) + await using (var initialProducer = new EventHubProducerClient(EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, scope.EventHubName, EventHubsTestEnvironment.Instance.Credential, options)) { partition = (await initialProducer.GetPartitionIdsAsync(cancellationSource.Token)).Last(); @@ -675,7 +725,11 @@ public async Task ProducerIsRejectedWithPartitionOptionsForInvalidState() StartingSequenceNumber = (partitionProperties.LastPublishedSequenceNumber - 5) }); - await using var producer = new EventHubProducerClient(connectionString, options); + await using var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential, + options); Assert.That(async () => await producer.SendAsync(EventGenerator.CreateEvents(10), new SendEventOptions { PartitionId = partition }, cancellationSource.Token), Throws.InstanceOf().And.Property("Reason").EqualTo(EventHubsException.FailureReason.InvalidClientState)); diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/ReadMeSnippetsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/ReadMeSnippetsLiveTests.cs index 14d6f446a2d39..516efb9c9add6 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/ReadMeSnippetsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/ReadMeSnippetsLiveTests.cs @@ -37,7 +37,7 @@ public async Task CreateWithConnectionString() var eventHubName = "<< NAME OF THE EVENT HUB >>"; #else var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fakeHub"; + var eventHubName = "fake"; #endif // It is recommended that you cache the Event Hubs clients for the lifetime of your diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample01_HelloWorldLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample01_HelloWorldLiveTests.cs index 1624d277a6062..fb570965c0d5b 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample01_HelloWorldLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample01_HelloWorldLiveTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Azure.Identity; using Azure.Messaging.EventHubs.Consumer; using Azure.Messaging.EventHubs.Producer; using NUnit.Framework; @@ -57,9 +58,10 @@ public async Task PublishEvents() { await using var scope = await EventHubScope.CreateAsync(1); - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = scope.EventHubName; - var producer = new EventHubProducerClient(connectionString, eventHubName); + var producer = new EventHubProducerClient( + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential); #region Snippet:EventHubs_Sample01_PublishEvents @@ -116,9 +118,11 @@ public async Task ReadEvents() { await using var scope = await EventHubScope.CreateAsync(1); - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = scope.EventHubName; - var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, connectionString, eventHubName); + var consumer = new EventHubConsumerClient( + EventHubConsumerClient.DefaultConsumerGroupName, + EventHubsTestEnvironment.Instance.FullyQualifiedNamespace, + scope.EventHubName, + EventHubsTestEnvironment.Instance.Credential); #region Snippet:EventHubs_Sample01_ReadEvents diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs index b15f992a99146..8fda583df6e78 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs @@ -8,6 +8,7 @@ using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; +using Azure.Identity; using Azure.Messaging.EventHubs.Consumer; using Azure.Messaging.EventHubs.Producer; using NUnit.Framework; @@ -34,11 +35,13 @@ public async Task ConfigureProducerTransportWithFullOptions() #region Snippet:EventHubs_Sample02_ProducerTransportFullConnectionOptions #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = "fake"; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var producerOptions = new EventHubProducerClientOptions @@ -50,8 +53,9 @@ public async Task ConfigureProducerTransportWithFullOptions() }; var producer = new EventHubProducerClient( - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, producerOptions); #endregion @@ -72,19 +76,22 @@ public async Task ConfigureProducerTransportByProperty() #region Snippet:EventHubs_Sample02_ProducerTransportProperty #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = "fake"; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var producerOptions = new EventHubProducerClientOptions(); producerOptions.ConnectionOptions.TransportType = EventHubsTransportType.AmqpWebSockets; var producer = new EventHubProducerClient( - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, producerOptions); #endregion @@ -105,11 +112,13 @@ public async Task ConfigureProducerProxyWithFullOptions() #region Snippet:EventHubs_Sample02_ProducerProxyFullConnectionOptions #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = "fake"; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var producerOptions = new EventHubProducerClientOptions @@ -122,8 +131,9 @@ public async Task ConfigureProducerProxyWithFullOptions() }; var producer = new EventHubProducerClient( - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, producerOptions); #endregion @@ -144,11 +154,13 @@ public async Task ConfigureProducerProxyByProperty() #region Snippet:EventHubs_Sample02_ProducerProxyProperty #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = "fake"; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var producerOptions = new EventHubProducerClientOptions(); @@ -156,8 +168,9 @@ public async Task ConfigureProducerProxyByProperty() producerOptions.ConnectionOptions.Proxy = new WebProxy("https://proxyserver:80", true); var producer = new EventHubProducerClient( - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, producerOptions); #endregion @@ -178,19 +191,22 @@ public async Task ConfigureCustomEndpointAddress() #region Snippet:EventHubs_Sample02_ConnectionOptionsCustomEndpoint #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = "fake"; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var producerOptions = new EventHubProducerClientOptions(); producerOptions.ConnectionOptions.CustomEndpointAddress = new Uri("amqps://app-gateway.mycompany.com"); var producer = new EventHubProducerClient( - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, producerOptions); #endregion @@ -211,11 +227,13 @@ public async Task ConfigureRemoteCertificateValidationCallback() #region Snippet:EventHubs_Sample02_RemoteCertificateValidationCallback #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; - var eventHubName = "fake"; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var eventHubName = "fakse"; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif static bool ValidateServerCertificate( @@ -239,8 +257,9 @@ static bool ValidateServerCertificate( producerOptions.ConnectionOptions.CertificateValidationCallback = ValidateServerCertificate; var producer = new EventHubProducerClient( - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, producerOptions); #endregion @@ -261,11 +280,13 @@ public async Task ConfigureConsumerRetryWithFullOptions() #region Snippet:EventHubs_Sample02_ConsumerRetryWithFullOptions #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = "fake"; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; @@ -282,8 +303,9 @@ public async Task ConfigureConsumerRetryWithFullOptions() var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, consumerOptions); #endregion @@ -304,11 +326,13 @@ public async Task ConfigureConsumerRetryByProperty() #region Snippet:EventHubs_Sample02_ConsumerRetryByProperty #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = "fake"; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; @@ -318,8 +342,9 @@ public async Task ConfigureConsumerRetryByProperty() var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, consumerOptions); #endregion diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample03_EventHubMetadataLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample03_EventHubMetadataLiveTests.cs index 0baaba8e76137..08a750239f512 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample03_EventHubMetadataLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample03_EventHubMetadataLiveTests.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Linq; using System.Threading.Tasks; +using Azure.Identity; using Azure.Messaging.EventHubs.Consumer; using Azure.Messaging.EventHubs.Producer; using NUnit.Framework; @@ -32,14 +33,19 @@ public async Task InspectHub() #region Snippet:EventHubs_Sample03_InspectHub #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubProducerClient(connectionString, eventHubName); + var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -70,14 +76,19 @@ public async Task QueryPartitions() #region Snippet:EventHubs_Sample03_QueryPartitions #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubProducerClient(connectionString, eventHubName); + var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -104,15 +115,21 @@ public async Task InspectPartition() #region Snippet:EventHubs_Sample03_InspectPartition #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; - var consumer = new EventHubConsumerClient(consumerGroup, connectionString, eventHubName); + var consumer = new EventHubConsumerClient( + consumerGroup, + fullyQualifiedNamespace, + eventHubName, + credential); try { diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample04_PublishingEventsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample04_PublishingEventsLiveTests.cs index bd42c3c9b92d0..0d14b8ddba4f1 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample04_PublishingEventsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample04_PublishingEventsLiveTests.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Linq; using System.Threading.Tasks; +using Azure.Identity; using Azure.Messaging.EventHubs.Producer; using NUnit.Framework; @@ -33,14 +34,19 @@ public async Task EventBatch() #region Snippet:EventHubs_Sample04_EventBatch #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubProducerClient(connectionString, eventHubName); + var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -73,14 +79,19 @@ public async Task AutomaticRouting() #region Snippet:EventHubs_Sample04_AutomaticRouting #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubProducerClient(connectionString, eventHubName); + var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -118,14 +129,19 @@ public async Task AutomaticRoutingBuffered() #region Snippet:EventHubs_Sample04_AutomaticRoutingBuffered #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubBufferedProducerClient(connectionString, eventHubName); + var producer = new EventHubBufferedProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); // The failure handler is required and invoked after all allowable // retries were applied. @@ -175,14 +191,19 @@ public async Task PartitionKey() #region Snippet:EventHubs_Sample04_PartitionKey #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubProducerClient(connectionString, eventHubName); + var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -225,14 +246,19 @@ public async Task PartitionKeyBuffered() #region Snippet:EventHubs_Sample04_PartitionKeyBuffered #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubBufferedProducerClient(connectionString, eventHubName); + var producer = new EventHubBufferedProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); // The failure handler is required and invoked after all allowable // retries were applied. @@ -287,14 +313,19 @@ public async Task PartitionId() #region Snippet:EventHubs_Sample04_PartitionId #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubProducerClient(connectionString, eventHubName); + var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -339,14 +370,19 @@ public async Task PartitionIdBuffered() #region Snippet:EventHubs_Sample04_PartitionIdBuffered #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubBufferedProducerClient(connectionString, eventHubName); + var producer = new EventHubBufferedProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); // The failure handler is required and invoked after all allowable // retries were applied. @@ -403,14 +439,19 @@ public async Task CustomMetadata() #region Snippet:EventHubs_Sample04_CustomMetadata #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubBufferedProducerClient(connectionString, eventHubName); + var producer = new EventHubBufferedProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); // The failure handler is required and invoked after all allowable // retries were applied. @@ -478,11 +519,13 @@ public async Task BufferedConfiguration() #region Snippet:EventHubs_Sample04_BufferedConfiguration #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var options = new EventHubBufferedProducerClientOptions @@ -494,7 +537,11 @@ public async Task BufferedConfiguration() EnableIdempotentRetries = true }; - var producer = new EventHubBufferedProducerClient(connectionString, eventHubName, options); + var producer = new EventHubBufferedProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential, + options); // The failure handler is required and invoked after all allowable // retries were applied. @@ -544,14 +591,19 @@ public async Task NoBatch() #region Snippet:EventHubs_Sample04_NoBatch #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubProducerClient(connectionString, eventHubName); + var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -585,14 +637,20 @@ public async Task MultipleBatches() #region Snippet:EventHubs_Sample04_MultipleBatches #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubProducerClient(connectionString, eventHubName); + var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); + var batches = default(IEnumerable); var eventsToSend = new Queue(); @@ -635,14 +693,19 @@ public async Task CustomBatchSize() #region Snippet:EventHubs_Sample04_CustomBatchSize #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubProducerClient(connectionString, eventHubName); + var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample05_ReadingEventsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample05_ReadingEventsLiveTests.cs index 598fd6bd77a53..dcfe61f941e06 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample05_ReadingEventsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample05_ReadingEventsLiveTests.cs @@ -9,6 +9,7 @@ using System.Reflection; using System.Threading; using System.Threading.Tasks; +using Azure.Identity; using Azure.Messaging.EventHubs.Consumer; using Azure.Messaging.EventHubs.Primitives; using Azure.Messaging.EventHubs.Producer; @@ -38,18 +39,21 @@ public async Task ReadAllPartitions() #region Snippet:EventHubs_Sample05_ReadAllPartitions #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -98,18 +102,21 @@ public async Task ReadAllPartitionsWaitTime() #region Snippet:EventHubs_Sample05_ReadAllPartitionsWaitTime #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -163,18 +170,21 @@ public async Task ReadAllPartitionsFromLatest() #region Snippet:EventHubs_Sample05_ReadAllPartitionsFromLatest #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -216,18 +226,21 @@ public async Task ReadPartition() #region Snippet:EventHubs_Sample05_ReadPartition #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -273,18 +286,21 @@ public async Task ReadPartitionWaitTime() #region Snippet:EventHubs_Sample05_ReadPartitionWaitTime #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -352,18 +368,21 @@ public async Task ReadPartitionFromDate() #region Snippet:EventHubs_Sample05_ReadPartitionFromDate #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -411,18 +430,21 @@ public async Task ReadPartitionFromOffset() #region Snippet:EventHubs_Sample05_ReadPartitionFromOffset #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -469,18 +491,21 @@ public async Task ReadPartitionFromSequence() #region Snippet:EventHubs_Sample05_ReadPartitionFromSequence #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -527,18 +552,21 @@ public async Task ReadPartitionTrackLastEnqueued() #region Snippet:EventHubs_Sample05_ReadPartitionTrackLastEnqueued #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -594,11 +622,13 @@ public async Task ReadPartitionWithReceiver() #region Snippet:EventHubs_Sample05_ReadPartitionWithReceiver #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; @@ -607,7 +637,10 @@ public async Task ReadPartitionWithReceiver() string firstPartition; - await using (var producer = new EventHubProducerClient(connectionString, eventHubName)) + await using (var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential)) { firstPartition = (await producer.GetPartitionIdsAsync()).First(); } @@ -616,8 +649,9 @@ public async Task ReadPartitionWithReceiver() consumerGroup, firstPartition, EventPosition.Earliest, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample07_EarlierLanguageVersionsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample07_EarlierLanguageVersionsLiveTests.cs index c3476139f9759..077d7cd51ea36 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample07_EarlierLanguageVersionsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample07_EarlierLanguageVersionsLiveTests.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Threading; using System.Threading.Tasks; +using Azure.Identity; using Azure.Messaging.EventHubs.Consumer; using Azure.Messaging.EventHubs.Producer; using NUnit.Framework; @@ -34,14 +35,19 @@ public async Task Publish() #region Snippet:EventHubs_Sample07_Publish #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubProducerClient(connectionString, eventHubName); + var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -76,18 +82,21 @@ public async Task ReadAllPartitions() #region Snippet:EventHubs_Sample07_ReadAllPartitions #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; var consumer = new EventHubConsumerClient( consumerGroup, - connectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); try { diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample08_CustomEventProcessorLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample08_CustomEventProcessorLiveTests.cs index 597c620fba3ad..cbda1869d4343 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample08_CustomEventProcessorLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample08_CustomEventProcessorLiveTests.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using Azure.Core; +using Azure.Identity; using Azure.Messaging.EventHubs.Consumer; using Azure.Messaging.EventHubs.Primitives; using Azure.Messaging.EventHubs.Processor; @@ -48,18 +49,26 @@ public async Task CustomProcessorUse() #region Snippet:EventHubs_Sample08_CustomProcessorUse #if SNIPPET - var storageConnectionString = "<< CONNECTION STRING FOR THE STORAGE ACCOUNT >>"; + var credential = new DefaultAzureCredential(); + + var storageAccountEndpoint = "<< Account Uri (likely similar to https://{your-account}.blob.core.windows.net) >>"; var blobContainerName = "<< NAME OF THE BLOB CONTAINER >>"; - var eventHubsConnectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + 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 >>"; + var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) + { + BlobContainerName = blobContainerName + }; + var storageClient = new BlobContainerClient( - storageConnectionString, - blobContainerName); + blobUriBuilder.ToUri(), + credential); #else - var eventHubsConnectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var credential = EventHubsTestEnvironment.Instance.Credential; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); var storageClient = Mock.Of(); @@ -71,8 +80,9 @@ public async Task CustomProcessorUse() storageClient, maximumBatchSize, consumerGroup, - eventHubsConnectionString, - eventHubName); + fullyQualifiedNamespace, + eventHubName, + credential); using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(TimeSpan.FromSeconds(30)); @@ -113,8 +123,9 @@ public CustomProcessor( BlobContainerClient storageClient, int eventBatchMaximumCount, string consumerGroup, - string connectionString, + string fullyQualifiedNamespace, string eventHubName, + TokenCredential credential, EventProcessorOptions clientOptions = default) : base( #if SNIPPET @@ -124,8 +135,9 @@ public CustomProcessor( #endif eventBatchMaximumCount, consumerGroup, - connectionString, + fullyQualifiedNamespace, eventHubName, + credential, clientOptions) { } diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample09_ObservableEventBatchLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample09_ObservableEventBatchLiveTests.cs index 51fa5e13c1789..990354ec812ec 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample09_ObservableEventBatchLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample09_ObservableEventBatchLiveTests.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Linq; using System.Threading.Tasks; +using Azure.Identity; using Azure.Messaging.EventHubs.Producer; using NUnit.Framework; @@ -32,14 +33,19 @@ public async Task Sample09_AccessingEventData() #region Snippet:Sample09_AccessingEventData #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubProducerClient(connectionString, eventHubName); + var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { @@ -86,14 +92,19 @@ public async Task Sample09_CheckingBatch() #region Snippet:Sample09_CheckingBatch #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubProducerClient(connectionString, eventHubName); + var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); try { diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample10_AzureEventSourceListenerTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample10_AzureEventSourceListenerTests.cs index edb4fe5a9b443..bde86915b6cdc 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample10_AzureEventSourceListenerTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample10_AzureEventSourceListenerTests.cs @@ -7,6 +7,7 @@ using System.IO; using System.Threading.Tasks; using Azure.Core.Diagnostics; +using Azure.Identity; using Azure.Messaging.EventHubs.Producer; using NUnit.Framework; @@ -33,13 +34,19 @@ public async Task ConsoleListener() #region Snippet:EventHubs_Sample10_ConsoleListener #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubProducerClient(connectionString, eventHubName); + + var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); using AzureEventSourceListener consoleListener = AzureEventSourceListener.CreateConsoleLogger(EventLevel.LogAlways); @@ -71,13 +78,19 @@ public async Task TraceListener() #region Snippet:EventHubs_Sample10_TraceListener #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubProducerClient(connectionString, eventHubName); + + var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); using AzureEventSourceListener traceListener = AzureEventSourceListener.CreateTraceLogger(EventLevel.LogAlways); @@ -109,13 +122,19 @@ public async Task CustomListenerWithFilter() #region Snippet:EventHubs_Sample10_CustomListenerWithFilter #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; + var credential = new DefaultAzureCredential(); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; + var credential = EventHubsTestEnvironment.Instance.Credential; #endif - var producer = new EventHubProducerClient(connectionString, eventHubName); + + var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); using AzureEventSourceListener customListener = new AzureEventSourceListener((args, message) => { @@ -164,19 +183,24 @@ public async Task CustomListenerWithFile() #region Snippet:EventHubs_Sample10_CustomListenerWithFile #if SNIPPET - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; - var producer = new EventHubProducerClient(connectionString, eventHubName); + var credential = new DefaultAzureCredential(); using Stream stream = new FileStream("<< PATH TO THE FILE >>", FileMode.OpenOrCreate, FileAccess.Write); #else - var connectionString = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; var eventHubName = scope.EventHubName; - var producer = new EventHubProducerClient(connectionString, eventHubName); + var credential = EventHubsTestEnvironment.Instance.Credential; using Stream stream = new MemoryStream(); #endif + var producer = new EventHubProducerClient( + fullyQualifiedNamespace, + eventHubName, + credential); + using StreamWriter streamWriter = new StreamWriter(stream) { AutoFlush = true diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/SamplesCommonTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/SamplesCommonTests.cs index c6d01c3da7b4b..fe1ced34a650f 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/SamplesCommonTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/SamplesCommonTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using Azure.Messaging.EventHubs.Consumer; +using Azure.Identity; using NUnit.Framework; namespace Azure.Messaging.EventHubs.Tests @@ -23,14 +24,17 @@ public void ConsumerBasicConfiguration() { #region Snippet:EventHubs_SamplesCommon_ConsumerBasicConfig - var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; + var credential = new DefaultAzureCredential(); + #endregion - Assert.That(connectionString, Is.Not.Null); + Assert.That(fullyQualifiedNamespace, Is.Not.Null); Assert.That(eventHubName, Is.Not.Null); + Assert.That(credential, Is.Not.Null); Assert.That(consumerGroup, Is.Not.Null); } } From ddf241a8d3880f155327e916d40ceed1812143e4 Mon Sep 17 00:00:00 2001 From: Jesse Squire Date: Mon, 30 Sep 2024 14:57:52 -0700 Subject: [PATCH 02/16] Test fixes --- .../MigrationGuideSnippetsLiveTests.cs | 2 +- .../tests/Snippets/ReadMeSnippetsLiveTests.cs | 6 ++--- ...02_EventProcessorConfigurationLiveTests.cs | 20 ++++++++-------- ...ample03_EventProcessorHandlersLiveTests.cs | 18 +++++++------- .../Sample04_ProcessingEventsLiveTests.cs | 8 +++---- ...tityAndSharedAccessCredentialsLiveTests.cs | 2 +- ...questingStorageServiceVersionsLiveTests.cs | 2 +- .../Sample07_BatchProcessingLiveTests.cs | 2 +- .../Sample02_EventHubsClientsLiveTests.cs | 16 ++++++------- .../Sample03_EventHubMetadataLiveTests.cs | 6 ++--- .../Sample04_PublishingEventsLiveTests.cs | 24 +++++++++---------- .../Sample05_ReadingEventsLiveTests.cs | 20 ++++++++-------- ...mple07_EarlierLanguageVersionsLiveTests.cs | 4 ++-- .../Sample09_ObservableEventBatchLiveTests.cs | 4 ++-- 14 files changed, 67 insertions(+), 67 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/MigrationGuideSnippetsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/MigrationGuideSnippetsLiveTests.cs index 779f3550176c9..7916e042b8cd3 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/MigrationGuideSnippetsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/MigrationGuideSnippetsLiveTests.cs @@ -56,7 +56,7 @@ public async Task MigrateCheckpoints() var eventHubName = "fake-hub"; var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = storageScope.ContainerName; #endif diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/ReadMeSnippetsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/ReadMeSnippetsLiveTests.cs index 5bae5cc75586a..cd3fde8c9856f 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/ReadMeSnippetsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/ReadMeSnippetsLiveTests.cs @@ -82,7 +82,7 @@ public void ConfigureHandlers() var eventHubName = "fake-hub"; var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif @@ -174,7 +174,7 @@ public async Task ProcessUntilCanceled() var eventHubName = eventHubScope.EventHubName; var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = storageScope.ContainerName; #endif @@ -256,7 +256,7 @@ public void CreateWithIdentity() var eventHubName = "fake-hub"; var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample02_EventProcessorConfigurationLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample02_EventProcessorConfigurationLiveTests.cs index ea6239c1c6055..6a3292e873e55 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample02_EventProcessorConfigurationLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample02_EventProcessorConfigurationLiveTests.cs @@ -47,7 +47,7 @@ public void ConfigureLoadBalancingStrategy() var eventHubName = "fake"; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif @@ -101,7 +101,7 @@ public void ConfigureLoadBalancingIntervals() var eventHubName = "fake"; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif @@ -156,7 +156,7 @@ public void ConfigureTransportWithFullOptions() var eventHubName = "fake"; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif @@ -213,7 +213,7 @@ public void ConfigureTransportByProperty() var eventHubName = "fake"; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif @@ -265,7 +265,7 @@ public void ConfigureProxyWithFullOptions() var eventHubName = "fake"; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif @@ -323,7 +323,7 @@ public void ConfigureProxyByProperty() var eventHubName = "fake"; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif @@ -376,7 +376,7 @@ public void ConfigureCustomEndpointAddress() var eventHubName = "fake"; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif @@ -428,7 +428,7 @@ public void ConfigureRemoteCertificateValidationCallback() var eventHubName = "fake"; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif @@ -497,7 +497,7 @@ public void ConfigureRetryWithFullOptions() var eventHubName = "fake"; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif @@ -557,7 +557,7 @@ public void ConfigureRetryByProperty() var eventHubName = "fake"; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample03_EventProcessorHandlersLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample03_EventProcessorHandlersLiveTests.cs index c7ec9df2d6f60..dcea8ce792a21 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample03_EventProcessorHandlersLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample03_EventProcessorHandlersLiveTests.cs @@ -49,7 +49,7 @@ public void EventHandlerExceptionHandling() var eventHubName = "fake"; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif @@ -128,7 +128,7 @@ public void EventHandlerCancellation() var eventHubName = "fake"; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif @@ -215,7 +215,7 @@ public async Task EventHandlerStopOnException() var eventHubName = "fake"; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif @@ -339,7 +339,7 @@ public void ErrorHandlerArgs() var eventHubName = "fake"; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif @@ -426,11 +426,11 @@ public async Task ErrorHandlerCancellationRecovery() var credential = EventHubsTestEnvironment.Instance.Credential; var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; - var eventHubName = "fake"; + var eventHubName = eventHubScope.EventHubName; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; - var blobContainerName = "fake"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var blobContainerName = storageScope.ContainerName; #endif var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) @@ -571,7 +571,7 @@ public void InitializeHandlerArgs() var eventHubName = "fake"; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif @@ -660,7 +660,7 @@ public void CloseHandlerArgs() var eventHubName = "fake"; var consumerGroup = "$Default"; - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = "fake"; #endif diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample04_ProcessingEventsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample04_ProcessingEventsLiveTests.cs index ba76369b51116..8725db5627df3 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample04_ProcessingEventsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample04_ProcessingEventsLiveTests.cs @@ -53,7 +53,7 @@ public async Task BasicEventProcessing() var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = storageScope.ContainerName; #endif @@ -204,7 +204,7 @@ public async Task CheckpointByEventCount() var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = storageScope.ContainerName; #endif @@ -336,7 +336,7 @@ public async Task InitializePartition() var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = storageScope.ContainerName; #endif @@ -459,7 +459,7 @@ public async Task ProcessWithHeartbeat() var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = storageScope.ContainerName; #endif diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample05_IdentityAndSharedAccessCredentialsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample05_IdentityAndSharedAccessCredentialsLiveTests.cs index 11ccf8705359b..e10c8cd100cca 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample05_IdentityAndSharedAccessCredentialsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample05_IdentityAndSharedAccessCredentialsLiveTests.cs @@ -52,7 +52,7 @@ public async Task DefaultAzureCredential() var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = storageScope.ContainerName; #endif diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample06_RequestingStorageServiceVersionsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample06_RequestingStorageServiceVersionsLiveTests.cs index 2f21d4266cfcf..e6c49f55cda0e 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample06_RequestingStorageServiceVersionsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample06_RequestingStorageServiceVersionsLiveTests.cs @@ -52,7 +52,7 @@ public async Task ProcessEvents() var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = storageScope.ContainerName; #endif diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample07_BatchProcessingLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample07_BatchProcessingLiveTests.cs index 4f6e8f53b8141..417b717aff966 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample07_BatchProcessingLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample07_BatchProcessingLiveTests.cs @@ -53,7 +53,7 @@ public async Task ProcessByBatch() var eventHubName = eventHubScope.EventHubName; var consumerGroup = eventHubScope.ConsumerGroups.First(); - var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; + var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; var blobContainerName = storageScope.ContainerName; #endif diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs index 8fda583df6e78..5c257f84b9054 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs @@ -39,7 +39,7 @@ public async Task ConfigureProducerTransportWithFullOptions() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = "fake"; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -80,7 +80,7 @@ public async Task ConfigureProducerTransportByProperty() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = "fake"; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -116,7 +116,7 @@ public async Task ConfigureProducerProxyWithFullOptions() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = "fake"; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -158,7 +158,7 @@ public async Task ConfigureProducerProxyByProperty() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = "fake"; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -195,7 +195,7 @@ public async Task ConfigureCustomEndpointAddress() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = "fake"; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -231,7 +231,7 @@ public async Task ConfigureRemoteCertificateValidationCallback() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = "fakse"; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -284,7 +284,7 @@ public async Task ConfigureConsumerRetryWithFullOptions() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = "fake"; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -330,7 +330,7 @@ public async Task ConfigureConsumerRetryByProperty() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = "fake"; var credential = EventHubsTestEnvironment.Instance.Credential; #endif diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample03_EventHubMetadataLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample03_EventHubMetadataLiveTests.cs index 08a750239f512..c758b7b90efe7 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample03_EventHubMetadataLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample03_EventHubMetadataLiveTests.cs @@ -37,7 +37,7 @@ public async Task InspectHub() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -80,7 +80,7 @@ public async Task QueryPartitions() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -119,7 +119,7 @@ public async Task InspectPartition() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample04_PublishingEventsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample04_PublishingEventsLiveTests.cs index 0d14b8ddba4f1..c5702ebac6e73 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample04_PublishingEventsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample04_PublishingEventsLiveTests.cs @@ -38,7 +38,7 @@ public async Task EventBatch() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -83,7 +83,7 @@ public async Task AutomaticRouting() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -133,7 +133,7 @@ public async Task AutomaticRoutingBuffered() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -195,7 +195,7 @@ public async Task PartitionKey() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -250,7 +250,7 @@ public async Task PartitionKeyBuffered() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -317,7 +317,7 @@ public async Task PartitionId() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -374,7 +374,7 @@ public async Task PartitionIdBuffered() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -443,7 +443,7 @@ public async Task CustomMetadata() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -523,7 +523,7 @@ public async Task BufferedConfiguration() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -595,7 +595,7 @@ public async Task NoBatch() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -641,7 +641,7 @@ public async Task MultipleBatches() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -697,7 +697,7 @@ public async Task CustomBatchSize() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample05_ReadingEventsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample05_ReadingEventsLiveTests.cs index dcfe61f941e06..0f7cf87fe79f8 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample05_ReadingEventsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample05_ReadingEventsLiveTests.cs @@ -43,7 +43,7 @@ public async Task ReadAllPartitions() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -106,7 +106,7 @@ public async Task ReadAllPartitionsWaitTime() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -174,7 +174,7 @@ public async Task ReadAllPartitionsFromLatest() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -230,7 +230,7 @@ public async Task ReadPartition() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -290,7 +290,7 @@ public async Task ReadPartitionWaitTime() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -372,7 +372,7 @@ public async Task ReadPartitionFromDate() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -434,7 +434,7 @@ public async Task ReadPartitionFromOffset() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -495,7 +495,7 @@ public async Task ReadPartitionFromSequence() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -556,7 +556,7 @@ public async Task ReadPartitionTrackLastEnqueued() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -626,7 +626,7 @@ public async Task ReadPartitionWithReceiver() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample07_EarlierLanguageVersionsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample07_EarlierLanguageVersionsLiveTests.cs index 077d7cd51ea36..b4ac38e697b2b 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample07_EarlierLanguageVersionsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample07_EarlierLanguageVersionsLiveTests.cs @@ -39,7 +39,7 @@ public async Task Publish() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -86,7 +86,7 @@ public async Task ReadAllPartitions() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample09_ObservableEventBatchLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample09_ObservableEventBatchLiveTests.cs index 990354ec812ec..4c1983986ba2b 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample09_ObservableEventBatchLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample09_ObservableEventBatchLiveTests.cs @@ -37,7 +37,7 @@ public async Task Sample09_AccessingEventData() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -96,7 +96,7 @@ public async Task Sample09_CheckingBatch() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif From 4df0e9228d3a7f4bfbc7c59d4834cf4d1622f4bc Mon Sep 17 00:00:00 2001 From: Jesse Squire Date: Mon, 30 Sep 2024 16:40:25 -0700 Subject: [PATCH 03/16] Fixing more typos --- .../Snippets/Sample03_EventProcessorHandlersLiveTests.cs | 4 ++-- .../tests/Consumer/EventHubConsumerClientLiveTests.cs | 2 +- .../Snippets/Sample10_AzureEventSourceListenerTests.cs | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample03_EventProcessorHandlersLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample03_EventProcessorHandlersLiveTests.cs index dcea8ce792a21..163821a58f813 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample03_EventProcessorHandlersLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs.Processor/tests/Snippets/Sample03_EventProcessorHandlersLiveTests.cs @@ -212,11 +212,11 @@ public async Task EventHandlerStopOnException() var credential = EventHubsTestEnvironment.Instance.Credential; var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; - var eventHubName = "fake"; + var eventHubName = eventHubScope.EventHubName; var consumerGroup = "$Default"; var storageAccountEndpoint = $"https://{ StorageTestEnvironment.Instance.StorageAccountName }.blob.{ StorageTestEnvironment.Instance.StorageEndpointSuffix}"; - var blobContainerName = "fake"; + var blobContainerName = storageScope.ContainerName; #endif var blobUriBuilder = new BlobUriBuilder(new Uri(storageAccountEndpoint)) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs index 012672d024e4e..8534f3c6777fd 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs @@ -2470,7 +2470,7 @@ public async Task ConsumerCanReadFromAllPartitionsStartingWithLatest() using var cancellationSource = new CancellationTokenSource(); cancellationSource.CancelAfter(EventHubsTestEnvironment.Instance.TestExecutionTimeLimit); - var sourceEvents = EventGenerator.CreateEvents(100).ToList(); + var sourceEvents = EventGenerator.CreateEvents(50).ToList(); await using (var consumer = new EventHubConsumerClient( EventHubConsumerClient.DefaultConsumerGroupName, diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample10_AzureEventSourceListenerTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample10_AzureEventSourceListenerTests.cs index bde86915b6cdc..3b11046118e61 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample10_AzureEventSourceListenerTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample10_AzureEventSourceListenerTests.cs @@ -38,7 +38,7 @@ public async Task ConsoleListener() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -82,7 +82,7 @@ public async Task TraceListener() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -126,7 +126,7 @@ public async Task CustomListenerWithFilter() var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; #endif @@ -189,7 +189,7 @@ public async Task CustomListenerWithFile() using Stream stream = new FileStream("<< PATH TO THE FILE >>", FileMode.OpenOrCreate, FileAccess.Write); #else - var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.EventHubsConnectionString; + var fullyQualifiedNamespace = EventHubsTestEnvironment.Instance.FullyQualifiedNamespace; var eventHubName = scope.EventHubName; var credential = EventHubsTestEnvironment.Instance.Credential; From 21f23f39527a87d1067917833f0c0ddf68ed4c1d Mon Sep 17 00:00:00 2001 From: Jesse Squire Date: Wed, 2 Oct 2024 13:27:20 -0700 Subject: [PATCH 04/16] Test debugging --- .../tests/Consumer/EventHubConsumerClientLiveTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs index 8534f3c6777fd..e877d2835fddd 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs @@ -2486,17 +2486,17 @@ public async Task ConsumerCanReadFromAllPartitionsStartingWithLatest() // Begin reading though no events have been published. This is necessary to open the connection and // ensure that the consumer is watching the partition. - var readTask = ReadEventsFromAllPartitionsAsync(consumer,sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token, startFromEarliest: false); + var readTask = ReadEventsFromAllPartitionsAsync(consumer, sourceEvents.Select(evt => evt.MessageId), cancellationSource.Token, startFromEarliest: false); // Give the consumer a moment to ensure that it is established and then send events for it to read. - await Task.Delay(250); + await Task.Delay(1250); await SendEventsToAllPartitionsAsync(scope.EventHubName, sourceEvents, partitions, cancellationSource.Token); // Read the events and validate the resulting state. var readState = await readTask; - Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); + //Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); Assert.That(readState.Events.Count, Is.EqualTo(sourceEvents.Count), "Only the source events should have been read."); foreach (var sourceEvent in sourceEvents) From 9102cfbc6043676b4c25ed91c6ecf0559de9725f Mon Sep 17 00:00:00 2001 From: Jesse Squire Date: Wed, 2 Oct 2024 14:32:25 -0700 Subject: [PATCH 05/16] tuning test timing and renabling cancellation check --- .../tests/Consumer/EventHubConsumerClientLiveTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs index e877d2835fddd..46354f947f761 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs @@ -2490,13 +2490,13 @@ public async Task ConsumerCanReadFromAllPartitionsStartingWithLatest() // Give the consumer a moment to ensure that it is established and then send events for it to read. - await Task.Delay(1250); + await Task.Delay(1000); await SendEventsToAllPartitionsAsync(scope.EventHubName, sourceEvents, partitions, cancellationSource.Token); // Read the events and validate the resulting state. var readState = await readTask; - //Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); + Assert.That(cancellationSource.IsCancellationRequested, Is.False, "The cancellation token should not have been signaled."); Assert.That(readState.Events.Count, Is.EqualTo(sourceEvents.Count), "Only the source events should have been read."); foreach (var sourceEvent in sourceEvents) From 516866fd19e5356c404b3c7eb1c2905851cbac2b Mon Sep 17 00:00:00 2001 From: Jesse Squire Date: Wed, 2 Oct 2024 15:32:22 -0700 Subject: [PATCH 06/16] tuning test timing --- .../tests/Consumer/EventHubConsumerClientLiveTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs index 46354f947f761..971e2d33d6118 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs @@ -2490,7 +2490,7 @@ public async Task ConsumerCanReadFromAllPartitionsStartingWithLatest() // Give the consumer a moment to ensure that it is established and then send events for it to read. - await Task.Delay(1000); + await Task.Delay(1250); await SendEventsToAllPartitionsAsync(scope.EventHubName, sourceEvents, partitions, cancellationSource.Token); // Read the events and validate the resulting state. From ae15323df80db35825fca35471b18858cf25bedc Mon Sep 17 00:00:00 2001 From: Jesse Squire Date: Thu, 3 Oct 2024 15:43:33 -0700 Subject: [PATCH 07/16] Extending test timing slightly --- .../tests/Consumer/EventHubConsumerClientLiveTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs index 971e2d33d6118..b322cbc6777d3 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Consumer/EventHubConsumerClientLiveTests.cs @@ -2490,7 +2490,7 @@ public async Task ConsumerCanReadFromAllPartitionsStartingWithLatest() // Give the consumer a moment to ensure that it is established and then send events for it to read. - await Task.Delay(1250); + await Task.Delay(1500); await SendEventsToAllPartitionsAsync(scope.EventHubName, sourceEvents, partitions, cancellationSource.Token); // Read the events and validate the resulting state. From fcd4d820e12528003028cbfea29e0c0f06420b69 Mon Sep 17 00:00:00 2001 From: Jesse Squire Date: Mon, 7 Oct 2024 17:05:52 -0700 Subject: [PATCH 08/16] Update sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs Co-authored-by: Madalyn Redding Heaps <66138537+m-redding@users.noreply.github.com> --- .../tests/Snippets/Sample02_EventHubsClientsLiveTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs index 5c257f84b9054..b5f1d0dc3011b 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs @@ -76,7 +76,7 @@ public async Task ConfigureProducerTransportByProperty() #region Snippet:EventHubs_Sample02_ProducerTransportProperty #if SNIPPET - var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else From 9512d2b8e6ac845303077983e09688bb51cd9d59 Mon Sep 17 00:00:00 2001 From: Jesse Squire Date: Mon, 7 Oct 2024 17:05:58 -0700 Subject: [PATCH 09/16] Update sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs Co-authored-by: Madalyn Redding Heaps <66138537+m-redding@users.noreply.github.com> --- .../tests/Snippets/Sample02_EventHubsClientsLiveTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs index b5f1d0dc3011b..8c09b788a65e2 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs @@ -35,7 +35,7 @@ public async Task ConfigureProducerTransportWithFullOptions() #region Snippet:EventHubs_Sample02_ProducerTransportFullConnectionOptions #if SNIPPET - var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else From e58bd1c725604149fa4c12428b611885c330977b Mon Sep 17 00:00:00 2001 From: Jesse Squire Date: Mon, 7 Oct 2024 17:06:07 -0700 Subject: [PATCH 10/16] Update sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs Co-authored-by: Madalyn Redding Heaps <66138537+m-redding@users.noreply.github.com> --- .../tests/Snippets/Sample02_EventHubsClientsLiveTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs index 8c09b788a65e2..be6cced932f43 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs @@ -112,7 +112,7 @@ public async Task ConfigureProducerProxyWithFullOptions() #region Snippet:EventHubs_Sample02_ProducerProxyFullConnectionOptions #if SNIPPET - var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else From 0c199c905496f9e614fb0fb783bcb25424ac9bdb Mon Sep 17 00:00:00 2001 From: Jesse Squire Date: Mon, 7 Oct 2024 17:06:13 -0700 Subject: [PATCH 11/16] Update sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs Co-authored-by: Madalyn Redding Heaps <66138537+m-redding@users.noreply.github.com> --- .../tests/Snippets/Sample02_EventHubsClientsLiveTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs index be6cced932f43..58c9f4d938fee 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs @@ -154,7 +154,7 @@ public async Task ConfigureProducerProxyByProperty() #region Snippet:EventHubs_Sample02_ProducerProxyProperty #if SNIPPET - var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else From 602253a2b147c55567b429c23929e6236e14128d Mon Sep 17 00:00:00 2001 From: Jesse Squire Date: Mon, 7 Oct 2024 17:06:20 -0700 Subject: [PATCH 12/16] Update sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs Co-authored-by: Madalyn Redding Heaps <66138537+m-redding@users.noreply.github.com> --- .../tests/Snippets/Sample02_EventHubsClientsLiveTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs index 58c9f4d938fee..e2ef07617aa82 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs @@ -191,7 +191,7 @@ public async Task ConfigureCustomEndpointAddress() #region Snippet:EventHubs_Sample02_ConnectionOptionsCustomEndpoint #if SNIPPET - var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else From 0aa06edd9705994d0faddeab833e0efa2fbcafcb Mon Sep 17 00:00:00 2001 From: Jesse Squire Date: Mon, 7 Oct 2024 17:06:32 -0700 Subject: [PATCH 13/16] Update sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs Co-authored-by: Madalyn Redding Heaps <66138537+m-redding@users.noreply.github.com> --- .../tests/Snippets/Sample02_EventHubsClientsLiveTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs index e2ef07617aa82..5dd88340b7cae 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs @@ -227,7 +227,7 @@ public async Task ConfigureRemoteCertificateValidationCallback() #region Snippet:EventHubs_Sample02_RemoteCertificateValidationCallback #if SNIPPET - var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else From f2c4f5d2002cc8ec7fa4ce68897c4b779205002f Mon Sep 17 00:00:00 2001 From: Jesse Squire Date: Mon, 7 Oct 2024 17:06:38 -0700 Subject: [PATCH 14/16] Update sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs Co-authored-by: Madalyn Redding Heaps <66138537+m-redding@users.noreply.github.com> --- .../tests/Snippets/Sample02_EventHubsClientsLiveTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs index 5dd88340b7cae..27c53ebddf59a 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs @@ -280,7 +280,7 @@ public async Task ConfigureConsumerRetryWithFullOptions() #region Snippet:EventHubs_Sample02_ConsumerRetryWithFullOptions #if SNIPPET - var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else From f5bb396f79e67f0ea3f2fa167b72973fcacce131 Mon Sep 17 00:00:00 2001 From: Jesse Squire Date: Mon, 7 Oct 2024 17:06:45 -0700 Subject: [PATCH 15/16] Update sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs Co-authored-by: Madalyn Redding Heaps <66138537+m-redding@users.noreply.github.com> --- .../tests/Snippets/Sample02_EventHubsClientsLiveTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs index 27c53ebddf59a..1583a2560b021 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs +++ b/sdk/eventhub/Azure.Messaging.EventHubs/tests/Snippets/Sample02_EventHubsClientsLiveTests.cs @@ -326,7 +326,7 @@ public async Task ConfigureConsumerRetryByProperty() #region Snippet:EventHubs_Sample02_ConsumerRetryByProperty #if SNIPPET - var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; + var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); #else From 00002b23920bd97ba57add8cdfbc2805cb4e507f Mon Sep 17 00:00:00 2001 From: Jesse Squire Date: Tue, 8 Oct 2024 12:17:26 -0700 Subject: [PATCH 16/16] Regenerating snippets --- .../samples/Sample02_EventHubsClients.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample02_EventHubsClients.md b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample02_EventHubsClients.md index 6dde7dbb860ae..0727e9e678820 100644 --- a/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample02_EventHubsClients.md +++ b/sdk/eventhub/Azure.Messaging.EventHubs/samples/Sample02_EventHubsClients.md @@ -55,7 +55,7 @@ Communication with the Event Hubs service can be configured by adjusting the `Ev For illustration, the `EventHubProducerClientOptions` are demonstrated, but the concept and form are common across the client options types. ```C# Snippet:EventHubs_Sample02_ProducerTransportFullConnectionOptions -var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); @@ -76,7 +76,7 @@ var producer = new EventHubProducerClient( The connection options are populated by default; you may set just the desired properties rather than creating a new instance, if you prefer. ```C# Snippet:EventHubs_Sample02_ProducerTransportProperty -var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); @@ -97,7 +97,7 @@ A common scenario for adjusting the connection options is configuring a proxy. For illustration, the `EventHubProducerClientOptions` are demonstrated, but the concept and form are common across the client options types. ```C# Snippet:EventHubs_Sample02_ProducerProxyFullConnectionOptions -var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); @@ -120,7 +120,7 @@ var producer = new EventHubProducerClient( The connection options are populated by default; you may set just the desired properties rather than creating a new instance, if you prefer. ```C# Snippet:EventHubs_Sample02_ProducerProxyProperty -var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); @@ -154,7 +154,7 @@ Connections to the Azure Event Hubs service are made using the fully qualified n Some environments using unconventional proxy configurations or with certain configurations of an Express Route circuit require a custom address be used for proper routing, leaving are unable to connect from their on-premises network to the Event Hubs service using the assigned endpoint address. To support these scenarios, a custom endpoint address may be specified as part of the connection options. This custom address will take precedence for establishing the connection to the Event Hubs service. ```C# Snippet:EventHubs_Sample02_ConnectionOptionsCustomEndpoint -var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); @@ -175,7 +175,7 @@ For some environments using a proxy or custom gateway for routing traffic to Eve By default, these certificates are not trusted by the Event Hubs client library and the connection will be refused. To enable these scenarios, a [RemoteCertificateValidationCallback](https://learn.microsoft.com/dotnet/api/system.net.security.remotecertificatevalidationcallback) can be registered to provide custom validation logic for remote certificates. This allows an application to override the default trust decision and assert responsibility for accepting or rejecting the certificate. ```C# Snippet:EventHubs_Sample02_RemoteCertificateValidationCallback -var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); @@ -213,7 +213,7 @@ The built-in retry policy offers an implementation for an exponential back-off s The values used as thresholds for the different aspects of these strategies can be configured by adjusting the `EventHubsRetryOptions` that are exposed by the `RetryOptions` member of a client options type. For illustration, the `EventHubConsumerClientOptions` are demonstrated, but the concept and form are common across the client options types. ```C# Snippet:EventHubs_Sample02_ConsumerRetryWithFullOptions -var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName; @@ -240,7 +240,7 @@ var consumer = new EventHubConsumerClient( The retry options are populated by default; you may set just the desired properties rather than creating a new instance, if you prefer. ```C# Snippet:EventHubs_Sample02_ConsumerRetryByProperty -var fullyQualifiedNamespace = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>"; +var fullyQualifiedNamespace = "<< NAMESPACE (likely similar to {your-namespace}.servicebus.windows.net) >>"; var eventHubName = "<< NAME OF THE EVENT HUB >>"; var credential = new DefaultAzureCredential(); var consumerGroup = EventHubConsumerClient.DefaultConsumerGroupName;