diff --git a/apps/expert/lib/expert/engine_node.ex b/apps/expert/lib/expert/engine_node.ex index 2f5d42b5..0519b924 100644 --- a/apps/expert/lib/expert/engine_node.ex +++ b/apps/expert/lib/expert/engine_node.ex @@ -29,17 +29,21 @@ defmodule Expert.EngineNode do def start(%__MODULE__{} = state, paths, from) do this_node = inspect(Node.self()) + dist_port = Expert.EPMD.dist_port() - args = [ - "--name", - Project.node_name(state.project), - "--cookie", - state.cookie, - "--no-halt", - "-e", - "Node.connect(#{this_node})" - | path_append_arguments(paths) - ] + args = + [ + "--erl", + "-start_epmd false -erl_epmd_port #{dist_port} -dist_listen false", + "--name", + Project.node_name(state.project), + "--cookie", + state.cookie, + "--no-halt", + "-e", + "Node.connect(#{this_node}); IO.puts(\"ok\")" + | path_append_arguments(paths) + ] port = Expert.Port.open_elixir(state.project, args: args) @@ -110,7 +114,6 @@ defmodule Expert.EngineNode do use GenServer def start(project) do - :ok = ensure_epmd_started() start_net_kernel(project) node_name = Project.node_name(project) @@ -134,16 +137,6 @@ defmodule Expert.EngineNode do :rpc.call(node, Engine, :ensure_apps_started, []) end - defp ensure_epmd_started do - case System.cmd("epmd", ~w(-daemon)) do - {"", 0} -> - :ok - - _ -> - {:error, :epmd_failed} - end - end - if Mix.env() == :test do # In test environment, Expert depends on the Engine app, so we look for it # in the expert build path. @@ -278,7 +271,7 @@ defmodule Expert.EngineNode do @impl true def handle_call({:start, paths}, from, %State{} = state) do - :ok = :net_kernel.monitor_nodes(true, node_type: :visible) + :ok = :net_kernel.monitor_nodes(true, node_type: :all) Process.send_after(self(), :maybe_start_timeout, @start_timeout) state = State.start(state, paths, from) {:noreply, state} diff --git a/apps/expert/lib/expert/epmd.ex b/apps/expert/lib/expert/epmd.ex new file mode 100644 index 00000000..bff5030e --- /dev/null +++ b/apps/expert/lib/expert/epmd.ex @@ -0,0 +1,26 @@ +defmodule Expert.EPMD do + def dist_port do + :persistent_term.get(:expert_dist_port, nil) + end + + # EPMD callbacks + + def register_node(name, port), do: register_node(name, port, :inet) + + def register_node(name, port, family) do + :persistent_term.put(:expert_dist_port, port) + + # We don't care if EPMD is not running + case :erl_epmd.register_node(name, port, family) do + {:error, _} -> {:ok, -1} + {:ok, _} = ok -> ok + end + end + + defdelegate start_link(), to: :erl_epmd + defdelegate port_please(name, host), to: :erl_epmd + defdelegate port_please(name, host, timeout), to: :erl_epmd + defdelegate listen_port_please(name, host), to: :erl_epmd + defdelegate address_please(name, host, family), to: :erl_epmd + defdelegate names(host_name), to: :erl_epmd +end diff --git a/apps/expert/rel/remote.vm.args.eex b/apps/expert/rel/remote.vm.args.eex new file mode 100644 index 00000000..559a4767 --- /dev/null +++ b/apps/expert/rel/remote.vm.args.eex @@ -0,0 +1,12 @@ +## Customize flags given to the VM: https://www.erlang.org/doc/man/erl.html +## -mode/-name/-sname/-setcookie are configured via env vars, do not set them here + +## Increase number of concurrent ports/sockets +##+Q 65536 + +## Tweak GC to run more often +##-env ERL_FULLSWEEP_AFTER 10 + +## Enable deployment without epmd +## (requires changing both vm.args and remote.vm.args) +-start_epmd false -dist_listen false diff --git a/apps/expert/rel/vm.args.eex b/apps/expert/rel/vm.args.eex new file mode 100644 index 00000000..c31a4837 --- /dev/null +++ b/apps/expert/rel/vm.args.eex @@ -0,0 +1,12 @@ +## Customize flags given to the VM: https://www.erlang.org/doc/man/erl.html +## -mode/-name/-sname/-setcookie are configured via env vars, do not set them here + +## Increase number of concurrent ports/sockets +##+Q 65536 + +## Tweak GC to run more often +##-env ERL_FULLSWEEP_AFTER 10 + +## Enable deployment without epmd +## (requires changing both vm.args and remote.vm.args) +-start_epmd false -epmd_module Elixir.XPExpert.EPMD