elixir - 22 genserver
访问量: 1518
参考:https://elixir-lang.org/getting-started/mix-otp/genserver.html
新建一个 registry.ex文件
efmodule KV.Registry do use GenServer def start_link(opts) do # 这里的__MODULE__ 表示当前的 module GenServer.start_link(__MODULE__, :ok, opts) end def lookup(server,name) do GenServer.call(server, {:lookup, name}) end def create(server, name) do GenServer.cast(server, {:create, name}) end def init(:ok) do {:ok , %{}} end # call : 是同步的 sync def handle_call({:lookup,name}, _from, names) do {:reply, Map.fetch(names, name), names} end # cast: 是异步的(async) def handle_cast({:create, name}, names ) do if Map.has_key?(names, name) do {:noreply, names} else {:ok, bucket} = KV.Bucket.start_link([]) {:noreply, Map.put(names, name, bucket)} end end end
测试一下 Agent, Process monitor
$ iex -S mix iex(1)> {:ok, pid} = KV.Bucket.start_link [] {:ok, #PID<0.153.0>} iex(2)> Process.monitor pid #Reference<0.1655961756.1033633793.180708> iex(3)> Agent.stop pid :ok iex(4)> flush {:DOWN, #Reference<0.1655961756.1033633793.180708>, :process, #PID<0.153.0>, :normal} :ok还可以进一步修改 server的实现, 代码如下:
defmodule KV.Registry do use GenServer def start_link(opts) do # 这里的__MODULE__ 表示当前的 module GenServer.start_link(__MODULE__, :ok, opts) end def lookup(server,name) do GenServer.call(server, {:lookup, name}) end def create(server, name) do GenServer.cast(server, {:create, name}) end def init(:ok) do names = %{} refs = %{} {:ok, {names, refs}} end # call : 是同步的 sync def handle_call({:lookup,name}, _from, state ) do {names, _} = state {:reply, Map.fetch(names, name), state} end # cast: 是异步的(async) def handle_cast({:create, name}, {names, refs}) do if Map.has_key?(names, name) do {:noreply, {names, refs}} else {:ok, pid} = KV.Bucket.start_link([]) ref = Process.monitor(pid) refs = Map.put(refs, ref, name) names = Map.put(names, name, pid) {:noreply, {names, refs}} end end def handle_info({:DOWN, ref, :process, _pid, _reason}, {names, refs}) do {name, refs} = Map.pop(refs, ref) names = Map.delete(names, name) {:noreply, {names, refs}} end def handle_info(_msg, state) do {:noreply, state} end def stop(server) do GenServer.stop(server) end end