52 lines
1.2 KiB
Elixir
52 lines
1.2 KiB
Elixir
defmodule Ecto.Repo.Registry do
|
|
@moduledoc false
|
|
|
|
use GenServer
|
|
|
|
def start_link(_opts) do
|
|
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
|
|
end
|
|
|
|
def associate(pid, name, value) when is_pid(pid) do
|
|
GenServer.call(__MODULE__, {:associate, pid, name, value})
|
|
end
|
|
|
|
def all_running() do
|
|
for [pid, name] <- :ets.match(__MODULE__, {:"$1", :_, :"$2", :_}) do
|
|
name || pid
|
|
end
|
|
end
|
|
|
|
def lookup(repo) when is_atom(repo) do
|
|
GenServer.whereis(repo)
|
|
|> Kernel.||(raise "could not lookup Ecto repo #{inspect repo} because it was not started or it does not exist")
|
|
|> lookup()
|
|
end
|
|
|
|
def lookup(pid) when is_pid(pid) do
|
|
:ets.lookup_element(__MODULE__, pid, 4)
|
|
end
|
|
|
|
## Callbacks
|
|
|
|
@impl true
|
|
def init(:ok) do
|
|
table = :ets.new(__MODULE__, [:named_table, read_concurrency: true])
|
|
{:ok, table}
|
|
end
|
|
|
|
@impl true
|
|
def handle_call({:associate, pid, name, value}, _from, table) do
|
|
ref = Process.monitor(pid)
|
|
true = :ets.insert(table, {pid, ref, name, value})
|
|
{:reply, :ok, table}
|
|
end
|
|
|
|
@impl true
|
|
def handle_info({:DOWN, ref, _type, pid, _reason}, table) do
|
|
[{^pid, ^ref, _, _}] = :ets.lookup(table, pid)
|
|
:ets.delete(table, pid)
|
|
{:noreply, table}
|
|
end
|
|
end
|