Skip to content

Remove dependencies on AfterEndpointsAllocatedEvent #9598

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

Merged
merged 4 commits into from
Jun 5, 2025

Conversation

danegsta
Copy link
Member

Description

In order to support proxyless persistent containers by default (and dynamic endpoint allocation in general), the AfterEndpointsAllocatedEvent is going to need to be deprecated. The current eventing model assumes that all endpoinst are allocated before any resources are created, but to properly support persistent containers, we'll have to break that assumption. This means that some endpoints may not become fully allocated until after resource creation starts.

This PR marks AfterEndpointsAllocatedEvent as [Obsolete] with instructions to use the resource specific BeforeResourceStartedEvent or ResourceEndpointsAllocatedEvent events as appropriate. Additionally it replaces all internal usage of AfterEndpointsAllocatedEvent with one of the two previous events.

The one remaining scenario that will need to be reworked is the AfterEndpointsAllocatedAsync callback in IDistributedApplicationLifecycleHook. The only internal usage is in DevcontainerPortForwardingLifecycleHook, but that will likely need to be rewritten to be event based too.

Fixes # (issue)

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected. (possible work for IDistributedApplicationLifecycleHook usage)
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No
  • Does the change require an update in our Aspire docs?

@Copilot Copilot AI review requested due to automatic review settings May 30, 2025 23:12
@danegsta danegsta requested a review from mitchdenny as a code owner May 30, 2025 23:12
@github-actions github-actions bot added the area-app-model Issues pertaining to the APIs in Aspire.Hosting, e.g. DistributedApplication label May 30, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR deprecates AfterEndpointsAllocatedEvent in favor of the more granular BeforeResourceStartedEvent and ResourceEndpointsAllocatedEvent, updating internal subscriptions and tests accordingly.

  • Mark AfterEndpointsAllocatedEvent as [Obsolete] and update all internal subscribe calls.
  • Replace test uses of the obsolete event with the appropriate new events (or suppress warnings when testing legacy behavior).
  • Remove obsolete event publishing in many tests and adjust builder extensions to use the new event model.

Reviewed Changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/Aspire.Hosting.Tests/WithUrlsTests.cs Updated subscription from AfterEndpointsAllocatedEvent to ResourceEndpointsAllocatedEvent.
tests/Aspire.Hosting.Tests/Eventing/DistributedApplicationBuilderEventingTests.cs Added pragmas to suppress warnings when subscribing to the obsolete event.
tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs Removed obsolete event publish calls (needs replacement in some tests).
tests/Aspire.Hosting.Qdrant.Tests/QdrantFunctionalTests.cs Switched subscription to ConnectionStringAvailableEvent.
tests/Aspire.Hosting.PostgreSQL.Tests/AddPostgresTests.cs Removed obsolete event publishes and changed test signature.
tests/Aspire.Hosting.MySql.Tests/AddMySqlTests.cs Updated to publish BeforeResourceStartedEvent for phpMyAdmin.
src/Aspire.Hosting/ResourceBuilderExtensions.cs Rewired health-check subscribe to ResourceEndpointsAllocatedEvent.
src/Aspire.Hosting/Orchestrator/ApplicationOrchestrator.cs Replaced subscribe to obsolete event; updated handler signature.
src/Aspire.Hosting/Lifecycle/IDistributedApplicationLifecycleHook.cs Introduced new AfterEndpointsAllocatedAsync default method.
src/Aspire.Hosting/ApplicationModel/AfterEndpointsAllocatedEvent.cs Marked the event class as [Obsolete].
src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs Switched commander extension to BeforeResourceStartedEvent.
src/Aspire.Hosting.MySql/MySqlBuilderExtensions.cs Replaced subscribe call to use new event for phpMyAdmin.
src/Aspire.Hosting.Kafka/KafkaBuilderExtensions.cs Updated Kafka UI subscribe to BeforeResourceStartedEvent.
Comments suppressed due to low confidence (7)

tests/Aspire.Hosting.Tests/WithUrlsTests.cs:56

  • The test name WithUrlsCallsCallbackAfterBeforeResourceStartedEvent suggests it should subscribe to BeforeResourceStartedEvent, but the code uses ResourceEndpointsAllocatedEvent. Either rename the test to match the new event or switch to BeforeResourceStartedEvent if that was intended.
builder.Eventing.Subscribe<ResourceEndpointsAllocatedEvent>(projectA.Resource, (e, ct) =>

tests/Aspire.Hosting.Redis.Tests/AddRedisTests.cs:303

  • After removing the obsolete publish of AfterEndpointsAllocatedEvent, this test no longer triggers the resource-specific event. Add a await builder.Eventing.PublishAsync<BeforeResourceStartedEvent>(new(redisInsight, app.Services)); before asserting environment variables.
var redisInsight = Assert.Single(builder.Resources.OfType<RedisInsightResource>());

src/Aspire.Hosting/Orchestrator/ApplicationOrchestrator.cs:98

  • This still publishes the obsolete AfterEndpointsAllocatedEvent. It should be replaced with ResourceEndpointsAllocatedEvent (or other resource-specific events) to align with the new deprecation model.
await _eventing.PublishAsync(afterEndpointsAllocatedEvent, context.CancellationToken).ConfigureAwait(false);

src/Aspire.Hosting.Redis/RedisBuilderExtensions.cs:172

  • The variable hostString is no longer declared in scope because the if block was removed. Restore declaration or conditional check to avoid a compilation error.
hostsVariableBuilder.Append(hostString);

src/Aspire.Hosting.Kafka/KafkaBuilderExtensions.cs:118

  • [nitpick] The original check for InternalEndpoint.IsAllocated was removed. Consider re-introducing a check so you only configure the UI for resources whose endpoints are ready.
var endpoint = kafkaResource.InternalEndpoint;

src/Aspire.Hosting/Lifecycle/IDistributedApplicationLifecycleHook.cs:31

  • Since AfterEndpointsAllocatedEvent is deprecated, mark this lifecycle hook method with [Obsolete] to guide implementers toward the replacement events.
Task AfterEndpointsAllocatedAsync(DistributedApplicationModel appModel, CancellationToken cancellationToken = default)

tests/Aspire.Hosting.PostgreSQL.Tests/AddPostgresTests.cs:372

  • This test was converted to void and no longer awaits event publishing. If you intend to publish BeforeResourceStartedEvent for pgadmin, mark the test async Task and await the publish call to ensure setup runs before assertions.
public void WithPgAdminAddsContainer()

…nt.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@danegsta danegsta requested review from davidfowl and JamesNK May 30, 2025 23:30
@@ -26,6 +26,7 @@ namespace Aspire.Hosting.ApplicationModel;
/// </code>
/// </example>
/// </remarks>
[Obsolete("The AfterEndpointsAllocatedEvent is deprecated and will be removed in a future version. Use the resource specific events BeforeResourceStartedEvent or ResourceEndpointsAllocatedEvent instead depending on your needs.")]
Copy link
Member

Choose a reason for hiding this comment

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

@Aaronontheweb @Alirexaa big change coming.

@@ -240,48 +242,45 @@ private async Task ProcessUrls(IResource resource, CancellationToken cancellatio
}
}

private Task ProcessResourcesWithoutLifetime(AfterEndpointsAllocatedEvent @event, CancellationToken cancellationToken)
private async Task ProcessResourcesWithoutLifetime(ResourceEndpointsAllocatedEvent @event, CancellationToken cancellationToken)
Copy link
Member

Choose a reason for hiding this comment

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

This is a sketchiest change 😄

Copy link
Member Author

Choose a reason for hiding this comment

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

It’s definitely the one that stood out the most, but at least with the current event behavior/timing it should behave the same.

@davidfowl
Copy link
Member

Can you also deprecate IDistributedApplicationLifecycleHook.AfterEndpointsAllocatedAsync. I think we have that all over the place.

@danegsta
Copy link
Member Author

danegsta commented Jun 2, 2025

Can you also deprecate IDistributedApplicationLifecycleHook.AfterEndpointsAllocatedAsync. I think we have that all over the place.

Main headache there is that marking the interface method as [Obsolete] won't cause the analyzers to flag any classes that implement it. We'd have to mark the whole IDistributedApplicationLifecycleHook obsolete if we want users to actually see any warnings/errors before the method goes away.

Copy link
Member

@davidfowl davidfowl left a comment

Choose a reason for hiding this comment

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

Lets get this in to see if there are any regressions

@danegsta danegsta merged commit 4f2dcfc into dotnet:main Jun 5, 2025
254 checks passed
@davidfowl
Copy link
Member

@balachir can you make sure to spend extra time on potential regressions here? These are all of the ui tools we have.

@davidfowl
Copy link
Member

@mitchdenny you should be aware of this change.

@DamianEdwards you too.

@mitchdenny
Copy link
Member

@aaronpowell heads up. Biggish change in 9.4

@balachir
Copy link

balachir commented Jun 6, 2025

@v-elenafeng please see comments above. Please work with your team to do extra and focused ET when we validate this change for 9.4. And also prioritize this validation for early next week so that we can catch any issues soon.

@DamianEdwards
Copy link
Member

Woah this will have a bunch of ramifications. I'm working on a separate change to modify how URL processing works and that includes making custom resources responsible for the firing of their own ResourceEndpointsAllocatedEvent and this change makes that much more impactful.

@danegsta
Copy link
Member Author

danegsta commented Jun 7, 2025

Woah this will have a bunch of ramifications. I'm working on a separate change to modify how URL processing works and that includes making custom resources responsible for the firing of their own ResourceEndpointsAllocatedEvent and this change makes that much more impactful.

This is necessary to support running persistent containers without proxies by default, as proxyless containers have async endpoint availability (if a random host port is used, the container resource has to be created before the endpoint is actually allocated if no proxy is used).

The main headache is that lots of code assumes AfterEndpointsAllocatedEvent is fired before ay resources are created (because so far that was guaranteed behavior), but with proxyless containers, we can't make that guarantee anymore. Ultimately, in most (if not all) cases AfterEndpointsAllocatedEvent wasn't actually used for the name on the tin, since it was either being used to do an operation before resources were created or to retrieve the endpoints for a specific resource (which ultimately ResourceEndpointsAllocatedEvent is a better fit for anyway).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-app-model Issues pertaining to the APIs in Aspire.Hosting, e.g. DistributedApplication
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants