Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: ensure some elixir internals are ready #478

Merged
merged 1 commit into from
May 15, 2024
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
56 changes: 40 additions & 16 deletions lib/next_ls/runtime.ex
Original file line number Diff line number Diff line change
Expand Up @@ -231,22 +231,32 @@ defmodule NextLS.Runtime do
true <- connect(node, port, 120) do
NextLS.Logger.info(logger, "Connected to node #{node}")

:next_ls
|> :code.priv_dir()
|> Path.join("monkey/_next_ls_private_compiler.ex")
|> then(&:rpc.call(node, Code, :compile_file, [&1]))
|> tap(fn
{:badrpc, error} ->
NextLS.Logger.error(logger, "Bad RPC call to node #{node}: #{inspect(error)}")
send(me, {:cancel, error})

_ ->
:ok
end)

{:ok, _} = :rpc.call(node, :_next_ls_private_compiler, :start, [])

send(me, {:node, node})
result =
:next_ls
|> :code.priv_dir()
|> Path.join("monkey/_next_ls_private_compiler.ex")
|> then(fn path ->
if await_config_table(node, 5) do
:rpc.call(node, Code, :compile_file, [path])
else
{:badrpc, "internal ets table not found"}
end
end)
|> then(fn
{:badrpc, error} ->
NextLS.Logger.error(logger, "Bad RPC call to node #{node}: #{inspect(error)}")
send(me, {:cancel, error})
:error

_ ->
:ok
end)

if result == :ok do
{:ok, _} = :rpc.call(node, :_next_ls_private_compiler, :start, [])

send(me, {:node, node})
end
else
error ->
send(me, {:cancel, error})
Expand Down Expand Up @@ -275,6 +285,20 @@ defmodule NextLS.Runtime do
end
end

defp await_config_table(_node, 0) do
false
end

defp await_config_table(node, attempts) do
# this is an Elixir implementation detail, handle with care
if :undefined == :rpc.call(node, :ets, :whereis, [:elixir_config]) do
Process.sleep(100)
await_config_table(node, attempts - 1)
else
true
end
end

@impl GenServer
def handle_call(:ready?, _from, state) when is_ready(state) do
{:reply, true, state}
Expand Down
8 changes: 3 additions & 5 deletions priv/monkey/_next_ls_private_compiler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1032,14 +1032,13 @@ defmodule :_next_ls_private_compiler do
@moduledoc false

def start do
Code.put_compiler_option(:parser_options, columns: true, token_metadata: true)

children = [
:_next_ls_private_compiler_worker
]

# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: :_next_ls_private_application_supervisor]
{:ok, pid} = Supervisor.start_link(children, opts)
{:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one, name: :_next_ls_private_application_supervisor)
Process.unlink(pid)
{:ok, pid}
end
Expand All @@ -1049,7 +1048,6 @@ defmodule :_next_ls_private_compiler do
def compile do
# keep stdout on this node
Process.group_leader(self(), Process.whereis(:user))
Code.put_compiler_option(:parser_options, columns: true, token_metadata: true)

Code.put_compiler_option(:tracers, [NextLSPrivate.DepTracer | @tracers])

Expand Down