diff --git a/apps/expert/lib/expert/engine_node.ex b/apps/expert/lib/expert/engine_node.ex index c948d21e..e691f29f 100644 --- a/apps/expert/lib/expert/engine_node.ex +++ b/apps/expert/lib/expert/engine_node.ex @@ -31,10 +31,25 @@ defmodule Expert.EngineNode do this_node = inspect(Node.self()) dist_port = Expert.EPMD.dist_port() + # Detect test env by checking if manager node name (see test_helper.exs) + is_test? = Node.self() |> to_string() |> String.starts_with?("expert-testing-") + + # In release, use full epmdless config. + # In test, skip -erl_epmd_port and -dist_listen false b/c: + # - Manager uses EPMD (can't load Expert.EPMD before Elixir runtime) + # - Project needs to query EPMD on default port (4369) to find manager + # - :global registry needs bidirectional communication + erl_flags = + if is_test? do + "-start_epmd false" + else + "-start_epmd false -erl_epmd_port #{dist_port} -dist_listen false" + end + args = [ "--erl", - "-start_epmd false -erl_epmd_port #{dist_port} -dist_listen false", + erl_flags, "--name", Project.node_name(state.project), "--cookie", diff --git a/apps/expert/test/test_helper.exs b/apps/expert/test/test_helper.exs index 15d06e94..674edb0d 100644 --- a/apps/expert/test/test_helper.exs +++ b/apps/expert/test/test_helper.exs @@ -1,11 +1,31 @@ Application.ensure_all_started(:snowflake) Application.ensure_all_started(:refactorex) + +# Start EPMD for the test manager node. +# We can't use Expert.EPMD here because the kernel needs epmd_module before +# Elixir loads. In releases, Elixir is in the boot sequence. In mix test, it's not. +# Compromise: manager uses EPMD, project nodes are epmdless (see engine_node.ex). {"", 0} = System.cmd("epmd", ~w(-daemon)) -random_number = :rand.uniform(500) with :nonode@nohost <- Node.self() do + random_number = :rand.uniform(500) + {:ok, _pid} = - :net_kernel.start(:"testing-#{random_number}@127.0.0.1", %{name_domain: :longnames}) + :net_kernel.start(:"expert-testing-#{random_number}@127.0.0.1", %{name_domain: :longnames}) +end + +# Query our distribution port and store it in persistent_term +# This enables epmdless configuration for project nodes spawned during tests +node_name = + Node.self() + |> to_string() + |> String.split("@") + |> hd() + |> String.to_charlist() + +case :erl_epmd.port_please(node_name, ~c"127.0.0.1") do + {:port, port, _version} -> :persistent_term.put(:expert_dist_port, port) + _error -> :ok end Engine.Module.Loader.start_link(nil)