Skip to content

Commit cb11396

Browse files
committed
fix: single thread compiler requests
1 parent c9e260b commit cb11396

File tree

9 files changed

+1097
-176
lines changed

9 files changed

+1097
-176
lines changed

lib/next_ls.ex

+194-100
Large diffs are not rendered by default.

lib/next_ls/progress.ex

+20-18
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,28 @@ defmodule NextLS.Progress do
22
@moduledoc false
33
@env Mix.env()
44
def start(lsp, token, msg) do
5-
# FIXME: gen_lsp should allow stubbing requests so we don't have to
6-
# set this in every test. For now, don't send it in the test env
7-
if @env != :test do
8-
GenLSP.request(lsp, %GenLSP.Requests.WindowWorkDoneProgressCreate{
9-
id: System.unique_integer([:positive]),
10-
params: %GenLSP.Structures.WorkDoneProgressCreateParams{
11-
token: token
12-
}
13-
})
14-
end
5+
Task.start(fn ->
6+
# FIXME: gen_lsp should allow stubbing requests so we don't have to
7+
# set this in every test. For now, don't send it in the test env
8+
if @env != :test do
9+
GenLSP.request(lsp, %GenLSP.Requests.WindowWorkDoneProgressCreate{
10+
id: System.unique_integer([:positive]),
11+
params: %GenLSP.Structures.WorkDoneProgressCreateParams{
12+
token: token
13+
}
14+
})
15+
end
1516

16-
GenLSP.notify(lsp, %GenLSP.Notifications.DollarProgress{
17-
params: %GenLSP.Structures.ProgressParams{
18-
token: token,
19-
value: %GenLSP.Structures.WorkDoneProgressBegin{
20-
kind: "begin",
21-
title: msg
17+
GenLSP.notify(lsp, %GenLSP.Notifications.DollarProgress{
18+
params: %GenLSP.Structures.ProgressParams{
19+
token: token,
20+
value: %GenLSP.Structures.WorkDoneProgressBegin{
21+
kind: "begin",
22+
title: msg
23+
}
2224
}
23-
}
24-
})
25+
})
26+
end)
2527
end
2628

2729
def stop(lsp, token, msg \\ nil) do

lib/next_ls/runtime.ex

+23-41
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ defmodule NextLS.Runtime do
9090
sname = "nextls-runtime-#{System.system_time()}"
9191
name = Keyword.fetch!(opts, :name)
9292
working_dir = Keyword.fetch!(opts, :working_dir)
93+
lsp_pid = Keyword.fetch!(opts, :lsp_pid)
9394
uri = Keyword.fetch!(opts, :uri)
9495
parent = Keyword.fetch!(opts, :parent)
9596
logger = Keyword.fetch!(opts, :logger)
@@ -222,6 +223,8 @@ defmodule NextLS.Runtime do
222223
:ok
223224
end)
224225

226+
{:ok, _} = :rpc.call(node, :_next_ls_private_compiler, :start, [])
227+
225228
send(me, {:node, node})
226229
else
227230
error ->
@@ -237,6 +240,7 @@ defmodule NextLS.Runtime do
237240
port: port,
238241
task_supervisor: task_supervisor,
239242
logger: logger,
243+
lsp_pid: lsp_pid,
240244
parent: parent,
241245
errors: nil,
242246
registry: registry,
@@ -279,54 +283,32 @@ defmodule NextLS.Runtime do
279283
end
280284
end
281285

282-
def handle_call({:compile, opts}, from, %{node: node} = state) do
283-
for {_ref, {task_pid, _from}} <- state.compiler_refs, do: Process.exit(task_pid, :kill)
284-
285-
task =
286-
Task.Supervisor.async_nolink(state.task_supervisor, fn ->
287-
if opts[:force] do
288-
File.rm_rf!(Path.join(state.working_dir, ".elixir-tools/_build"))
289-
end
290-
291-
case :rpc.call(node, :_next_ls_private_compiler, :compile, []) do
292-
{:badrpc, error} ->
293-
NextLS.Logger.error(state.logger, "Bad RPC call to node #{node}: #{inspect(error)}")
294-
[]
295-
296-
{_, diagnostics} when is_list(diagnostics) ->
297-
Registry.dispatch(state.registry, :extensions, fn entries ->
298-
for {pid, _} <- entries, do: send(pid, {:compiler, diagnostics})
299-
end)
300-
301-
NextLS.Logger.info(state.logger, "Compiled #{state.name}!")
302-
303-
diagnostics
304-
305-
{:error, %Mix.Error{message: "Can't continue due to errors on dependencies"}} ->
306-
{:runtime_failed, state.name, {:error, :deps}}
286+
def handle_call({:compile, opts}, _from, %{node: node} = state) do
287+
opts =
288+
opts
289+
|> Keyword.put_new(:working_dir, state.working_dir)
290+
|> Keyword.put_new(:registry, state.registry)
291+
|> Keyword.put(:from, self())
307292

308-
unknown ->
309-
NextLS.Logger.warning(state.logger, "Unexpected compiler response: #{inspect(unknown)}")
310-
[]
311-
end
312-
end)
293+
with {:badrpc, error} <- :rpc.call(node, :_next_ls_private_compiler_worker, :enqueue_compiler, [opts]) do
294+
NextLS.Logger.error(state.logger, "Bad RPC call to node #{node}: #{inspect(error)}")
295+
end
313296

314-
{:noreply, %{state | compiler_refs: Map.put(state.compiler_refs, task.ref, {task.pid, from})}}
297+
{:reply, :ok, state}
315298
end
316299

317300
@impl GenServer
318-
def handle_info({ref, errors}, %{compiler_refs: compiler_refs} = state) when is_map_key(compiler_refs, ref) do
319-
Process.demonitor(ref, [:flush])
320-
321-
orig = elem(compiler_refs[ref], 1)
322-
GenServer.reply(orig, errors)
323-
324-
{:noreply, %{state | compiler_refs: Map.delete(compiler_refs, ref)}}
301+
# NOTE: these two callbacks are basically to forward the messages from the runtime to the LSP
302+
# LSP process so that progress messages can be dispatched
303+
def handle_info({:compiler_result, caller_ref, result}, state) do
304+
# we add the runtime name into the message
305+
send(state.lsp_pid, {:compiler_result, caller_ref, state.name, result})
306+
{:noreply, state}
325307
end
326308

327-
def handle_info({:DOWN, ref, :process, _pid, _reason}, %{compiler_refs: compiler_refs} = state)
328-
when is_map_key(compiler_refs, ref) do
329-
{:noreply, %{state | compiler_refs: Map.delete(compiler_refs, ref)}}
309+
def handle_info({:compiler_canceled, _caller_ref} = msg, state) do
310+
send(state.lsp_pid, msg)
311+
{:noreply, state}
330312
end
331313

332314
def handle_info({:DOWN, _, :port, port, _}, %{port: port} = state) do

lib/next_ls/runtime/supervisor.ex

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ defmodule NextLS.Runtime.Supervisor do
1111
def init(init_arg) do
1212
name = init_arg[:name]
1313
lsp = init_arg[:lsp]
14+
lsp_pid = init_arg[:lsp_pid]
1415
registry = init_arg[:registry]
1516
logger = init_arg[:logger]
1617
hidden_folder = init_arg[:path]
@@ -34,7 +35,8 @@ defmodule NextLS.Runtime.Supervisor do
3435
name: db_name,
3536
runtime: name,
3637
activity: db_activity},
37-
{NextLS.Runtime, init_arg[:runtime] ++ [name: name, registry: registry, parent: sidecar_name, db: db_name]}
38+
{NextLS.Runtime,
39+
init_arg[:runtime] ++ [name: name, registry: registry, parent: sidecar_name, lsp_pid: lsp_pid, db: db_name]}
3840
]
3941

4042
Supervisor.init(children, strategy: :one_for_one)

0 commit comments

Comments
 (0)