/var/log/messages

May 22, 2019 - 2 minute read - Comments - programming

プログラミング Elixir (31)

スタックな OTP サーバの課題を、って思ってたらやっていたorz

サーバ実行のトラッキング

以降を確認しつつ、控えを列挙な方向です。

こうか (ちょっとハマッた)

iex(1)> {:ok,pid} = GenServer.start_link(Sequence.Server, 100, [:debug [:trace]]) 

以下な出力が。

** (FunctionClauseError) no function clause matching in Access.get/3    
    
    The following arguments were given to Access.get/3:
    
        # 1
        :debug
    
        # 2
        :trace
    
        # 3
        nil
    
    Attempted function clauses (showing 5 out of 5):
    
        def get(%module{} = container, key, default)
        def get(map, key, default) when is_map(map)
        def get(list, key, default) when is_list(list) and is_atom(key)
        def get(list, key, _default) when is_list(list)
        def get(nil, _key, default)
    
    (elixir) lib/access.ex:316: Access.get/3

ありゃ?

リトライ

iex(1)> {:ok,pid} = GenServer.start_link(Sequence.Server, 100, [debug: [:trace]]) 
{:ok, #PID<0.135.0>}

できたな。。。

iex(2)> GenServer.call(pid, :next_number)
*DBG* <0.135.0> got call next_number from <0.133.0>
*DBG* <0.135.0> sent 100 to <0.133.0>, new state 101
100
iex(3)> GenServer.call(pid, :next_number)
*DBG* <0.135.0> got call next_number from <0.133.0>
*DBG* <0.135.0> sent 101 to <0.133.0>, new state 102
101

あるいは以下。

iex(5)> {:ok,pid} = GenServer.start_link(Sequence.Server, 100, [debug: [:statistics]])
{:ok, #PID<0.146.0>}

で、動作確認。

iex(6)> GenServer.call(pid, :next_number)
100
iex(7)> GenServer.call(pid, :next_number)
101
iex(8)> :sys.statistics pid, :get
{:ok,
 [
   start_time: {{2019, 5, 22}, {20, 33, 17}},
   current_time: {{2019, 5, 22}, {20, 34, 6}},
   reductions: 94,
   messages_in: 2,
   messages_out: 2
 ]}

あるいは デバッグパラメータにひも付けられたリストは、単に sys モジュールで呼ばれる関数の名前 て記載があります。on/off できる模様。

iex(9)> :sys.trace pid, true
:ok
iex(10)> GenServer.call(pid, :next_number)
*DBG* <0.146.0> got call next_number from <0.133.0>
*DBG* <0.146.0> sent 102 to <0.133.0>, new state 103
102
iex(11)> :sys.trace pid, false            
:ok
iex(12)> GenServer.call(pid, :next_number)
103

これはこれは。あるいは get_status も便利、とあります。

iex(13)> :sys.get_status pid
{:status, #PID<0.146.0>, {:module, :gen_server},
 [
   [
     "$ancestors": [#PID<0.133.0>, #PID<0.77.0>], 
     "$initial_call": {Sequence.Server, :init, 1}
   ],
   :running,
   #PID<0.133.0>,
   [statistics: {{{2019, 5, 22}, {20, 33, 17}}, {:reductions, 21}, 4, 4}],
   [
     header: 'Status for generic server <0.146.0>',
     data: [
       {'Status', :running},
       {'Parent', #PID<0.133.0>},
       {'Logged events', []}
     ],
     data: [{'State', 104}]
   ]
 ]}

サーバモニタリングツール

て、GUI 環境が必要なのか。

iex(14)> :observer.start()
20:47:51.534 [error] WX Failed loading 'wxe_driver'@'/usr/lib/erlang/lib/wx-1.8.8/priv' 
{:error,
 {{:load_driver,
   'symbol _ZThn776_N17wxGenericListCtrl31GetSizeAvailableForScrollTargetERK6wxSize, version WXU_3.0 not defined in file libwx_gtk2u_core-3.0.so.0 with link time reference'}
,
  [ 
    {:wxe_server, :start, 1, [file: 'wxe_server.erl', line: 65]},
    {:wx, :new, 1, [file: 'wx.erl', line: 115]},
    {:observer_wx, :init, 1, [file: 'observer_wx.erl', line: 107]},
    {:wx_object, :init_it, 6, [file: 'wx_object.erl', line: 372]},
    {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]}
  ]}}

むむむ。

インターフェースの整理

とりあえず、ここまで確認しておきたい。実装が以下。

defmodule Sequence.Server do
  use GenServer

  def start_link(current_number) do
    GenServer.start_link(__MODULE__, current_number, name: __MODULE__)
  end

  def next_number do
    GenServer.call __MODULE__, :next_number
  end

  def increment_number(delta) do
    GenServer.cast __MODULE__, {:increment_number, delta}
  end

  def handle_call(:next_number, _from, current_number) do
    { :reply, current_number, current_number+1 }
  end

  def handle_cast({:increment_number, delta}, current_number) do
    { :noreply, current_number + delta}
  end

  def format_status(_reason, [ _pdict, state]) do
    [data: [{'State', "My current state is '#{inspect state}', and I'm happy"}]]
  end

  def init(init_arg) do
    {:ok, init_arg}
  end
end

iex -S mix なナニを以下に。

iex(1)> Sequence.Server.start_link 123
{:ok, #PID<0.144.0>}
iex(2)> Sequence.Server.next_number
123
iex(3)> Sequence.Server.next_number
124
iex(4)> Sequence.Server.increment_number 100
:ok
iex(5)> Sequence.Server.next_number
225
iex(6)>

練習問題は明日あたりで云々な方向にて。

はじめての宝酒造杯 プログラミング Elixir (32)

comments powered by Disqus