Skip to content

Handle Unity editor offline reconnects#1183

Open
liuzqk wants to merge 2 commits into
CoplayDev:betafrom
liuzqk:fix/editor-lifecycle-recovery
Open

Handle Unity editor offline reconnects#1183
liuzqk wants to merge 2 commits into
CoplayDev:betafrom
liuzqk:fix/editor-lifecycle-recovery

Conversation

@liuzqk
Copy link
Copy Markdown

@liuzqk liuzqk commented May 31, 2026

Summary

Handle the common window where the Unity Editor is closed or still starting while MCP tools are called.

  • detect editor-offline connection failures before dispatching tool commands
  • retry connection acquisition briefly to cover editor startup and bridge registration races
  • return a structured editor_offline response with hint=retry instead of an unhandled connection failure
  • add focused regression coverage for offline, reconnect, and non-offline error behavior

Why

When the Editor is closed or not ready, agents currently see transport failures and often retry the wrong layer. A retryable MCP response gives clients a clear signal to back off and try again after Unity is ready.

Validation

  • uv run --extra dev python -m pytest tests/test_editor_lifecycle_recovery.py tests/integration/test_domain_reload_resilience.py -q
  • git diff --check

Summary by CodeRabbit

  • New Features

    • Added editor-offline detection with automatic reconnection attempts within a configurable maximum wait time.
    • Returns structured offline responses with retry guidance to help clients handle editor unavailability gracefully.
    • Retries until the editor returns and refreshes discovery during the reconnect window.
  • Documentation

    • Added Editor Lifecycle Recovery specification detailing offline response behavior and reconnection handling.
  • Tests

    • Added tests covering offline detection, structured offline responses, retry behavior, and discovery refresh during reconnect.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 31, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 11ce327c-1e33-4339-990d-47df6e8acd97

📥 Commits

Reviewing files that changed from the base of the PR and between 2f50043 and 7b7231d.

📒 Files selected for processing (2)
  • Server/src/transport/legacy/unity_connection.py
  • Server/tests/test_editor_lifecycle_recovery.py

📝 Walkthrough

Walkthrough

This PR adds editor-offline detection and bounded reconnect waiting to the legacy Unity transport: connection acquisition can be retried (with optional discovery cache bypass) within a configurable window, and when offline it returns a structured editor_offline MCPResponse with retry metadata.

Changes

Editor Lifecycle Recovery

Layer / File(s) Summary
Editor-offline detection, force-refresh plumbing, and spec
Server/src/transport/legacy/unity_connection.py, docs/plans/2026-05-31-editor-lifecycle-recovery-spec.md
Adds _is_editor_offline_error, _editor_offline_response, _get_connection_with_editor_reconnect (polling get_unity_connection(..., force_refresh=...) within a clamped env timeout) and extends UnityConnectionPool.get_connection / get_unity_connection with keyword-only force_refresh. Includes a new design spec.
Integration with send_command_with_retry
Server/src/transport/legacy/unity_connection.py
send_command_with_retry now obtains the connection via _get_connection_with_editor_reconnect and immediately returns the offline MCPResponse when applicable; otherwise continues existing reload-aware retry/send flow.
Test coverage for editor offline scenarios
Server/tests/test_editor_lifecycle_recovery.py
Adds four tests covering structured offline response when no editor, retry-until-available behavior (mocking time/sleep), discovery/cache-refresh when editor returns, and parameterized detection of offline-like ConnectionError messages.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • CoplayDev/unity-mcp#595: Also updates connection/retry-loop logic in send_command_with_retry within the same module, handling bounded retry behavior with different termination reasons.
  • CoplayDev/unity-mcp#510: Related editor recovery improvements in the same transport module, adding reason-aware connection retry behavior for Unity reload/session scenarios.
  • CoplayDev/unity-mcp#796: Companion recovery mechanism in the same file that adds stale-socket detection and cleanup before sending, complementing this PR's offline-reconnect logic.

Poem

🐰 I wait by the socket, nose twitching in time,
I sniff for the editor's heartbeat and rhyme,
Retry in soft hops, a patient little chore,
Until the port opens and we chatter once more,
Then hop away happy — connected, restored.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description covers the why, what, and validation details, but does not follow the provided template structure with Type of Change, Compatibility testing, and other required sections. Restructure the description to match the template: add Type of Change checkboxes, Compatibility section with Unity versions and package source, Testing checkboxes with specific test runs, and Related Issues/Documentation sections.
Docstring Coverage ⚠️ Warning Docstring coverage is 30.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: handling reconnect behavior when the Unity editor is offline.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@liuzqk liuzqk force-pushed the fix/editor-lifecycle-recovery branch from b7da729 to 2f50043 Compare May 31, 2026 06:22
@liuzqk liuzqk marked this pull request as ready for review May 31, 2026 06:53
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
Server/tests/test_editor_lifecycle_recovery.py (1)

26-66: 💤 Low value

Coverage note: this test patches get_unity_connection directly, so it bypasses discover_all_instances' 5s cache. It validates the retry mechanics but won't catch the no-instances reconnect gap flagged in unity_connection.py. Worth adding a case that exercises the real discovery path once that gap is addressed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Server/tests/test_editor_lifecycle_recovery.py` around lines 26 - 66, Add a
new test that exercises the real discovery path instead of patching
get_unity_connection directly: simulate discover_all_instances returning an
empty list initially and then returning the instance after the discovery cache
expires so send_command_with_retry goes through the discovery -> reconnect gap;
patch transport.legacy.unity_connection.discover_all_instances,
transport.legacy.unity_connection.time.monotonic and time.sleep to control
timing, set UNITY_MCP_EDITOR_RECONNECT_MAX_WAIT_S via monkeypatch, and assert
send_command_with_retry (the send_command_with_retry function) eventually calls
get_unity_connection and succeeds, verifying retries across the discovery cache
gap.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Server/src/transport/legacy/unity_connection.py`:
- Around line 824-862: The reconnect loop in
_get_connection_with_editor_reconnect retries get_unity_connection() but
discovery is cached, so add a force-refresh plumbing: extend
get_unity_connection(...)/UnityConnectionPool.get_connection(...) to accept a
force_refresh: bool flag and pass it to
discover_all_instances(force_refresh=True) inside UnityConnectionPool, and then
modify _get_connection_with_editor_reconnect to set force_refresh=True for
subsequent reconnect attempts (e.g., when _resolve_instance_id raises the “No
Unity Editor instances found” error or after the first failed attempt) so
instance discovery is re-scanned within the
UNITY_MCP_EDITOR_RECONNECT_MAX_WAIT_S window.

---

Nitpick comments:
In `@Server/tests/test_editor_lifecycle_recovery.py`:
- Around line 26-66: Add a new test that exercises the real discovery path
instead of patching get_unity_connection directly: simulate
discover_all_instances returning an empty list initially and then returning the
instance after the discovery cache expires so send_command_with_retry goes
through the discovery -> reconnect gap; patch
transport.legacy.unity_connection.discover_all_instances,
transport.legacy.unity_connection.time.monotonic and time.sleep to control
timing, set UNITY_MCP_EDITOR_RECONNECT_MAX_WAIT_S via monkeypatch, and assert
send_command_with_retry (the send_command_with_retry function) eventually calls
get_unity_connection and succeeds, verifying retries across the discovery cache
gap.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 03fa78e4-798c-4909-9591-0477d80e498b

📥 Commits

Reviewing files that changed from the base of the PR and between 2d2bdc5 and 2f50043.

📒 Files selected for processing (3)
  • Server/src/transport/legacy/unity_connection.py
  • Server/tests/test_editor_lifecycle_recovery.py
  • docs/plans/2026-05-31-editor-lifecycle-recovery-spec.md

Comment thread Server/src/transport/legacy/unity_connection.py
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.

1 participant