WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 8, 2025

Summary

Fixes #7733 - OnBeforeResourceStarted event firing twice on container restart

Problem

When restarting a container resource via the dashboard, the OnBeforeResourceStarted event was being fired twice instead of once. This was causing duplicate log messages and potentially triggering callbacks twice.

Root Cause

In DcpExecutor.StartResourceAsync, when restarting a container:

  1. Line 2405 publishes OnResourceStartingContext
  2. Then calls CreateContainerAsync
  3. Line 1918 in CreateContainerAsync publishes OnResourceStartingContext again
  4. ApplicationOrchestrator.OnResourceStarting handler publishes BeforeResourceStartedEvent for each context

Solution

Remove the duplicate OnResourceStartingContext publish from StartResourceAsync for containers. CreateContainerAsync already publishes this event during both initial creation and restart, so the duplicate was unnecessary.

Why Executables Are Unaffected

Executables follow a different pattern:

  • Initial creation: CreateResourceExecutablesAsyncCore publishes the event (line 1506) before calling CreateExecutableAsync
  • Restart: StartResourceAsync publishes the event before calling CreateExecutableAsync
  • CreateExecutableAsync never publishes the event

Therefore, removing the event publish from StartResourceAsync for executables would break initial startup.

Changes Made

  • src/Aspire.Hosting/Dcp/DcpExecutor.cs: Removed duplicate OnResourceStartingContext publish in StartResourceAsync for containers
  • tests/Aspire.Hosting.Tests/Dcp/DcpExecutorTests.cs: Added two tests:
    • ContainerRestarted_OnResourceStartingContextFiredOnce - Verifies containers only fire the event once on restart
    • ResourceRestarted_OnResourceStartingContextFiredOnce - Verifies executables still work correctly
    • Both tests use WithTestAndResourceLogging for better diagnostics

Testing

  • ✅ Added ContainerRestarted_OnResourceStartingContextFiredOnce test - reproduces the bug before the fix, passes after
  • ✅ Added ResourceRestarted_OnResourceStartingContextFiredOnce test - ensures executables still work correctly
  • ✅ All 63 DcpExecutorTests pass
  • ✅ All 14 ApplicationOrchestratorTests pass
  • ✅ Tests use WithTestAndResourceLogging for diagnostics
  • ✅ Code review completed
Original prompt

This section details on the original issue you should resolve

<issue_title>OnBeforeResourceStarted being fired twice on restart</issue_title>
<issue_description>### Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

If you restart a resource, the OnBeforeResourceStarted event seems to get fired twice if you try to restart a resource.

Expected Behavior

The event should only get fired a single time for each restart.

Image

Steps To Reproduce

  1. Start the following app host
  2. On the dashboard restart the nginx resource (both restart and stop/start reproduce)
  3. Observe the "Before Start" messages in the console output
var builder = DistributedApplication
    .CreateBuilder(args);

var foo = builder.AddContainer("nginx", "nginx")
    .OnBeforeResourceStarted((_, _, _) =>
    {
        Console.WriteLine($"Before Start {DateTime.Now}");
        return Task.CompletedTask;
    });

builder.Build().Run();

Exceptions (if any)

Logs:

During startup, the "Before Start" line is only printed once as you'd expect. but the restart at the end of logs shows two events fired at pretty much the same time.

info: Aspire.Hosting.DistributedApplication[0]
      Aspire version: 13.0.0+7512c2944094a58904b6c803aa824c4a4ce42e11
info: Aspire.Hosting.DistributedApplication[0]
      Distributed application starting.
info: Aspire.Hosting.DistributedApplication[0]
      Application host directory is: S:\DotNetConf\DotNetConf.AppHost
Before Start 20/11/2025 13:53:19
info: Aspire.Hosting.DistributedApplication[0]
      Distributed application started. Press Ctrl+C to shut down.
info: Aspire.Hosting.DistributedApplication[0]
      Now listening on: https://localhost:17031
info: Aspire.Hosting.DistributedApplication[0]
      Login to the dashboard at https://localhost:17031/login?t=0d33a1e5059de528e9cba4cb8b116462
Before Start 20/11/2025 13:53:33
Before Start 20/11/2025 13:53:33

.NET Version info

No response

Anything else?

No response</issue_description>

<agent_instructions>Make a repro of this problem before investigating it using the steps in the issue. Then once you have that (it could be a test), then reproduce the problem and look for the solution.

These events are raised in ApplicationOrchestrator and DcpExecutor.</agent_instructions>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits December 8, 2025 09:06
- Remove duplicate OnResourceStartingContext publish in StartResourceAsync for containers
- CreateContainerAsync already publishes this event during both initial creation and restart
- Executables are unaffected as they follow a different pattern
- Add test to verify the fix for containers
- Add test to verify executables still work correctly

Co-authored-by: davidfowl <[email protected]>
- Use consistent DistributedApplicationOptions in both tests
- Both tests now follow the same pattern for builder initialization

Co-authored-by: davidfowl <[email protected]>
c.Spec.Start = true;

await _executorEvents.PublishAsync(new OnResourceStartingContext(cancellationToken, resourceType, appResource.ModelResource, appResource.DcpResourceName)).ConfigureAwait(false);
// OnResourceStartingContext will be published by CreateContainerAsync
Copy link
Member

Choose a reason for hiding this comment

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

@copilot Is this correct? What will not firing OnResourceStartingContext break?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, this is correct. Both the initial creation path and the restart path go through CreateContainerAsync, which publishes OnResourceStartingContext at line 1918.

Initial creation: CreateContainersAsyncCreateContainerAsyncCoreCreateContainerAsync → publishes event
Restart: StartResourceAsyncCreateContainerAsync → publishes event

The only subscriber is ApplicationOrchestrator.OnResourceStarting, which sets the state to "Starting", updates container properties, and publishes BeforeResourceStartedEvent. This all still happens correctly with the change.

The bug was that on restart, StartResourceAsync was publishing the event AND then CreateContainerAsync was publishing it again, causing the duplicate. The test ContainerRestarted_OnResourceStartingContextFiredOnce verifies this fix works correctly.

Copilot AI changed the title [WIP] Fix OnBeforeResourceStarted firing twice on resource restart Fix duplicate OnBeforeResourceStarted event on container restart Dec 8, 2025
Copilot AI requested a review from davidfowl December 8, 2025 09:20
@github-actions
Copy link
Contributor

github-actions bot commented Dec 8, 2025

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 13385

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 13385"

@davidfowl davidfowl requested review from JamesNK and danegsta December 8, 2025 17:22
@davidfowl
Copy link
Member

@copilot these added test should be using the WithTestAndResourceLogging API

- Add ITestOutputHelper parameter to DcpExecutorTests class constructor
- Call WithTestAndResourceLogging in both new tests for better diagnostics
- Add using statement for Aspire.Hosting.Utils namespace

Co-authored-by: davidfowl <[email protected]>
Copy link
Contributor Author

Copilot AI commented Dec 9, 2025

@copilot these added test should be using the WithTestAndResourceLogging API

Updated in commit 641ce83. Added ITestOutputHelper parameter to the test class and called WithTestAndResourceLogging in both tests for better diagnostics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OnBeforeResourceStarted being fired twice on restart

2 participants