-
Notifications
You must be signed in to change notification settings - Fork 462
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
Conversation
The azure provisioning stuff here is outdated so I would just delete all of it since it isn't required. |
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. |
I'm not sure what happened in this PR, but if you look at main the Aspire.Hosting.Azure.Provisioning package has been deleted... 😄 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) |
Restarting for the third time, because of #2875 Done. |
… but skeleton is there)
92b3a87
to
fd9b1af
Compare
…onents); modified davidfowl's demo EH project to use new resources and components; bugfixes;
playground/AspireEventHub/EventHubs.ServiceDefaults/Extensions.cs
Outdated
Show resolved
Hide resolved
@sebastienros @eerhardt for the component review |
Also @jsquire for azure sdk review |
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. on start up. |
src/Components/Aspire.Azure.Messaging.EventHubs/EventProcessorClientComponent.cs
Outdated
Show resolved
Hide resolved
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).
src/Aspire.Hosting.Azure/Provisioning/Provisioners/AzureProvisioner.cs
Outdated
Show resolved
Hide resolved
src/Aspire.Hosting.Azure/Extensions/AzureEventHubsExtensions.cs
Outdated
Show resolved
Hide resolved
src/Aspire.Hosting.Azure/Extensions/AzureEventHubsExtensions.cs
Outdated
Show resolved
Hide resolved
src/Aspire.Hosting.Azure/Extensions/AzureEventHubsExtensions.cs
Outdated
Show resolved
Hide resolved
The following example assumes that you have an Azure Event Hubs namespace and an Event Hub created and wish to configure an `EventHubProducerClient` to send events to the Event Hub. The `EventHubConsumerClient`, `EventProcessorClient`, and `PartitionReceiver`are configured in a similar manner. | ||
|
||
In the _Program.cs_ file of your project, call the `AddAzureEventHubProducerClient` extension method to register | ||
a `EventHubProducerClient` for use via the dependency injection container. The method takes a connection name parameter. This assumes you have included the `EntityPath` in the connection string to specify the Event Hub name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assumes you have included the
EntityPath
in the connection string to specify the Event Hub name.
This doesn't seem ideal, since we say we don't recommend using a connection string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is also surprising since I would have expected:
var eventHub = builder.AddAzureEventHubs("eventhubns")
.AddEventHub("hub");
builder.AddProject<Projects.EventHubsApi>("api")
.WithReference(eventHub);
To result with the EntityPath
in the connection string (just like it does if I'm using a database server + database, the connection string has Database=<db_name>
in the connection string.
Is the above code supposed to use EntityPath
in the connection string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mitchdenny Brought this up already and it would mean making the "hub" it's own de-facto AspireResource to enable deep-linking like this. I replied and said the same could be said for allowing deep-linking of ASB topic and queues (a feature that isn't there either) so I think this could be punted for another release. But yep, you're right -- AEH and ASB should do like MSSQL does. But I don't have time to get this done for this release. I'm happy to improve it for P6.
As you (or maybe someone else said?) before, while we do control what Resources inject as connection strings when using an AppHost, we don't control what developers may do when managing their own connection strings. I'd rather that we "do the right thing" when a dev passes an entitypath. It seems like the path of least surprise. It's what I would expect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't control what developers may do when managing their own connection strings. I'd rather that we "do the right thing" when a dev passes an entitypath. It seems like the path of least surprise. It's what I would expect.
I don't disagree that we should "do the right thing" when someone passes an entitypath.
The part I was commenting on is the "Usage example" the README gives assumes you are doing something we don't recommend you do - use a connection string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, gotcha!
/// </summary> | ||
/// <param name="builder">The Azure Event Hubs resource builder.</param> | ||
/// <param name="name">The name of the Event Hub.</param> | ||
public static IResourceBuilder<AzureEventHubsResource> AddEventHub(this IResourceBuilder<AzureEventHubsResource> builder, string name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This API pattern differs from how databases work. I think it will be surprising to our customers.
In databases, we have:
var db = builder.AddPostgres("db-server").AddDatabase("db1");
builder.AddProject<Projects.Api>("api")
.WithReference(db);
When executing that code, db
points to the db1
resource - a "child" of the db-server
. So when you .WithReference(db)
, the connection string name that you use in your app is going to be db1
.
But here,
var hub = builder.AddEventHubs("eventhub-ns").AddEventHub("hub");
builder.AddProject<Projects.Api>("api")
.WithReference(hub);
hub
is going to point to the eventhub-ns
resource, and not the hub
resource. So in your web app, you need to use builder.AddAzureEventHubProducerClient("eventhub-ns")
, which is different than how databases work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree 100% -- see my comment above. The service bus resource is equally deficient, and I copied that code. I'd want to see this fixes for both ASB and AEH in P6. /cc @mitchdenny
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this work with managed identity?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this work with managed identity?
Did you mean to put this here, @davidfowl ? If so, I don't see why not?
Update Telemetry and Components Progress docs Minor cleanup feedback
src/Aspire.Hosting.Azure.EventHubs/Aspire.Hosting.Azure.EventHubs.csproj
Show resolved
Hide resolved
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:
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. |
This isn't necessary. We should just be able to call a different overload on the AzureClientFactoryBuilder, which gives us the
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 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
There was a problem hiding this 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.)
* 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 <[email protected]> * Update src/Aspire.Hosting.Azure/Extensions/AzureEventHubsExtensions.cs Co-authored-by: Jesse Squire <[email protected]> * 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 <[email protected]> * 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 <[email protected]> * Update playground/AspireEventHub/EventHubsConsumer/EventHubsConsumer.csproj Co-authored-by: Eric Erhardt <[email protected]> * Update src/Aspire.Hosting.Azure.EventHubs/Aspire.Hosting.Azure.EventHubs.csproj Co-authored-by: Eric Erhardt <[email protected]> * 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 <[email protected]> Co-authored-by: Jesse Squire <[email protected]> Co-authored-by: Eric Erhardt <[email protected]>
* 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 <[email protected]> Co-authored-by: Mitch Denny <[email protected]> Co-authored-by: Jesse Squire <[email protected]>
Thank you @oising !!!!! |
Initial support for Azure Event Hubs, as per #1147
Optional extras (may defer to a second PR)
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