Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/engine/test/test_helper.exs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
Application.ensure_all_started(:snowflake)
Application.ensure_all_started(:refactorex)
{"", 0} = System.cmd("epmd", ~w(-daemon))

random_number = :rand.uniform(500)

with :nonode@nohost <- Node.self() do
{:ok, _pid} =
:net_kernel.start(:"testing-#{random_number}@127.0.0.1", %{name_domain: :longnames})
Node.start(:"expert-manager-testing-#{random_number}@127.0.0.1", :longnames)
end

Engine.Module.Loader.start_link(nil)
Expand Down
22 changes: 22 additions & 0 deletions apps/expert/lib/expert/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ defmodule Expert.Application do
System.halt(1)
end

ensure_epmd_module!()

children = [
{Forge.NodePortMapper, []},
document_store_child_spec(),
{DynamicSupervisor, Expert.Project.DynamicSupervisor.options()},
{DynamicSupervisor, name: Expert.DynamicSupervisor},
Expand All @@ -89,4 +92,23 @@ defmodule Expert.Application do
def document_store_child_spec do
{Document.Store, derive: [analysis: &Forge.Ast.analyze/1]}
end

def ensure_epmd_module! do
epmd_module = to_charlist(Forge.EPMD)

case :init.get_argument(:epmd_module) do
{:ok, [[^epmd_module]]} ->
:ok

_ ->
Application.put_env(:kernel, :epmd_module, Forge.EPMD, persistent: true)

# Note: this is a private API
if :net_kernel.epmd_module() != Forge.EPMD do
raise("""
you must set the environment variable ELIXIR_ERL_OPTIONS="-epmd_module #{Forge.EPMD}"
""")
end
end
end
end
67 changes: 38 additions & 29 deletions apps/expert/lib/expert/engine_node.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,39 @@ defmodule Expert.EngineNode do
@dialyzer {:nowarn_function, start: 3}

def start(%__MODULE__{} = state, paths, from) do
this_node = inspect(Node.self())

args = [
"--name",
Project.node_name(state.project),
"--cookie",
state.cookie,
"--no-halt",
"-e",
"Node.connect(#{this_node})"
| path_append_arguments(paths)
]

case Expert.Port.open_elixir(state.project, args: args) do
this_node = to_string(Node.self())
dist_port = Forge.EPMD.dist_port()

args =
[
"--erl",
"-start_epmd false -epmd_module #{Forge.EPMD}",
"--cookie",
state.cookie,
"--no-halt",
"-e",
# We manually start distribution here instead of using --sname/--name
# because those options are not really compatible with `-epmd_module`.
# Apparently, passing the --name/-sname options causes the Erlang VM
# to start distribution right away before the modules in the code path
# are loaded, and it will crash because Forge.EPMD doesn't exist yet.
# If we start distribution manually after all the code is loaded,
# everything works fine.
"""
{:ok, _} = Node.start(:"#{Project.node_name(state.project)}", :longnames)
#{Forge.NodePortMapper}.register()
IO.puts(\"ok\")
"""
| path_append_arguments(paths)
]

env =
[
{"EXPERT_PARENT_NODE", this_node},
{"EXPERT_PARENT_PORT", to_string(dist_port)}
]

case Expert.Port.open_elixir(state.project, args: args, env: env) do
{:error, :no_elixir, message} ->
GenLSP.error(Expert.get_lsp(), message)
Expert.terminate("Failed to find an elixir executable, shutting down", 1)
Expand All @@ -64,7 +83,7 @@ defmodule Expert.EngineNode do
end

def on_nodeup(%__MODULE__{} = state, node_name) do
if node_name == Project.node_name(state.project) do
if String.starts_with?(to_string(node_name), to_string(Project.node_name(state.project))) do
{pid, _ref} = state.started_by
Process.monitor(pid)
GenServer.reply(state.started_by, :ok)
Expand Down Expand Up @@ -117,7 +136,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)
Expand All @@ -134,23 +152,13 @@ defmodule Expert.EngineNode do

defp start_net_kernel(%Project{} = project) do
manager = Project.manager_node_name(project)
:net_kernel.start(manager, %{name_domain: :longnames})
Node.start(manager, :longnames)
end

defp ensure_apps_started(node) 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.
Expand Down Expand Up @@ -294,7 +302,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)

case State.start(state, paths, from) do
Expand Down Expand Up @@ -365,7 +373,8 @@ defmodule Expert.EngineNode do
end

@impl true
def handle_info({_port, {:data, _message}}, %State{} = state) do
def handle_info({_port, {:data, message}}, %State{} = state) do
Logger.debug("Node port message: #{to_string(message)}")
{:noreply, state}
end

Expand Down
2 changes: 1 addition & 1 deletion apps/expert/lib/expert/port.ex
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ defmodule Expert.Port do
opts
end

Port.open({:spawn_executable, launcher}, opts)
Port.open({:spawn_executable, launcher}, [:stderr_to_stdout | opts])
end

@doc """
Expand Down
13 changes: 13 additions & 0 deletions apps/expert/rel/remote.vm.args.eex
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## 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)
-epmd_module Elixir.XPForge.EPMD
Copy link
Member

Choose a reason for hiding this comment

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

Please double check this is indeed necessary. You may be fine using epmd for remote debugging (or maybe remote debugging is pointless).

-start_epmd false
12 changes: 12 additions & 0 deletions apps/expert/rel/vm.args.eex
Original file line number Diff line number Diff line change
@@ -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.XPForge.EPMD
2 changes: 2 additions & 0 deletions apps/expert/test/engine/build_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ defmodule Engine.BuildTest do
|> Project.workspace_path()
|> File.rm_rf()

{:ok, _} = start_supervised(Forge.NodePortMapper)
{:ok, _} = start_supervised({EngineSupervisor, project})
{:ok, _, _} = EngineNode.start(project)
EngineApi.register_listener(project, self(), [:all])
Expand Down Expand Up @@ -650,6 +651,7 @@ defmodule Engine.BuildTest do

describe ".exs files" do
setup do
start_supervised!({Forge.NodePortMapper, []})
start_supervised!(Engine.Dispatch)
start_supervised!(Engine.ModuleMappings)
start_supervised!(Build.CaptureServer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ defmodule Expert.Engine.CodeIntelligence.DefinitionTest do
end

setup_all do
{:ok, _} = start_supervised({Forge.NodePortMapper, []})
project = project(:navigations)
start_supervised!({Document.Store, derive: [analysis: &Forge.Ast.analyze/1]})
{:ok, _} = start_supervised({EngineSupervisor, project})
Expand Down
1 change: 1 addition & 0 deletions apps/expert/test/engine/engine_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ defmodule EngineTest do
import Forge.Test.Fixtures

def start_project(%Project{} = project) do
start_supervised!({Forge.NodePortMapper, []})
start_supervised!({Expert.EngineSupervisor, project})
assert {:ok, _, _} = EngineNode.start(project)
:ok
Expand Down
1 change: 1 addition & 0 deletions apps/expert/test/expert/engine_node_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ defmodule Expert.EngineNodeTest do

setup do
project = project()
start_supervised!({Forge.NodePortMapper, []})
start_supervised!({EngineSupervisor, project})
{:ok, %{project: project}}
end
Expand Down
1 change: 1 addition & 0 deletions apps/expert/test/expert/project/node_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ defmodule Expert.Project.NodeTest do
setup do
project = project()

{:ok, _} = start_supervised({Forge.NodePortMapper, []})
{:ok, _} = start_supervised({DynamicSupervisor, Expert.Project.DynamicSupervisor.options()})
{:ok, _} = start_supervised({Expert.Project.Supervisor, project})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ defmodule Expert.Provider.Handlers.CodeActionTest do
use ExUnit.Case, async: false

setup_all do
start_supervised!({Forge.NodePortMapper, []})
start_supervised!({Document.Store, derive: [analysis: &Forge.Ast.analyze/1]})
project = project(:navigations)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ defmodule Expert.Provider.Handlers.CodeLensTest do
use Patch

setup_all do
start_supervised!({Forge.NodePortMapper, []})
start_supervised(Document.Store)
project = project(:umbrella)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ defmodule Expert.Provider.Handlers.FormattingTest do
end

def with_real_project(%{project: project}) do
{:ok, _} = start_supervised({Forge.NodePortMapper, []})
{:ok, _} = start_supervised({Expert.EngineSupervisor, project})
{:ok, _, _} = EngineNode.start(project)
EngineApi.register_listener(project, self(), [:all])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ defmodule Expert.Provider.Handlers.GoToDefinitionTest do
setup_all do
project = project(:navigations)

start_supervised!({Forge.NodePortMapper, []})
start_supervised!(Expert.Application.document_store_child_spec())
start_supervised!({DynamicSupervisor, Expert.Project.DynamicSupervisor.options()})
start_supervised!({Expert.Project.Supervisor, project})
Expand Down
1 change: 1 addition & 0 deletions apps/expert/test/expert/provider/handlers/hover_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ defmodule Expert.Provider.Handlers.HoverTest do
setup_all do
project = Fixtures.project()

start_supervised!({Forge.NodePortMapper, []})
start_supervised!(Expert.Application.document_store_child_spec())
start_supervised!({DynamicSupervisor, Expert.Project.DynamicSupervisor.options()})
start_supervised!({Expert.Project.Supervisor, project})
Expand Down
1 change: 1 addition & 0 deletions apps/expert/test/support/test/completion_case.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ defmodule Expert.Test.Expert.CompletionCase do
setup_all do
project = project()

start_supervised!({Forge.NodePortMapper, []})
start_supervised!({DynamicSupervisor, Expert.Project.DynamicSupervisor.options()})
start_supervised!({Expert.Project.Supervisor, project})

Expand Down
4 changes: 2 additions & 2 deletions apps/expert/test/test_helper.exs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
Application.ensure_all_started(:snowflake)
Application.ensure_all_started(:refactorex)
{"", 0} = System.cmd("epmd", ~w(-daemon))

random_number = :rand.uniform(500)

with :nonode@nohost <- Node.self() do
{:ok, _pid} =
:net_kernel.start(:"testing-#{random_number}@127.0.0.1", %{name_domain: :longnames})
Node.start(:"expert-manager-testing-#{random_number}@127.0.0.1", :longnames)
end

Engine.Module.Loader.start_link(nil)
Expand Down
2 changes: 1 addition & 1 deletion apps/forge/lib/forge/document/store.ex
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ defmodule Forge.Document.Store do
end

def name do
{:via, :global, {__MODULE__, entropy()}}
{:global, {__MODULE__, entropy()}}
end

defp entropy_key do
Expand Down
Loading
Loading