Skip to content

Commit 06acca3

Browse files
committed
fix: ensure some elixir internals are ready (#478)
Frequently we'd see the following error in tests, and some users were seeing in production: ``` [error] Bad RPC call to node nextls-runtime-1715431446385794000@MacBook -XXX: {:EXIT, {:badarg, [{:ets, :lookup, [:elixir_config, :parser_options], [error_info: %{cause: :id, module: :erl_stdlib_errors}] }, {:elixir_config, :get, 1, [file: ~c"src/elixir_config.erl", line: 21]} , {:elixir_compiler, :string, 3, [file: ~c"src/elixir_compiler.erl", line : 7]}, {Module.ParallelChecker, :verify, 1, [file: ~c"lib/module/parallel _checker.ex", line: 112]}, {Code, :compile_file, 1, []}]}} ``` I believe that this is caused by an internal ETS table not being booted yet, so we not await on it being present on the project node. Closes #467
1 parent 4559d1a commit 06acca3

File tree

3 files changed

+54
-32
lines changed

3 files changed

+54
-32
lines changed

.github/workflows/release.yaml

+11-11
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@ permissions:
99
pull-requests: write
1010

1111
jobs:
12-
commitlint:
13-
runs-on: ubuntu-latest
14-
name: commitlint
12+
# commitlint:
13+
# runs-on: ubuntu-latest
14+
# name: commitlint
1515

16-
steps:
17-
- uses: actions/checkout@v4
18-
with:
19-
fetch-depth: 0
20-
- name: Install Deps
21-
run: yarn install
22-
- name: Lint PR Title
23-
run: yarn commitlint --from "${{ github.event.before }}"
16+
# steps:
17+
# - uses: actions/checkout@v4
18+
# with:
19+
# fetch-depth: 0
20+
# - name: Install Deps
21+
# run: yarn install
22+
# - name: Lint PR Title
23+
# run: yarn commitlint --from "${{ github.event.before }}"
2424

2525
release:
2626
name: release

lib/next_ls/runtime.ex

+40-16
Original file line numberDiff line numberDiff line change
@@ -231,22 +231,32 @@ defmodule NextLS.Runtime do
231231
true <- connect(node, port, 120) do
232232
NextLS.Logger.info(logger, "Connected to node #{node}")
233233

234-
:next_ls
235-
|> :code.priv_dir()
236-
|> Path.join("monkey/_next_ls_private_compiler.ex")
237-
|> then(&:rpc.call(node, Code, :compile_file, [&1]))
238-
|> tap(fn
239-
{:badrpc, error} ->
240-
NextLS.Logger.error(logger, "Bad RPC call to node #{node}: #{inspect(error)}")
241-
send(me, {:cancel, error})
242-
243-
_ ->
244-
:ok
245-
end)
246-
247-
{:ok, _} = :rpc.call(node, :_next_ls_private_compiler, :start, [])
248-
249-
send(me, {:node, node})
234+
result =
235+
:next_ls
236+
|> :code.priv_dir()
237+
|> Path.join("monkey/_next_ls_private_compiler.ex")
238+
|> then(fn path ->
239+
if await_config_table(node, 5) do
240+
:rpc.call(node, Code, :compile_file, [path])
241+
else
242+
{:badrpc, "internal ets table not found"}
243+
end
244+
end)
245+
|> then(fn
246+
{:badrpc, error} ->
247+
NextLS.Logger.error(logger, "Bad RPC call to node #{node}: #{inspect(error)}")
248+
send(me, {:cancel, error})
249+
:error
250+
251+
_ ->
252+
:ok
253+
end)
254+
255+
if result == :ok do
256+
{:ok, _} = :rpc.call(node, :_next_ls_private_compiler, :start, [])
257+
258+
send(me, {:node, node})
259+
end
250260
else
251261
error ->
252262
send(me, {:cancel, error})
@@ -275,6 +285,20 @@ defmodule NextLS.Runtime do
275285
end
276286
end
277287

288+
defp await_config_table(_node, 0) do
289+
false
290+
end
291+
292+
defp await_config_table(node, attempts) do
293+
# this is an Elixir implementation detail, handle with care
294+
if :undefined == :rpc.call(node, :ets, :whereis, [:elixir_config]) do
295+
Process.sleep(100)
296+
await_config_table(node, attempts - 1)
297+
else
298+
true
299+
end
300+
end
301+
278302
@impl GenServer
279303
def handle_call(:ready?, _from, state) when is_ready(state) do
280304
{:reply, true, state}

priv/monkey/_next_ls_private_compiler.ex

+3-5
Original file line numberDiff line numberDiff line change
@@ -1032,14 +1032,13 @@ defmodule :_next_ls_private_compiler do
10321032
@moduledoc false
10331033

10341034
def start do
1035+
Code.put_compiler_option(:parser_options, columns: true, token_metadata: true)
1036+
10351037
children = [
10361038
:_next_ls_private_compiler_worker
10371039
]
10381040

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

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

0 commit comments

Comments
 (0)