Skip to content

fix: Prevent stale server recovery after Editor restarts#1166

Merged
hatayama merged 2 commits into
v3-betafrom
feature/hatayama/move-runtime-state-session-state
May 19, 2026
Merged

fix: Prevent stale server recovery after Editor restarts#1166
hatayama merged 2 commits into
v3-betafrom
feature/hatayama/move-runtime-state-session-state

Conversation

@hatayama
Copy link
Copy Markdown
Owner

Summary

  • Server recovery state is now scoped to the active Unity Editor session, so stale runtime flags do not survive Editor restarts.
  • In-flight upgrades still preserve the first domain reload recovery state from older settings JSON.

User Impact

  • Previously, transient server and reload flags were stored in UserSettings JSON, which could make a later Editor launch look like it was still recovering old runtime state.
  • Now those flags survive domain reloads within the same Editor session, but clear naturally when the Editor session ends.

Changes

  • Added a SessionState-backed editor session state service and repository for server, domain reload, and reconnect UI runtime flags.
  • Rewired server startup, recovery, domain reload detection, bridge server, and settings window paths to use session-scoped state instead of persistent editor settings.
  • Removed transient runtime fields from editor settings JSON and strip legacy keys during settings recovery.
  • Added a legacy JSON reader so the first reload after migration can preserve old in-flight recovery state without reviving stale running-only flags.

Verification

  • uloop compile: passed with 0 errors and 0 warnings
  • Focused EditMode tests: 38 passed
  • git diff --check: passed
  • codex-review v3-beta: clean, no accepted/actionable findings

Store reload and recovery flags in Unity SessionState so stale runtime state does not survive Editor restarts. Keep UserSettings JSON focused on persistent preferences, strip legacy transient keys, and preserve the first reload that crosses the migration.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 19, 2026

Review Change Stack

Warning

Rate limit exceeded

@hatayama has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 34 minutes and 59 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6eb7f4a6-088d-4642-bc89-40ac78f175da

📥 Commits

Reviewing files that changed from the base of the PR and between a7c6daa and 7176339.

📒 Files selected for processing (4)
  • Assets/Tests/Editor/DomainReloadDetectionServiceTests.cs
  • Packages/src/Editor/Infrastructure/Server/DomainReloadDetectionFileService.cs
  • Packages/src/Editor/Infrastructure/Settings/UnityCliLoopEditorLegacySessionStateReader.cs
  • Packages/src/Editor/Presentation/UnityCliLoopSettingsWindow.cs
📝 Walkthrough

Walkthrough

This PR migrates transient runtime state (server running, after-compile, domain reload, reconnecting, and UI-display flags) from persisted editor settings to per-editor-session storage. A new UnityCliLoopEditorSessionStateService backed by Unity's SessionState API replaces persistent settings for these flags, with legacy migration support for recovery data and cascading updates across server startup, recovery, domain-reload detection, bridge-server logic, and presentation layers.

Changes

Session State Refactoring: Move Transient Runtime Flags to Per-Editor-Session Storage

Layer / File(s) Summary
Session State Service Abstraction & Infrastructure
Packages/src/Editor/Domain/UnityCliLoopEditorSessionStateService.cs, Packages/src/Editor/Infrastructure/Settings/UnityCliLoopEditorSessionStateRepository.cs
New domain-layer IUnityCliLoopEditorSessionStatePort interface and UnityCliLoopEditorSessionStateService sealed class manage server running, after-compile, domain-reload, reconnecting, and UI-display flags; infrastructure-layer UnityCliLoopEditorSessionStateRepository implements the port using Unity's per-session SessionState API.
Test Helpers & Session State Fixtures
Assets/Tests/Editor/UnityCliLoopEditorSessionStateTestFactory.cs, Assets/Tests/Editor/UnityCliLoopEditorSessionStateRepositoryTests.cs
UnityCliLoopEditorSessionStateTestFactory provides service construction and snapshot capture/restore helpers; new test fixture validates repository default flags, persistence across recreation, and ClearAll() behavior.
Settings Data Cleanup & Legacy Migration Support
Packages/src/Editor/Domain/UnityCliLoopEditorSettingsData.cs, Packages/src/Editor/Domain/UnityCliLoopEditorSettingsService.cs, Packages/src/Editor/Infrastructure/Settings/UnityCliLoopEditorSettingsRepository.cs, Packages/src/Editor/Infrastructure/Settings/UnityCliLoopEditorLegacySessionStateReader.cs
Six transient runtime fields are removed from UnityCliLoopEditorSettingsData and corresponding methods from settings service port/implementation; legacy settings JSON keys are marked for cleanup during migration; new UnityCliLoopEditorLegacySessionStateReader recovers runtime flags from pre-refactoring settings files.
Domain Reload Detection Service Migration
Packages/src/Editor/Infrastructure/Server/DomainReloadDetectionFileService.cs
Refactored to depend on UnityCliLoopEditorSessionStateService, updating constructors and default wiring; StartDomainReload marks state through session service; CompleteDomainReload includes legacy-state migration and clears domain-reload flags via session service; ShouldShowReconnectingUI reads from session state.
Server Controller & Recovery Services Refactoring
Packages/src/Editor/Infrastructure/Server/UnityCliLoopServerController.cs, Packages/src/Editor/Application/SessionRecoveryService.cs, Packages/src/Editor/Application/UnityCliLoopServerStartupService.cs, Packages/src/Editor/Application/UseCases/DomainReloadRecoveryUseCase.cs
Cascading dependency injection: server controller, session recovery, server startup, and domain-reload recovery services now depend on UnityCliLoopEditorSessionStateService instead of settings service; all state operations (read/write/clear) switch from settings to session state for server lifecycle management.
Bridge Server & Domain Reload Registry Integration
Packages/src/Editor/Infrastructure/UnityCliLoopBridgeServer.cs
Removes UnityCliLoopEditorSettingsService dependency from factory and server; domain-reload checks in ServerLoopAsync and AcceptClientAsync switch from settings service to DomainReloadStateRegistry.IsDomainReloadInProgress().
Composition Root & Application Services Wiring
Packages/src/Editor/CompositionRoot/UnityCliLoopApplicationRegistration.cs, Packages/src/Editor/CompositionRoot/UnityCliLoopEditorBootstrapper.cs
UnityCliLoopApplicationRegistration.Register() creates session-state repository/service and wires it into domain-reload detection and server controller; UnityCliLoopApplicationServices constructor and new SessionStateService property expose the service; bootstrapper passes it to presentation startup.
Presentation Layer Integration
Packages/src/Editor/Presentation/PresentationEditorStartup.cs, Packages/src/Editor/Presentation/UnityCliLoopSettingsWindow.cs
Presentation startup accepts UnityCliLoopEditorSessionStateService alongside settings service; settings window registers and uses session-state service for post-compile reconnecting-UI and after-compile flag management.
Domain Reload Detection & Recovery Tests Refactoring
Assets/Tests/Editor/DomainReloadDetectionServiceTests.cs, Assets/Tests/Editor/DomainReloadRecoveryUseCaseTests.cs
Test fixtures refactored to create/clear session-state service and restore snapshots in setup/teardown; two new CompleteDomainReload migration tests validate that legacy recovery flags are migrated or stale-running-only flags are ignored; all state toggles and assertions switch to session state.
Server Controller & Startup Protection Tests Refactoring
Assets/Tests/Editor/UnityCliLoopServerControllerStartupLockTests.cs, Assets/Tests/Editor/UnityCliLoopServerStartupProtectionTests.cs
Session-state management added to setup/teardown; controller-service factory methods refactored from static to instance methods using shared _sessionStateService; editor-settings cloning/manual cleanup removed.
Settings Recovery & Package Removal Tests Updates
Assets/Tests/Editor/UnityCliLoopEditorSettingsRecoveryTests.cs, Assets/Tests/Editor/UnityCliLoopPackageRemovalSettingsResetterTests.cs
Settings recovery tests verify session-state separation and validate isServerRunning removal from persisted JSON; package-removal tests simplified to remove assertions about runtime state now scoped to session.
Static Analysis & Service Scan Updates
Assets/Tests/Editor/StaticFacadeStateGuardTests.cs
Extended to scan new UnityCliLoopEditorSessionStateService.cs for prohibited static-class declarations.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

  • hatayama/unity-cli-loop#1163: This PR implements the exact code-level migration described in the issue—adding IUnityCliLoopEditorSessionStatePort/UnityCliLoopEditorSessionStateService/Repository, removing transient flags from UnityCliLoopEditorSettingsData, and updating domain-reload, recovery, server-controller, bridge-server, and presentation code to use the new session-state service.

Possibly related PRs

  • hatayama/unity-cli-loop#1136: Both PRs modify DomainReloadDetectionFileService constructor wiring and StartDomainReload/CompleteDomainReload/rollback/UI-visibility logic, so the main PR's session-state refactor is directly tied to that PR's readiness-state and domain-reload recovery changes.
  • hatayama/unity-cli-loop#1079: Both PRs refactor the same domain-reload test suite (DomainReloadDetectionServiceTests.cs and DomainReloadRecoveryUseCaseTests.cs) by changing injected dependencies—main PR switches to session-state services while the referenced PR updates settings dependency wiring.
  • hatayama/unity-cli-loop#1150: Both PRs update DomainReloadRecoveryUseCase and its tests to change server-recovery logic wiring—main PR switches "was running" state source to session-state, while the referenced PR changes shutdown path preference and assertions.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.05% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: Prevent stale server recovery after Editor restarts' is clear, specific, and directly reflects the main change of scoping server recovery state to the active Editor session.
Description check ✅ Passed The description is well-related to the changeset. It explains the summary, user impact, specific changes made, and verification steps that align with the SessionState-backed service migration shown in the raw summary.
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
  • Commit unit tests in branch feature/hatayama/move-runtime-state-session-state

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.

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.

🧹 Nitpick comments (2)
Packages/src/Editor/Domain/UnityCliLoopEditorSessionStateService.cs (1)

96-109: ⚡ Quick win

Make MarkDomainReloadStarted(false) explicitly normalize recovery/UI flags.

Line 99 returns early, so previous isAfterCompile/isReconnecting/UI flags remain untouched. That can preserve stale recovery intent across cycles in the same Editor session. Consider clearing those flags in the !serverIsRunning path to make transition outcomes deterministic.

♻️ Proposed adjustment
 public void MarkDomainReloadStarted(bool serverIsRunning)
 {
     SetIsDomainReloadInProgress(true);
     if (!serverIsRunning)
     {
+        SetIsAfterCompile(false);
+        SetIsReconnecting(false);
+        SetShowReconnectingUI(false);
+        SetShowPostCompileReconnectingUI(false);
         return;
     }

     SetIsServerRunning(true);
     SetIsAfterCompile(true);
🤖 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 `@Packages/src/Editor/Domain/UnityCliLoopEditorSessionStateService.cs` around
lines 96 - 109, MarkDomainReloadStarted currently returns early when
serverIsRunning is false which leaves previous recovery/UI flags stale; update
the !serverIsRunning branch in MarkDomainReloadStarted to explicitly normalize
state by calling SetIsServerRunning(false), SetIsAfterCompile(false),
SetIsReconnecting(false), SetShowReconnectingUI(false) and
SetShowPostCompileReconnectingUI(false) before returning so the editor session
flags are deterministic.
Assets/Tests/Editor/UnityCliLoopEditorSessionStateRepositoryTests.cs (1)

42-57: ⚡ Quick win

Add a regression test for MarkDomainReloadStarted(serverIsRunning: false).

Current coverage only exercises the true branch. A false-branch test that pre-seeds reconnect/recovery flags helps catch stale-flag regressions early.

🧪 Suggested test case
 [Test]
 public void GetFlags_WhenServiceAndRepositoryAreRecreated_ReadsExistingSessionValues()
 {
@@
 }
+
+[Test]
+public void MarkDomainReloadStarted_WhenServerIsNotRunning_DoesNotLeaveRecoveryFlagsEnabled()
+{
+    _sessionStateService.SetIsAfterCompile(true);
+    _sessionStateService.SetIsReconnecting(true);
+    _sessionStateService.SetShowReconnectingUI(true);
+    _sessionStateService.SetShowPostCompileReconnectingUI(true);
+
+    _sessionStateService.MarkDomainReloadStarted(serverIsRunning: false);
+
+    Assert.That(_sessionStateService.GetIsDomainReloadInProgress(), Is.True);
+    Assert.That(_sessionStateService.GetIsAfterCompile(), Is.False);
+    Assert.That(_sessionStateService.GetIsReconnecting(), Is.False);
+    Assert.That(_sessionStateService.GetShowReconnectingUI(), Is.False);
+    Assert.That(_sessionStateService.GetShowPostCompileReconnectingUI(), Is.False);
+}
🤖 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 `@Assets/Tests/Editor/UnityCliLoopEditorSessionStateRepositoryTests.cs` around
lines 42 - 57, Add a new unit test alongside
GetFlags_WhenServiceAndRepositoryAreRecreated_ReadsExistingSessionValues that
calls _sessionStateService.MarkDomainReloadStarted(serverIsRunning: false)
(instead of true), pre-seeds any reconnect/recovery flags to true via the
existing test factory/state setup, recreates the service with
UnityCliLoopEditorSessionStateTestFactory.CreateService(), and asserts the
recreated UnityCliLoopEditorSessionStateService returns the expected false
values from GetIsServerRunning(), GetIsAfterCompile(),
GetIsDomainReloadInProgress(), GetIsReconnecting(), GetShowReconnectingUI(), and
GetShowPostCompileReconnectingUI() so the false branch and stale-flag
regressions are covered.
🤖 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.

Nitpick comments:
In `@Assets/Tests/Editor/UnityCliLoopEditorSessionStateRepositoryTests.cs`:
- Around line 42-57: Add a new unit test alongside
GetFlags_WhenServiceAndRepositoryAreRecreated_ReadsExistingSessionValues that
calls _sessionStateService.MarkDomainReloadStarted(serverIsRunning: false)
(instead of true), pre-seeds any reconnect/recovery flags to true via the
existing test factory/state setup, recreates the service with
UnityCliLoopEditorSessionStateTestFactory.CreateService(), and asserts the
recreated UnityCliLoopEditorSessionStateService returns the expected false
values from GetIsServerRunning(), GetIsAfterCompile(),
GetIsDomainReloadInProgress(), GetIsReconnecting(), GetShowReconnectingUI(), and
GetShowPostCompileReconnectingUI() so the false branch and stale-flag
regressions are covered.

In `@Packages/src/Editor/Domain/UnityCliLoopEditorSessionStateService.cs`:
- Around line 96-109: MarkDomainReloadStarted currently returns early when
serverIsRunning is false which leaves previous recovery/UI flags stale; update
the !serverIsRunning branch in MarkDomainReloadStarted to explicitly normalize
state by calling SetIsServerRunning(false), SetIsAfterCompile(false),
SetIsReconnecting(false), SetShowReconnectingUI(false) and
SetShowPostCompileReconnectingUI(false) before returning so the editor session
flags are deterministic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ffea0240-d1f6-473b-b2bc-840e0425a0cf

📥 Commits

Reviewing files that changed from the base of the PR and between c5a583b and a7c6daa.

⛔ Files ignored due to path filters (5)
  • Assets/Tests/Editor/UnityCliLoopEditorSessionStateRepositoryTests.cs.meta is excluded by none and included by none
  • Assets/Tests/Editor/UnityCliLoopEditorSessionStateTestFactory.cs.meta is excluded by none and included by none
  • Packages/src/Editor/Domain/UnityCliLoopEditorSessionStateService.cs.meta is excluded by none and included by none
  • Packages/src/Editor/Infrastructure/Settings/UnityCliLoopEditorLegacySessionStateReader.cs.meta is excluded by none and included by none
  • Packages/src/Editor/Infrastructure/Settings/UnityCliLoopEditorSessionStateRepository.cs.meta is excluded by none and included by none
📒 Files selected for processing (25)
  • Assets/Tests/Editor/DomainReloadDetectionServiceTests.cs
  • Assets/Tests/Editor/DomainReloadRecoveryUseCaseTests.cs
  • Assets/Tests/Editor/StaticFacadeStateGuardTests.cs
  • Assets/Tests/Editor/UnityCliLoopEditorSessionStateRepositoryTests.cs
  • Assets/Tests/Editor/UnityCliLoopEditorSessionStateTestFactory.cs
  • Assets/Tests/Editor/UnityCliLoopEditorSettingsRecoveryTests.cs
  • Assets/Tests/Editor/UnityCliLoopPackageRemovalSettingsResetterTests.cs
  • Assets/Tests/Editor/UnityCliLoopServerControllerStartupLockTests.cs
  • Assets/Tests/Editor/UnityCliLoopServerStartupProtectionTests.cs
  • Packages/src/Editor/Application/SessionRecoveryService.cs
  • Packages/src/Editor/Application/UnityCliLoopServerStartupService.cs
  • Packages/src/Editor/Application/UseCases/DomainReloadRecoveryUseCase.cs
  • Packages/src/Editor/CompositionRoot/UnityCliLoopApplicationRegistration.cs
  • Packages/src/Editor/CompositionRoot/UnityCliLoopEditorBootstrapper.cs
  • Packages/src/Editor/Domain/UnityCliLoopEditorSessionStateService.cs
  • Packages/src/Editor/Domain/UnityCliLoopEditorSettingsData.cs
  • Packages/src/Editor/Domain/UnityCliLoopEditorSettingsService.cs
  • Packages/src/Editor/Infrastructure/Server/DomainReloadDetectionFileService.cs
  • Packages/src/Editor/Infrastructure/Server/UnityCliLoopServerController.cs
  • Packages/src/Editor/Infrastructure/Settings/UnityCliLoopEditorLegacySessionStateReader.cs
  • Packages/src/Editor/Infrastructure/Settings/UnityCliLoopEditorSessionStateRepository.cs
  • Packages/src/Editor/Infrastructure/Settings/UnityCliLoopEditorSettingsRepository.cs
  • Packages/src/Editor/Infrastructure/UnityCliLoopBridgeServer.cs
  • Packages/src/Editor/Presentation/PresentationEditorStartup.cs
  • Packages/src/Editor/Presentation/UnityCliLoopSettingsWindow.cs
💤 Files with no reviewable changes (2)
  • Packages/src/Editor/Domain/UnityCliLoopEditorSettingsService.cs
  • Packages/src/Editor/Domain/UnityCliLoopEditorSettingsData.cs

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 30 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread Packages/src/Editor/Presentation/UnityCliLoopSettingsWindow.cs Outdated
Remove legacy JSON recovery flags immediately after applying them to SessionState so upgrade migration cannot reapply stale reload state on later domain reloads. Also align the newly added settings-window session registration with the existing Debug.Assert contract.
@hatayama hatayama merged commit 5b7835d into v3-beta May 19, 2026
12 checks passed
@hatayama hatayama deleted the feature/hatayama/move-runtime-state-session-state branch May 19, 2026 01:18
@github-actions github-actions Bot mentioned this pull request May 19, 2026
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