Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 16, 2025

Problem

When running aspire run in watch mode, the CLI incorrectly exits when the backchannel disconnects. However, backchannel disconnections in watch mode typically occur because dotnet watch has restarted the apphost (e.g., due to a 'rude' change in Program.cs). The CLI should attempt to reconnect instead of terminating.

Solution

This PR refactors the backchannel disconnect handling in DotNetCliRunner to detect watch mode and automatically attempt reconnection when a disconnect occurs:

Watch Mode Behavior (New)

  • When the backchannel disconnects, the CLI now logs an informational message and attempts to reconnect
  • Reconnection attempts occur up to 30 times over approximately 30 seconds (1 second between attempts)
  • On successful reconnection, the CLI continues running and the dashboard remains accessible
  • The disconnect handler is recursively re-established after each successful reconnection
  • If the apphost process exits with a non-zero code or all reconnection attempts fail, the CLI exits appropriately

Non-Watch Mode Behavior (Unchanged)

  • Maintains existing behavior: CLI exits immediately on backchannel disconnect
  • No reconnection attempts are made

Implementation Details

DotNetCliRunner.cs changes:

  • Added IsWatchMode property to DotNetCliRunnerInvocationOptions to track watch mode state
  • Modified RunAsync() to set IsWatchMode based on the watch parameter
  • Refactored StartBackchannelAsync() to accept options and set up conditional disconnect handlers
  • Added new HandleBackchannelDisconnectInWatchModeAsync() method containing the reconnection logic
  • Implemented comprehensive logging at Information, Debug, Trace, Warning, and Error levels

Test coverage:

  • Added tests to verify IsWatchMode property is correctly set in both watch and non-watch scenarios
  • All 445 existing tests continue to pass with no regressions

Example Log Output

Successful reconnection in watch mode:

[INF] Backchannel disconnected in watch mode. Reason: RemotePartyTerminated. Attempting to reconnect...
[DBG] Reconnection attempt 1 of 30
[DBG] Reconnection attempt 2 of 30
[INF] Successfully reconnected to AppHost backchannel after 2 attempts.

Non-watch mode (existing behavior):

[INF] Backchannel disconnected. Exiting CLI.

Testing

  • ✅ All 445 tests in Aspire.Cli.Tests pass
  • ✅ Added 2 new tests for watch mode state tracking
  • ✅ Manual testing can be performed by enabling watch mode and making code changes to trigger apphost restart

Technical Notes

  • Uses Task.Run for the disconnect handler since EventHandler<JsonRpcDisconnectedEventArgs> is synchronous but reconnection logic is async
  • Creates a new IAppHostBackchannel instance for each reconnection attempt (required by interface design)
  • 30-second timeout provides adequate time for apphost restart on slower machines while remaining responsive
  • Process exit check prevents infinite reconnection attempts when apphost crashes

Fixes scenario where dotnet watch restarts cause CLI to exit unnecessarily.

Original prompt

The current implementation of the aspire run command in watch mode incorrectly shuts down the CLI when the backchannel disconnects. However, a backchannel disconnection in watch mode often occurs because the underlying dotnet watch process has restarted the apphost (e.g., due to a 'rude' change in apphost.cs). Instead of shutting down the CLI, we should refactor the logic in RunCommand to attempt to reconnect the backchannel when a disconnect is detected in watch mode. This change should:

  • Detect if aspire run is in watch mode.
  • On backchannel disconnection, if in watch mode, attempt to reconnect instead of exiting.
  • Ensure that non-watch mode behavior is unchanged (CLI should still exit on disconnect).
  • Add appropriate logging/messages for reconnect attempts, success, and failure.
  • Refactor the relevant logic into clear, testable methods or classes.
  • Add (or update) tests to verify this behavior, following the repo's xUnit/Microsoft.Testing.Platform conventions.

Do not update global.json or generated api/*.cs files. Use the latest C# features, maintain existing code formatting, and update only files relevant to RunCommand and watch mode backchannel handling.

This pull request was created as a result of the following prompt from Copilot chat.

The current implementation of the aspire run command in watch mode incorrectly shuts down the CLI when the backchannel disconnects. However, a backchannel disconnection in watch mode often occurs because the underlying dotnet watch process has restarted the apphost (e.g., due to a 'rude' change in apphost.cs). Instead of shutting down the CLI, we should refactor the logic in RunCommand to attempt to reconnect the backchannel when a disconnect is detected in watch mode. This change should:

  • Detect if aspire run is in watch mode.
  • On backchannel disconnection, if in watch mode, attempt to reconnect instead of exiting.
  • Ensure that non-watch mode behavior is unchanged (CLI should still exit on disconnect).
  • Add appropriate logging/messages for reconnect attempts, success, and failure.
  • Refactor the relevant logic into clear, testable methods or classes.
  • Add (or update) tests to verify this behavior, following the repo's xUnit/Microsoft.Testing.Platform conventions.

Do not update global.json or generated api/*.cs files. Use the latest C# features, maintain existing code formatting, and update only files relevant to RunCommand and watch mode backchannel handling.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

- Add IsWatchMode property to DotNetCliRunnerInvocationOptions
- Track watch mode state in RunAsync and pass to ExecuteAsync
- Refactor StartBackchannelAsync to support reconnection based on watch mode
- Add HandleBackchannelDisconnectInWatchModeAsync for reconnection logic
- In watch mode: attempt reconnection up to 30 times over 30 seconds
- In non-watch mode: maintain existing behavior (exit on disconnect)
- Add logging for reconnect attempts, success, and failure
- Add tests to verify IsWatchMode property is set correctly

Co-authored-by: mitchdenny <[email protected]>
@Copilot Copilot AI changed the title [WIP] Refactor aspire run to handle backchannel disconnection in watch mode Fix aspire run to reconnect backchannel in watch mode instead of exiting Oct 16, 2025
Copilot finished work on behalf of mitchdenny October 16, 2025 04:35
@Copilot Copilot AI requested a review from mitchdenny October 16, 2025 04:35
Copy link
Contributor

🚀 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 -- 12079

Or

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

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.

2 participants