fix(deps): break :application_controller cycle with vfs at boot#5
Merged
Conversation
Mark :vfs as runtime: false so Mix does not auto-inject it into exgit's generated `applications` list. vfs depends on exgit in its own dev/test env, and when both libs are bundled in a downstream consumer the application edge from exgit -> vfs deadlocks :application_controller at boot. The integration is compile-time only — `defimpl VFS.Mountable, for: Exgit.Workspace` references vfs's protocol module during compilation; there is no vfs supervision tree to start. So runtime: false is not a workaround, it is an accurate description of the relationship, matching Phoenix's pattern with its optional templating adapters. Side effect: Dialyxir's default PLT closure follows `applications`, so vfs beams need an explicit `plt_add_apps: [:vfs]` to keep Workspace.VFS clean of spurious unknown_function warnings. Adds Exgit.BootWithVfsTest as a regression smoke test: boots both apps in the same VM with a 30s per-test timeout. If a future change reintroduces the cycle the test deadlocks and ExUnit surfaces it as a clear failure rather than a stuck CI run.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
runtime: falseto the:vfsdep so Mix does not auto-inject it into exgit's generatedapplicationslist.plt_add_apps: [:vfs]to the dialyzer config to keep vfs beams in the PLT afterruntime: falseremoves them from the default closure.Exgit.BootWithVfsTest— a regression smoke test that boots:exgitand:vfstogether in the same VM under a 30s per-test timeout.The bug
Bundling both
:exgitand:vfsinto the same release (e.g. a downstream agent app) deadlocked:application_controllerat boot.Mechanism:
:exgithad{:vfs, ..., optional: true}— Mix still adds optional deps as application edges.:application_controllerwalksapplicationsfor every loaded app. When it sees:vfslisted by:exgit, it tries to start:vfs.:vfs(in dev/test) depends on:exgitfor its own integration tests against exgit as a vfs storage backend.:application_controller→ deadlock.optional_applicationsonly tells the controller "it's OK if this app is absent" — it does not break the dependency edge when the app is present. Once both libs are in the same build, you wedge.The fix
runtime: falseon the:vfsdep is the load-bearing flag. It tells Mix "compile against this, but don't list it inapplications." That is exactly the relationship we want: exgit uses vfs's protocol module at compile time (fordefimpl VFS.Mountable, for: Exgit.Workspace) but does not depend on a vfs supervision tree at runtime. Same shape as Phoenix's optional templating adapters.Architecture invariant preserved (per
CLAUDE.md):Exgit.Workspaceis mountable.Verification
Locally on
darwin, Elixir 1.19, OTP 28:mix format --check-formattedmix compile --warnings-as-errorsMIX_ENV=dev mix credo --strictMIX_ENV=dev mix dialyzermix test --warnings-as-errorsmix test test/exgit/workspace_vfs_test.exs --include vfsExgit.Workspace)mix run -e 'Application.ensure_all_started(:exgit); Application.ensure_all_started(:vfs); IO.puts("ok")'ok(previously deadlocked)Inspected
_build/dev/lib/exgit/ebin/exgit.app:applicationsno longer containsvfsoptional_applicationsis[]Elixir.VFS.Mountable.Exgit.Workspace,Elixir.Exgit.Workspace.VFS) remain inmodules— exactly the intended compile-time-only integration shape.