Skip to content

chore: Inject dispatcher runtime dependencies - #1479

Merged
hatayama merged 1 commit into
v3-betafrom
refactor/dispatcher-deps
Jul 4, 2026
Merged

hatayama merged 1 commit into
v3-betafrom
refactor/dispatcher-deps

Conversation

@hatayama

@hatayama hatayama commented Jul 4, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Replace dispatcher launch test seam package variables with explicit launch dependencies.
  • Replace dispatcher runtime seam package variables with dispatcherRunDeps.
  • Update tests to pass per-test dependencies instead of mutating package state.

Verification

  • go test ./internal/dispatcher
  • scripts/check-go-cli.sh

Review in cubic

@coderabbitai

coderabbitai Bot commented Jul 4, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The dispatcher and launch subsystems are refactored to use explicit dependency-injection structs (dispatcherRunDeps, launchDeps) instead of package-level global function variables. Core entrypoints gain WithDeps variants threading these structs through launch handling, real-CLI execution, and self-update freshness enforcement. Tests are updated accordingly.

Changes

Dispatcher dependency injection refactor

Layer / File(s) Summary
launchDeps container
cli/dispatcher/internal/dispatcher/launch_deps.go
New launchDeps struct and defaultLaunchDeps() wire process/focus/kill/wait/resolve/probe functions to clicore and local implementations.
Launch flow rewired
cli/dispatcher/internal/dispatcher/launch.go
Launch handling, existing-process detection/handling, readiness waiting, and exit polling switch to WithDeps variants driven by injected launchDeps; the old global var block is removed.
Focus logging and readiness classification
cli/dispatcher/internal/dispatcher/launch_focus_log.go, cli/dispatcher/internal/dispatcher/launch_startup_timeout_error.go
Focus logging and readiness-timeout wrapping now call deps.focusUnityProcess / deps.waitForToolReadiness instead of direct global helpers.
Launch tests
cli/dispatcher/internal/dispatcher/launch_test.go
Tests build defaultLaunchDeps(), stub specific fields, and call runLaunchWithDeps/waitForLaunchReadinessWithDeps/waitForUnityProcessExitWithDeps in place of global monkey-patching.
dispatcherRunDeps and RunDispatcher wiring
cli/dispatcher/internal/dispatcher/run_dispatcher.go, cli/dispatcher/internal/dispatcher/dispatcher_process.go
New dispatcherRunDeps/defaultDispatcherRunDeps() route RunDispatcher, process command dispatch, and pre-connection handling through injected deps.
Freshness/self-update enforcement
cli/dispatcher/internal/dispatcher/run_dispatcher.go
enforceDispatcherFreshness, dispatcherSelfUpdateDue, and markDispatcherSelfUpdateChecked become WithDeps variants using injected time and update runner.
Dispatcher tests
cli/dispatcher/internal/dispatcher/dispatcher_test.go
Tests configure deps via defaultDispatcherRunDeps()/stubDispatcherUpdateHooks and call runDispatcherWithDeps/enforceDispatcherFreshnessWithDeps instead of mutating globals.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Dispatcher
  participant tryHandleLaunchRequestWithDeps
  participant runLaunchWithDeps
  participant launchDeps

  Dispatcher->>tryHandleLaunchRequestWithDeps: launch request + deps
  tryHandleLaunchRequestWithDeps->>runLaunchWithDeps: run(deps)
  runLaunchWithDeps->>launchDeps: findRunningUnityProcess
  runLaunchWithDeps->>launchDeps: waitForToolReadiness / killUnityProcess / resolveUnityExecutablePath
  launchDeps-->>runLaunchWithDeps: readiness/process result
  runLaunchWithDeps-->>tryHandleLaunchRequestWithDeps: exit code
Loading

Possibly related PRs

  • hatayama/unity-cli-loop#1434: Both PRs modify the dispatcher freshness/self-update logic around enforceDispatcherFreshness and its checked-marker persistence.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: injecting dispatcher runtime dependencies.
Description check ✅ Passed The description matches the changeset by describing the dependency injection refactor and test updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/dispatcher-deps

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.

@hatayama
hatayama force-pushed the refactor/dispatcher-deps branch from 4bd6787 to 00c342c Compare July 4, 2026 00:29

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found and verified against the latest diff

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="cli/dispatcher/internal/dispatcher/launch_startup_timeout_error.go">

<violation number="1" location="cli/dispatcher/internal/dispatcher/launch_startup_timeout_error.go:27">
P3: Test error message still references the old function name `waitForLaunchReadiness`. Update it to `waitForLaunchReadinessWithDeps` so failure messages accurately identify the failing function.</violation>
</file>

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

Re-trigger cubic

Comment thread cli/dispatcher/internal/dispatcher/launch_startup_timeout_error.go
@hatayama
hatayama force-pushed the refactor/dispatcher-deps branch from 00c342c to 6b0b57e Compare July 4, 2026 00:33

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
cli/dispatcher/internal/dispatcher/launch_deps.go (1)

21-32: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

waitForUnityProcessExit default silently discards a caller's custom deps.

defaultLaunchDeps().waitForUnityProcessExit is wired to the package-level waitForUnityProcessExit (launch.go Line 319-321), which itself calls waitForUnityProcessExitWithDeps(..., defaultLaunchDeps()) — rebuilding a brand-new default deps rather than reusing the deps the caller constructed. Today this is harmless since defaultLaunchDeps() is the only production constructor, but it is a DI trap: if a future caller builds a partially-customized launchDeps (e.g., overriding only findRunningUnityProcess) without also overriding waitForUnityProcessExit, that override would silently not apply during exit-wait polling, since the default waitForUnityProcessExit field ignores the containing struct entirely. Tests already work around this by explicitly overriding waitForUnityProcessExit whenever they stub findRunningUnityProcess for exit-wait scenarios (e.g. launch_test.go TestRunLaunchRestartWritesProcessTransitionResponse), which masks the issue but doesn't fix the underlying inconsistency.

Consider having the default field close over the deps identity it belongs to isn't trivially possible in Go without extra indirection (chicken/egg), so a cleaner design might be to only keep waitForUnityProcessExitWithDeps as the canonical implementation and drop the deps-free waitForUnityProcessExit package function (if unused elsewhere), or clearly document that overriding findRunningUnityProcess alone does not affect exit-wait behavior unless waitForUnityProcessExit is also overridden.

🤖 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 `@cli/dispatcher/internal/dispatcher/launch_deps.go` around lines 21 - 32,
`defaultLaunchDeps` wires `waitForUnityProcessExit` to a deps-free wrapper that
rebuilds `defaultLaunchDeps()`, so any caller-provided overrides in `launchDeps`
are ignored during exit waiting. Update the `waitForUnityProcessExit` path in
`launch.go` / `launchDeps` so it uses the same dependency set passed into the
launch flow, or remove the wrapper and make `waitForUnityProcessExitWithDeps`
the single canonical implementation. Make sure `findRunningUnityProcess` and
other overridden fields still apply when `waitForUnityProcessExit` is invoked.
cli/dispatcher/internal/dispatcher/dispatcher_test.go (1)

400-413: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Downstream of the dispatcherReadInstalledVersion global noted in run_dispatcher.go.

This helper still saves/restores a package-level dispatcherReadInstalledVersion var (lines 407-411) while everything else (runUpdate, etc.) is now injected via deps. See the companion comment on run_dispatcher.go (lines 190-236) for the suggested fix of adding this to dispatcherRunDeps instead.

🤖 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 `@cli/dispatcher/internal/dispatcher/dispatcher_test.go` around lines 400 -
413, Move the installed-version reader off the package-level
dispatcherReadInstalledVersion global and into dispatcherRunDeps so
stubDispatcherUpdateHooks can inject it like runUpdate and the other deps.
Update the dispatcherRunDeps setup/defaultDispatcherRunDeps and the
run_dispatcher.go call sites to read the installed version from deps instead of
the global, then simplify stubDispatcherUpdateHooks to override only the
dependency and restore state through the deps wiring.
cli/dispatcher/internal/dispatcher/run_dispatcher.go (1)

190-236: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Thread dispatcherReadInstalledVersion through dispatcherRunDeps

dispatcherReadInstalledVersion is still a package-level mutable seam, and the tests patch it directly. Consider adding an installedVersion func(context.Context) (string, error) field to dispatcherRunDeps and plumbing it through dispatcherInstalledVersionOrEmpty so this dependency follows the same pattern as now, runRealCLI, and runUpdate.

🤖 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 `@cli/dispatcher/internal/dispatcher/run_dispatcher.go` around lines 190 - 236,
Thread the installed-version lookup through dispatcherRunDeps instead of relying
on the package-level dispatcherReadInstalledVersion seam. Add an
installedVersion func(context.Context) (string, error) field to
dispatcherRunDeps, wire it into defaultDispatcherRunDeps and
dispatcherInstalledVersionOrEmpty, and update enforceDispatcherFreshnessWithDeps
to use the injected dependency so tests can override it consistently with now,
runRealCLI, and runUpdate.
🤖 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 `@cli/dispatcher/internal/dispatcher/dispatcher_test.go`:
- Around line 400-413: Move the installed-version reader off the package-level
dispatcherReadInstalledVersion global and into dispatcherRunDeps so
stubDispatcherUpdateHooks can inject it like runUpdate and the other deps.
Update the dispatcherRunDeps setup/defaultDispatcherRunDeps and the
run_dispatcher.go call sites to read the installed version from deps instead of
the global, then simplify stubDispatcherUpdateHooks to override only the
dependency and restore state through the deps wiring.

In `@cli/dispatcher/internal/dispatcher/launch_deps.go`:
- Around line 21-32: `defaultLaunchDeps` wires `waitForUnityProcessExit` to a
deps-free wrapper that rebuilds `defaultLaunchDeps()`, so any caller-provided
overrides in `launchDeps` are ignored during exit waiting. Update the
`waitForUnityProcessExit` path in `launch.go` / `launchDeps` so it uses the same
dependency set passed into the launch flow, or remove the wrapper and make
`waitForUnityProcessExitWithDeps` the single canonical implementation. Make sure
`findRunningUnityProcess` and other overridden fields still apply when
`waitForUnityProcessExit` is invoked.

In `@cli/dispatcher/internal/dispatcher/run_dispatcher.go`:
- Around line 190-236: Thread the installed-version lookup through
dispatcherRunDeps instead of relying on the package-level
dispatcherReadInstalledVersion seam. Add an installedVersion
func(context.Context) (string, error) field to dispatcherRunDeps, wire it into
defaultDispatcherRunDeps and dispatcherInstalledVersionOrEmpty, and update
enforceDispatcherFreshnessWithDeps to use the injected dependency so tests can
override it consistently with now, runRealCLI, and runUpdate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c13d0841-a899-41ca-b4c5-ae3fb97bf331

📥 Commits

Reviewing files that changed from the base of the PR and between 175e731 and 6b0b57e.

📒 Files selected for processing (8)
  • cli/dispatcher/internal/dispatcher/dispatcher_process.go
  • cli/dispatcher/internal/dispatcher/dispatcher_test.go
  • cli/dispatcher/internal/dispatcher/launch.go
  • cli/dispatcher/internal/dispatcher/launch_deps.go
  • cli/dispatcher/internal/dispatcher/launch_focus_log.go
  • cli/dispatcher/internal/dispatcher/launch_startup_timeout_error.go
  • cli/dispatcher/internal/dispatcher/launch_test.go
  • cli/dispatcher/internal/dispatcher/run_dispatcher.go

@hatayama
hatayama merged commit ae02120 into v3-beta Jul 4, 2026
9 checks passed
@hatayama
hatayama deleted the refactor/dispatcher-deps branch July 4, 2026 00:43
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