Add all_loaded caching per node (#2346)

This commit is contained in:
José Valim 2023-11-14 19:31:33 +01:00 committed by GitHub
parent 3b15e75227
commit 835afa8287
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 2 deletions

View file

@ -23,6 +23,13 @@ defmodule Livebook.Intellisense do
map_binding: (Code.binding() -> any())
}
@doc """
Clear any cache stored related to the given node.
"""
def clear_cache(node) do
IdentifierMatcher.clear_all_loaded(node)
end
@doc """
Resolves an intellisense request as defined by `Runtime`.

View file

@ -99,6 +99,25 @@ defmodule Livebook.Intellisense.IdentifierMatcher do
@alias_only_atoms ~w(alias import require)a
@alias_only_charlists ~w(alias import require)c
@doc """
Clears all loaded entries stored for node.
"""
def clear_all_loaded(node) do
:persistent_term.erase({__MODULE__, node})
end
defp cached_all_loaded(node) do
case :persistent_term.get({__MODULE__, node}, :error) do
:error ->
modules = Enum.map(:erpc.call(node, :code, :all_loaded, []), &elem(&1, 0))
:persistent_term.put({__MODULE__, node}, modules)
modules
[_ | _] = modules ->
modules
end
end
@doc """
Returns a list of identifiers matching the given `hint` together
with relevant information.
@ -438,7 +457,7 @@ defmodule Livebook.Intellisense.IdentifierMatcher do
end
defp container_context_struct_fields(pairs, mod, hint, ctx) do
map = Map.from_struct(mod.__struct__)
map = Map.from_struct(mod.__struct__())
map = filter_out_fields(map, pairs)
for {field, default} <- map,
@ -619,7 +638,7 @@ defmodule Livebook.Intellisense.IdentifierMatcher do
end
defp get_modules(node) do
modules = Enum.map(:erpc.call(node, :code, :all_loaded, []), &elem(&1, 0))
modules = cached_all_loaded(node)
if node == node() and :code.get_mode() == :interactive do
modules ++ get_modules_from_applications()

View file

@ -307,6 +307,7 @@ defmodule Livebook.Runtime.ErlDist.RuntimeServer do
@impl true
def init(opts) do
Process.send_after(self(), :check_owner, @await_owner_timeout)
:net_kernel.monitor_nodes(true, node_type: :all)
schedule_memory_usage_report()
{:ok, evaluator_supervisor} = ErlDist.EvaluatorSupervisor.start_link()
@ -349,6 +350,11 @@ defmodule Livebook.Runtime.ErlDist.RuntimeServer do
end
end
def handle_info({:nodedown, node, _metadata}, state) do
Livebook.Intellisense.clear_cache(node)
{:noreply, state}
end
def handle_info({:DOWN, _, :process, owner, _}, %{owner: owner} = state) do
{:stop, :shutdown, state}
end

View file

@ -230,6 +230,16 @@ defmodule Livebook.IntellisenseTest do
] = Intellisense.get_completion_items("RuntimeE", context, node())
end
test "caches all loaded modules" do
context = eval(do: nil)
Intellisense.get_completion_items("Hub", context, node())
key = {Intellisense.IdentifierMatcher, node()}
assert [_ | _] = :persistent_term.get(key, :error)
Intellisense.IdentifierMatcher.clear_all_loaded(node())
assert :error = :persistent_term.get(key, :error)
end
test "Elixir struct completion lists nested options" do
context = eval(do: nil)