上章说到我们要引入syn https://github.com/ostinelli/syn/
看过文档,它并没有直接提供{via, Module, Name} 相关的方法。我们需要封装一下。
Name暂时可以用id,如果有需要再调整
以后有回调需求的话,刚好也可以做在那个模块里。
在player_server_manager项目里增加{:syn, "1.4.0"} 运行命令获取依赖
修改application 方法,增加依赖
def application do
[applications: [:logger, :syn],
mod: {PlayerServerManager, []}]
end
然后在项目里增加PlayerRegistry模块
defmodule PlayerRegistry do
def register_name(name, pid) when is_pid(pid) do
case :syn.register(name, pid) do
:ok -> :yes
_ -> :no
end
end def unregister_name(name) do
:syn.unregister(name)
:ok
end def whereis_name(name) do
:syn.find_by_key(name)
end def send(name, msg) do
case whereis_name(name) do
:undefined ->
exit({:badarg, {name, msg}})
pid ->
Kernel.send pid, msg
pid
end
end
end
参照:global 模块实现。
修改PlayerServer.start_link 如下
def via_tuple(id), do: {:via, PlayerRegistry, id}
def start_link(player) do
GenServer.start_link(__MODULE__, %{player: player, socket: nil}, name: via_tuple(player.base_info.id))
end
PlayerServerManager.start 修改,增加syn的初始化,
def start(_type, _args) do
import Supervisor.Spec, warn: false
:syn.init()
children = [
# Define workers and child supervisors to be supervised
worker(PlayerServer, [], restart: :temporary),
] # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :simple_one_for_one, name: PlayerServerManager.Supervisor]
Supervisor.start_link(children, opts)
end
PlayerServerManagerTest增加测试代码
test "player_registry", %{player: player} do
assert {:ok, pid} = PlayerServerManager.start_player_server(player)
assert PlayerServer.gem(PlayerServer.via_tuple(player.base_info.id)) == 0
end
测试成功,ok。目前看起来还好。分布式的注册以及冲突处理留待以后再做测试了。
写到这,发现via_tuple要能接受player和id2种参数更好,方便点。