[Elixir] GenServerのアイドルタイムアウト


この記事は Elixir その2 Advent Calendar 2020 16日目です。

前日は、「[Elixir] GenServerのCallとCast」でした。

本日もGenServer関連の話題です。

はじめに

さて、Elixirの「Let it crash」は本当にAWESOMEで正しくSupervisorを設置されすれば、何か問題があって子プロセスがクラッシュしてもSupervisorが自動でプロセスを再生成してくれます。
便利ですし、感動さえ覚えます。しかしながら、何もかも再起動して良いのでしょうか? そこをしっかり考えたいです。
Elixirのプロセスがいくら軽量だと言っても、なくてもよいものに関してはないほうが良いと思うのです。

GenServerを書くときには、アイドルタイムアウトの必要性も考えてみても良いかもしれません。

アイドルタイムアウト設定方法

設定方法は簡単です。

  1. GenServerの各callback関数の戻り値の3つ目にミリ秒の整数を指定。
  2. :timeout messageを処理するhandle_info/2を追加。その戻り値を{:stop, :normal, state}にすることでプロセスを停止させる。
defmodule ExampleServer do
  @idle_timeout 3000

  use GenServer, restart: :temporary

  require Logger

  def start_link do
    GenServer.start_link(__MODULE__, nil)
  end

  def init(state) do
    {:ok, nil, @idle_timeout}
  end

  def handle_call(:hello, _, state) do
    {:reply, "Hello", state, @idle_timeout}
  end

  def handle_info(:timeout, state) do
    Logger.info "Shutting down #{inspect(self())}"
    {:stop, :normal, state}
  end
end
# プロセスをスタート
iex> {:ok, pid} = ExampleServer.start_link
{:ok, #PID<0.135.0>}

# 3秒後自動でプロセス停止
iex>
09:18:59.764 [info]  Shutting down #PID<0.135.0>

さいごに

今後更に新しいことを学んだら随時内容も更新していこうと思います。


明日は「[Elixir] プロセス使用を検討する基準」です。引き続き、Elixirを楽しみましょう。