Elixir遊戲服設計三

玩家進程用gen_server來建模,我不直接使用 use GenServer, 而是使用exactor,該庫能夠去掉反鎖的接口定義。html

咱們新建一個 player_server_manager app吧, 使用 mix new player_server_manager --sup, 會給咱們增長sup。而後在mix.exs裏增長exactor的依賴以下:服務器

  defp deps do
    [{:exactor, "~> 2.2"}]
  end

跑 mix deps.get,成功了依賴就準備好了。app

默認生成的player_server_manager.exsocket

defmodule PlayerServerManager do
  use Application

  # See http://elixir-lang.org/docs/stable/elixir/Application.html
  # for more information on OTP Applications
  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    children = [
      # Define workers and child supervisors to be supervised
      # worker(PlayerServerManager.Worker, [arg1, arg2, arg3]),
    ]

    # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: PlayerServerManager.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

玩家進程就叫player_server吧。把它改爲我須要的。分佈式

defmodule PlayerServerManager do
  use Application

  # See http://elixir-lang.org/docs/stable/elixir/Application.html
  # for more information on OTP Applications
  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    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
end

由於玩家進程是動態建立的,所以採用simple_one_for_one, 同時我不須要默認傳參數,還有我不須要重啓。測試

好了如今讓咱們編寫PlayerServer模塊(如今是簡單的,並且我還未知有什麼須要調整的,後續隨着服務器設計而演化吧)。spa

讓咱們先增長個查詢鑽石的接口吧。設計

defmodule PlayerServer do

    use ExActor.GenServer

    defstart start_link(player), do: initial_state(%{player: player, socket: nil})
    defcall gem, state: state, do: reply(state.player.base_info.gem)
end

咱們在PlayerServerManager裏增長啓動接口以下rest

 def start_player_server(%Player{} = player) do
    Supervisor.start_child(PlayerServerManager.Supervisor, [player])
  end

在player_server_manager_test.exs裏增長測試代碼code

defmodule PlayerServerManagerTest do
  use ExUnit.Case
  doctest PlayerServerManager
  
  setup do
    Application.stop(:player_server_manager)
    :ok = Application.start(:player_server_manager)
  end

  setup do
      player = Player.new(0)
      {:ok, player: player}
  end
  test "start player_server", %{player: player} do
    assert {:ok, pid} = PlayerServerManager.start_player_server(player)
    assert  PlayerServer.gem(pid) == 0
  end
end

測試經過。

寫到這裏發現以前Player和BaseInfo @behavior 實際上應該爲@hehaviour, 既然以前沒報錯,我就把它去掉了,測試依然經過。說明其實可能只須要

defdelegate。

好了,這一章就到這。遺留的問題有,咱們一般須要給玩家進程一個名字,而不是經過pid,若是是單節點的話, local 註冊已經足夠,若是是跨服訪問,咱們須要一個分佈式的註冊機制(實際上分佈式註冊機制容易有坑,如無必要,千萬別)。好比gporc,好比syn。 前者比較有名,我之前在erlang用過,以前有碰到莫名奇妙的問題。因此下章試試syn吧。

相關文章
相關標籤/搜索