registry.ex (1244B)
1 defmodule Ecto.Repo.Registry do 2 @moduledoc false 3 4 use GenServer 5 6 def start_link(_opts) do 7 GenServer.start_link(__MODULE__, :ok, name: __MODULE__) 8 end 9 10 def associate(pid, name, value) when is_pid(pid) do 11 GenServer.call(__MODULE__, {:associate, pid, name, value}) 12 end 13 14 def all_running() do 15 for [pid, name] <- :ets.match(__MODULE__, {:"$1", :_, :"$2", :_}) do 16 name || pid 17 end 18 end 19 20 def lookup(repo) when is_atom(repo) do 21 GenServer.whereis(repo) 22 |> Kernel.||(raise "could not lookup Ecto repo #{inspect repo} because it was not started or it does not exist") 23 |> lookup() 24 end 25 26 def lookup(pid) when is_pid(pid) do 27 :ets.lookup_element(__MODULE__, pid, 4) 28 end 29 30 ## Callbacks 31 32 @impl true 33 def init(:ok) do 34 table = :ets.new(__MODULE__, [:named_table, read_concurrency: true]) 35 {:ok, table} 36 end 37 38 @impl true 39 def handle_call({:associate, pid, name, value}, _from, table) do 40 ref = Process.monitor(pid) 41 true = :ets.insert(table, {pid, ref, name, value}) 42 {:reply, :ok, table} 43 end 44 45 @impl true 46 def handle_info({:DOWN, ref, _type, pid, _reason}, table) do 47 [{^pid, ^ref, _, _}] = :ets.lookup(table, pid) 48 :ets.delete(table, pid) 49 {:noreply, table} 50 end 51 end