/var/log/messages

Jul 20, 2019 - 2 minute read - Comments - programming

Game of Life の実装

実装確認してみるに、vue が Phoenix 経由して Cell.Supervisor とやりとりしている模様。経由しているのは web/channels 配下にいる

  • Phoenix.Socket
  • (Socket を介して) Phoenix.Channel

を使っています。

てことは

OTP な実装確認しないと、なのか。リポジトリの README によれば

  • Cell は Genserver によって表現される
  • Cell は Cell.Supervisor によって制御される
  • Universe.Supervisor は Cell.Supervisor, Registry, Universe を制御
  • Universe はゲームの全体的な状態を表現
  • Registry は key-value strorage で Cell の pid と位置情報をリンクさせる方法を提供

とのこと。

というか

OTP なサーバと vue が直接 (ではないか) やりとりできる方法があるとは。というか、よくよく見てみるに、Phoenix.Channel は Cell とか Universe なんかを直接使っているな。このあたりの仕掛けってどうなっているのかと。

諸々確認したところ

Interface.LifeChannel が game 配架のクラスと直接やりとりできるのは umbrella project という仕組みによる模様。

LifeChannel の i/f は以下。

  • join
  • reset (on により JS から呼び出される)
  • tick (on により JS から呼び出される)

join

Cell を初期化しています (Cell.Supervisor.children の戻りを Cell.reap に渡している)。

reset

これ、リセット時に呼び出されるやつですね。初期化した後で

    broadcast!(socket, "reset", %{positions: Cell.Supervisor.positions})

してるのですが何これ。以下によれば

broadcast! は接続されている全クライアントに対してメッセージをプッシュする関数です。つまり、今回は受け取った値をそっくりそのまま全クライアントに対して配信するわけです。

とのこと。

tick

あるいはこちらはゲームの状態を進行させる手続き。

  • Universe.tick して
  • broadcast!(socket, "tick", %{positions: Cell.Supervisor.positions}) しています

何というか、メセジ (位置情報) を push してるのは良いのですが誰がこれを受け取っているのかと。色々確認してる中で channel.on はイベントリスナ登録、という記述がありました。

色々謎が解けたところで

本体側の確認に着手。て、OTP のプロセスを生成してるの誰でしょ。Universe.Supervisor を云々してるのは誰なのか問題。games 側の mix.exs に以下な記述があり、

  def application do
    # Specify extra applications you'll use from Erlang/Elixir
    [
      extra_applications: [:logger],
      mod: {Universe.Supervisor, []}
    ]
  end

アプリ起動時に呼び出すモジュールが、とのこと。というか、この games なアプリを誰が起動しているのかと、と言いつつ最上位の mix.exs 見てみるに

  def project do
    [apps_path: "apps",

な記述があり、apps 配架なプロジェクトの mix.exs によれば

  • interface では Interface
  • game では Universe.Supervisor

が、ということなのか成程。

ということで

OTP 側で起動されるのは Universe.Supervisor です。こいつは子供として

  • Universe
  • Cell.Supervisor
  • Registry

の面倒を見る模様。Registry がよくわからんな。