Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Azure Event Hubs #2870

Merged
merged 56 commits into from
Mar 27, 2024
Merged

Conversation

oising
Copy link
Contributor

@oising oising commented Mar 13, 2024

Initial support for Azure Event Hubs, as per #1147

  • Minimally adapt the Service Bus component and resource for Event Hubs
  • Add top-level support for EventHubProducerClient
  • Add top-level support for EventHubConsumerClient
  • Add top-level support for EventProcessorClient
    • Allow providing component name for a BlobContainerClient to use (read connection string and instantiate local instance)
    • Read BlobContainerClient from keyed DI using its Aspire connection name
  • Add top-level support for PartitionReceiver
  • Add playground sample AppHost and projects (modify davidfowl's test project)
  • Add ability to configure credential used in Azure Provisioner (via AzureProvisionCredential in AppHost configuration)
  • Add xmldoc documentation for components etc
  • Update README

Optional extras (may defer to a second PR)

  • Add support for chained AddHub(...) calls for top-level EH resource to allow variable config of hubs
    • Implement as child resource to allow deep-linking (i.e. provide connection string including EntityPath)
  • Implement Microsoft.Extensions.Azure style top-level component AddEventHubs(...) and hang clients configuration from clientBuilder
  • Add Streaming sample with Orleans

Aspire API shortcomings

EventProcessorClient requires a BlobContainerClient for managing EH checkpoints. Ideally we should be able to pass a connection name to a mounted aspire blob client component and retrieve the instance from the service provider, but there is no plumbing to get it in the component infra. The unbuilt service collection is available on the distributed builder and it could be fished out of there, assuming it was added before the current component, but this seems flakey. Instead, I'm creating a new blob client using the blob connection name (taken from user-supplied settings) and creating my own.

Microsoft Reviewers: Open in CodeFlow

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-integrations Issues pertaining to Aspire Integrations packages label Mar 13, 2024
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Mar 13, 2024
@davidfowl
Copy link
Member

The azure provisioning stuff here is outdated so I would just delete all of it since it isn't required.

@davidfowl
Copy link
Member

This entire PR seems based on a really old version of aspire. Everything is bicep based now.

@oising
Copy link
Contributor Author

oising commented Mar 14, 2024

This entire PR seems based on a really old version of aspire. Everything is bicep based now.

I think your definition of "really old" doesn't match with mine :) I'm working off of main, and I cloned barely a week ago? I'll update it.

@davidfowl
Copy link
Member

davidfowl commented Mar 14, 2024

I'm not sure what happened in this PR, but if you look at main the Aspire.Hosting.Azure.Provisioning package has been deleted... 😄

#2603

Somehow this brought it back.

@oising
Copy link
Contributor Author

oising commented Mar 14, 2024

I'm not sure what happened in this PR, but if you look at main the Aspire.Hosting.Azure.Provisioning package has been deleted... 😄

#2603

Somehow this brought it back.

I'll start from scratch -- tbh, this first pass was just about understanding how components and resources work (in this week's build lol)

@oising
Copy link
Contributor Author

oising commented Mar 15, 2024

Restarting for the third time, because of #2875

Done.

@oising oising force-pushed the support-eventhubs branch from 92b3a87 to fd9b1af Compare March 16, 2024 06:29
oising added 2 commits March 16, 2024 02:44
…onents); modified davidfowl's demo EH project to use new resources and components; bugfixes;
@davidfowl
Copy link
Member

@sebastienros @eerhardt for the component review
@mitchdenny @JoshLove-msft for the resource review. CDK codegen is also required here.

@davidfowl
Copy link
Member

Also @jsquire for azure sdk review

@oising
Copy link
Contributor Author

oising commented Mar 17, 2024

I rebased to stay up to date and now I'm hitting:

Application orchestrator dependency check had an unexpected error System.TimeoutException: The operation has timed out.
at Aspire.Hosting.Dcp.DcpDependencyCheck.EnsureDcpDependenciesAsync(CancellationToken cancellationToken) in C:\p\github\aspire\src\Aspire.Hosting\Dcp\DcpDependencyCheck.cs:line 67

on start up.

@davidfowl
Copy link
Member

Application orchestrator dependency check had an unexpected error System.TimeoutException: The operation has timed out.
at Aspire.Hosting.Dcp.DcpDependencyCheck.EnsureDcpDependenciesAsync(CancellationToken cancellationToken) in C:\p\github\aspire\src\Aspire.Hosting\Dcp\DcpDependencyCheck.cs:line 67

Consistently?

@oising
Copy link
Contributor Author

oising commented Mar 17, 2024

Application orchestrator dependency check had an unexpected error System.TimeoutException: The operation has timed out.
at Aspire.Hosting.Dcp.DcpDependencyCheck.EnsureDcpDependenciesAsync(CancellationToken cancellationToken) in C:\p\github\aspire\src\Aspire.Hosting\Dcp\DcpDependencyCheck.cs:line 67

Consistently?

Yes. I tried bumping the timeout to 5 mins and at some point something else timed out and brought the whole process down. I tried disabling the timeout (setting to 0) and same thing. Tried about a half dozen times.

edit: resolved, see #3003

No need to construct this (we recently changed this in the others).
@eerhardt
Copy link
Member

FYI @oising, I pushed some changes you should be aware of. The most important is that I fixed Tracing to work. Just wanted to let you know so you don't force push and revert those changes.

I think this is close to getting the initial merge. My most major concerns are:

  • Getting the Storage Blob client. I really think this should come from DI
  • The Settings class having properties that don't work depending on the client being used.
  • Full testing

If we want to merge this soon to guarantee it gets into preview5, and log issues for these to be followed up, I would be OK with that. FYI @davidfowl

@oising
Copy link
Contributor Author

oising commented Mar 26, 2024

FYI @oising, I pushed some changes you should be aware of. The most important is that I fixed Tracing to work. Just wanted to let you know so you don't force push and revert those changes.

I think this is close to getting the initial merge. My most major concerns are:

  • Getting the Storage Blob client. I really think this should come from DI
  • The Settings class having properties that don't work depending on the client being used.
  • Full testing

If we want to merge this soon to guarantee it gets into preview5, and log issues for these to be followed up, I would be OK with that. FYI @davidfowl

Thanks @eerhardt -- I really appreciate the thorough review and insightful suggestions :) I'm about to check in the suggested split settings approach as discussed above. It took a bit of jiggery-pokery with generics to fix a few things, but it seems to be good now.

As for the storage blob client, yes, I agree this is a bit of a rough edge; especially around the lack of unit tests here. As mentioned, the service provider isn't built at this point, but I could build it and look for a blob client within. I think this needs some configuration-by-convention love in the sense that we should probably only permit a keyed blob client so it can be configured in settings. Also, to test the logic around the container creation, I might want to lightly shim the blob client so I can unit test the behaviour without requiring a live connection. I'll spike this tomorrow.

@eerhardt
Copy link
Member

As mentioned, the service provider isn't built at this point, but I could build it and look for a blob client within.

This isn't necessary. We should just be able to call a different overload on the AzureClientFactoryBuilder, which gives us the IServiceProvider. See https://github.com/Azure/azure-sdk-for-net/blob/87d426597b261b88f8a6c6c21fab6031f857fb70/sdk/extensions/Microsoft.Extensions.Azure/src/AzureClientFactoryBuilder.cs#L164-L172. (Note it would take some refactoring of the base AzureComponent<TSettings, TClient, TClientOptions> class, as right now the abstract AddClient method takes a TBuilder, when it could just be passed an AzureClientFactoryBuilder.

I think this needs some configuration-by-convention love in the sense that we should probably only permit a keyed blob client so it can be configured in settings.

I see it a different way. It should allow for a keyed blob client, but shouldn't require it to be keyed. If no "blob service key" was configured, it should just get the BlobServiceClient from DI. If a "blob service key" was specified, then use it to get the BlobServiceClient from DI.

That way the simple case "just works". You just need to:

var builder = WebApplication.CreateBuilder(args);

builder.AddAzureBlobClient("blobConnectionName");
builder.AddAzureEventProcessorClient("eventhubns");

and the EventProcessorClient grabs the BlobClient. There's no need to force someone to use keys when there is only one.

- Remove unnecessary Directory.Packages.props entry
- Fix ConfigurationSchema.json to match implementation
- StringComparison.Ordinal is unnecessary when looking for a char
Copy link
Member

@eerhardt eerhardt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, @oising, for this contribution! Great work!

This LGTM to merge for preview5.

Can you log follow up issues for the remaining work? Notably:

  • Using DI to get the blob client in the EventProcessor
  • Testing
  • (I might have missed others. Please ensure it is all logged.)

@eerhardt eerhardt enabled auto-merge (squash) March 27, 2024 16:14
@eerhardt eerhardt merged commit 795a489 into dotnet:main Mar 27, 2024
8 checks passed
eerhardt added a commit to eerhardt/aspire that referenced this pull request Mar 27, 2024
* initial commit for event hubs component and resource (non-functional, but skeleton is there)

* corrected roledefinition

* added consumer client (now have producer, consumer and processor components); modified davidfowl's demo EH project to use new resources and components; bugfixes;

* fixes for processor client; updated build props/targets for playground project

* Update AzureEventHubsExtensions.cs

No need to construct this (we recently changed this in the others).

* some minor refactoring of processor client; made playground project more robust

* address review items; automatically generate processor identifier from hub and consumergroup; add more comments; minor refactoring

* Update src/Aspire.Hosting.Azure/Extensions/AzureEventHubsExtensions.cs

Co-authored-by: Jesse Squire <jesse.squire@gmail.com>

* Update src/Aspire.Hosting.Azure/Extensions/AzureEventHubsExtensions.cs

Co-authored-by: Jesse Squire <jesse.squire@gmail.com>

* update EH endpoint references to use eventHubsEndpoint instead of serviceBusEndpoint; beef up processor identifier naming.

* add ability to configure credential for azure provisioner (removed my hack); added first batch of documentation for component; added partitionreceiver component.

* Update src/Components/Aspire.Azure.Messaging.EventHubs/AzureMessagingEventHubsSettings.cs

Co-authored-by: Jesse Squire <jesse.squire@gmail.com>

* remove azure provisioner credential configuration stuff (will go into separate PR)

* address review points; refactor namespace parsing into base eh component

* fix package tags and add new icon to shared

* remove providercredential reference from config

* fix some more errant service bus mentions and regenerate configurationschema

* fix xmlcomment on settings

* remove azure section from sample config

* update components README.md

* delete EH playground readme

* minor edits for clarification

* port ASB connection/namespace tests; rewrite validation logic to be more robust

* Update playground/AspireEventHub/EventHubs.AppHost/EventHubs.AppHost.csproj

Co-authored-by: Eric Erhardt <eric.erhardt@microsoft.com>

* Update playground/AspireEventHub/EventHubsConsumer/EventHubsConsumer.csproj

Co-authored-by: Eric Erhardt <eric.erhardt@microsoft.com>

* Update src/Aspire.Hosting.Azure.EventHubs/Aspire.Hosting.Azure.EventHubs.csproj

Co-authored-by: Eric Erhardt <eric.erhardt@microsoft.com>

* generate aspire manifest etc for EH sample

* moved processor Start code into Execute for worker sample

* fixed another ref to service bus

* refine checkpoint blob container creation logic to avoid unnecessary permission demand if we can

* enhance logic for blob checkpoint container; add BlobContainerName to settings as an option

* persist checkpoints in processor sample for EH

* renamed settings class in tests to match AEH; was ASB.

* Fix Tracing with EventHubs
Update Telemetry and Components Progress docs
Minor cleanup feedback

* refactor EH client settings into individual classes

* Add readme for EH hosting

* Fix build

* Address PR feedback

- Remove unnecessary Directory.Packages.props entry
- Fix ConfigurationSchema.json to match implementation
- StringComparison.Ordinal is unnecessary when looking for a char

---------

Co-authored-by: Mitch Denny <mitchdenny@outlook.com>
Co-authored-by: Jesse Squire <jesse.squire@gmail.com>
Co-authored-by: Eric Erhardt <eric.erhardt@microsoft.com>
davidfowl pushed a commit that referenced this pull request Mar 27, 2024
* initial commit for event hubs component and resource (non-functional, but skeleton is there)

* corrected roledefinition

* added consumer client (now have producer, consumer and processor components); modified davidfowl's demo EH project to use new resources and components; bugfixes;

* fixes for processor client; updated build props/targets for playground project

* Update AzureEventHubsExtensions.cs

No need to construct this (we recently changed this in the others).

* some minor refactoring of processor client; made playground project more robust

* address review items; automatically generate processor identifier from hub and consumergroup; add more comments; minor refactoring

* Update src/Aspire.Hosting.Azure/Extensions/AzureEventHubsExtensions.cs



* Update src/Aspire.Hosting.Azure/Extensions/AzureEventHubsExtensions.cs



* update EH endpoint references to use eventHubsEndpoint instead of serviceBusEndpoint; beef up processor identifier naming.

* add ability to configure credential for azure provisioner (removed my hack); added first batch of documentation for component; added partitionreceiver component.

* Update src/Components/Aspire.Azure.Messaging.EventHubs/AzureMessagingEventHubsSettings.cs



* remove azure provisioner credential configuration stuff (will go into separate PR)

* address review points; refactor namespace parsing into base eh component

* fix package tags and add new icon to shared

* remove providercredential reference from config

* fix some more errant service bus mentions and regenerate configurationschema

* fix xmlcomment on settings

* remove azure section from sample config

* update components README.md

* delete EH playground readme

* minor edits for clarification

* port ASB connection/namespace tests; rewrite validation logic to be more robust

* Update playground/AspireEventHub/EventHubs.AppHost/EventHubs.AppHost.csproj



* Update playground/AspireEventHub/EventHubsConsumer/EventHubsConsumer.csproj



* Update src/Aspire.Hosting.Azure.EventHubs/Aspire.Hosting.Azure.EventHubs.csproj



* generate aspire manifest etc for EH sample

* moved processor Start code into Execute for worker sample

* fixed another ref to service bus

* refine checkpoint blob container creation logic to avoid unnecessary permission demand if we can

* enhance logic for blob checkpoint container; add BlobContainerName to settings as an option

* persist checkpoints in processor sample for EH

* renamed settings class in tests to match AEH; was ASB.

* Fix Tracing with EventHubs
Update Telemetry and Components Progress docs
Minor cleanup feedback

* refactor EH client settings into individual classes

* Add readme for EH hosting

* Fix build

* Address PR feedback

- Remove unnecessary Directory.Packages.props entry
- Fix ConfigurationSchema.json to match implementation
- StringComparison.Ordinal is unnecessary when looking for a char

---------

Co-authored-by: Oisin Grehan <oising@gmail.com>
Co-authored-by: Mitch Denny <mitchdenny@outlook.com>
Co-authored-by: Jesse Squire <jesse.squire@gmail.com>
@oising oising deleted the support-eventhubs branch March 27, 2024 20:35
@davidfowl
Copy link
Member

Thank you @oising !!!!!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-integrations Issues pertaining to Aspire Integrations packages community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants