Elixirのドキュメント生成方法

mix.ex の deps に ex_docearmark を追加する。バージョンは最新版で。

  defp deps do
    [{:ex_doc, ">= 0.0.0", only: :docs},
     {:earmark, ">= 0.0.0", only: :docs}]
  end

パッケージのダウンロードとコンパイル

$ mix deps.get
$ mix deps.compile

環境変数に docs を設定して、mix docs コマンドを実行する。

$ MIX_ENV=docs mix docs

出来上がり。

ドキュメントを hex に上げる。

$ MIX_ENV=docs mix hex.docs

prefecture_jp というライブラリを作成した

prefecture_jpというライブラリを作成した。Hexにも上げた。

機能

都道府県コードから都道府県名への変換、またはその逆。都道府県コードは JIS X 0401 に対応(0埋め2桁の数字)。

使い方

単体で

都道府県コードから都道府県名を検索

iex> PrefectureJp.find("01").name
"北海道"

iex> PrefectureJp.find(code: "13").name
"東京都"

都道府名から都道府県コードを検索

iex> PrefectureJp.find(name: "東京都").code
"13"

都道府県情報の一覧

iex> PrefectureJp.all
[%PrefectureJp.Prefecture{area: "北海道", code: "01", name: "北海道",
  name_e: "hokkaido", name_h: "ほっかいどう",
  name_k: "ホッカイドウ"},
  .
  .
  .
 %PrefectureJp.Prefecture{area: "九州", code: "47", name: "沖縄県",
  name_e: "okinawa", ...}]
Ectoと一緒に

use PrefectureJp, 都道府県コードを持つカラム名 と書くことで、以下のように都道府県コードから都道府県名を求めることができる。

defmodule Place do
    use Ecto.Model
    use PrefectureJp, :prefecture_code

    schema "places" do
        field :prefecture_code, :string
    end
end
iex> place = %Place{prefecture_code: "23"}
iex> place |> Place.prefecture(:name)
"愛知県"

その他

このライブラリは jp_prefectureに大きな影響を受けている。

Elixir v1.1.0

v1.1.0 がリリースされていた (下書きしているときは、v1.1.0 だったけれど、現在の最新版は v1.1.1)。

機能追加で特記すべきことは、Enum, Dict, Task への関数の追加と、MapSet 型の追加、と書かれている。HashSet よりも速く、今後はSetの実装はMapSetがメインになっていくっぽい。英語がよく理解できていない。ついでに言うと HashSetMapSet の違いもよくわかっていない。

今後は MapSet を使うようにすればいいのかな。

Elixir1.0.5 は Erlang18 に未対応ではなかった

というのを初めて知った。

きっかけは、dialyxir を使おうと思ったから。

dialyxir をインストールする時の必ずエラーが発生しインストールに失敗する。 エラーの内容は以下の通り。

  Creating PLT /home/ymmtmsys/.dialyxir_core_18_1.0.5.plt ...
** (FunctionClauseError) no function clause matching in Keyword.get/3
    (elixir) lib/keyword.ex:118: Keyword.get(:no_such_file, :files, nil)
    lib/mix/tasks/dialyzer.plt.ex:132: Mix.Tasks.Dialyzer.Plt.core_plt_contains?/2
    lib/mix/tasks/dialyzer.plt.ex:123: anonymous fn/1 in Mix.Tasks.Dialyzer.Plt.missing_apps/0
    (elixir) lib/enum.ex:662: anonymous fn/3 in Enum.filter/2
    (elixir) lib/enum.ex:1261: Enum."-reduce/3-lists^foldl/2-0-"/3
    (elixir) lib/enum.ex:662: Enum.filter/2
    lib/mix/tasks/dialyzer.plt.ex:106: Mix.Tasks.Dialyzer.Plt.need_add?/0
    lib/mix/tasks/dialyzer.plt.ex:57: Mix.Tasks.Dialyzer.Plt.run/1

:no_such_file ということなのでファイルが存在していなくエラーになっているっぽいが。。。よくわからないのでググってみると こんなissueを発見。そしてコメントに

Elixir does not yet support Erlang 18.

と書かれているのを発見。

...あれ、今まで動いていたから気付いていなかったけど、まだ Erlang18 は対応してないっぽい。

Elixir の github を覗いてみると、確かにv1.2.0でErlan1 18.0に対応するようだ

とりあえず、自分の環境の Erlang のバージョンを下げよう。

追記 (2015/09/15)

インストールに失敗する原因は、Erlang のバージョンではなくメモリ不足によるものだった。 512Mのメモリを積んだVM上でインストールして失敗を繰り返していたたけれど、2Gに増やしたら成功した。 ちなみに1Gでは失敗した。

自分のPCは4GBしか積んでないので、VMに2Gも割けないのでインストールが終わったら通常の512Mに戻した。

追記 (2015/09/29)

https://github.com/elixir-lang/elixir/releases/tag/v1.0.5 を見るとErlang18.0 に対応したと書いてありました。

HTTPoisonのプーリング

HTTPクライアントにHTTPoisonを利用してみた。

同時実行数を増やすと50コネクション以上のコネクションは作成されないことがわかった。コードを見てみると、内部ではhackneyが使われていることがわかった。

hackney のドキュメントをみると、何も指定がなければデフォルトのプールが利用されるようだ(これ?)。

変更するためにはどうしたらよいかを調べた。

プールの数を変更する方法

名前をつけてプールを開始する。

poolname = :mypool
options  = [max_connections: 10]
:hackney_pool.start_pool(poolname, options)

HTTPリクエストを送る際のパラメータで、[hackney: [pool: :mypool]] を渡す。

HTTPoison.get!("http://localhost:4001", %{}, hackney: [pool: :mypool])

これでデフォルトではなく、自分の希望通りのプールサイズになる。

調べた時のライブラリのバージョン

  • httpoison, 0.7.2
  • hackney, 1.3.1

Phoenix で Poolboy を使ってコネクション(プロセス)プーリング

Poolboy を使ってコネクションプーリングができるようにする。接続先は memcached

memcached のクライアントにはmcdを使った。

サンプルのhello_phoenixを元にした。手を加えたファイルだけ以下に貼っておく (ちなみに Phoenix は v1.0.0)。

実行してみと、、、

% curl localhost:4000
{"val":"Hello Phoenix"}

成功。

メモ

  1. mcd はプロセスを生成した時点ではmemcached と接続されていない。ので、start_link してすぐに使おうとすると、結果が取れない。
  2. max_overflow の値を0以上にすると、プールしている数が size に達していてもさらにそこから max_overflow 分だけプロセスを生成する。
  3. max_overflow 分のプロセスは必要になった時点で生成されるので、01 で書いたとおり、コネクションが確立されていないプロセスが渡される時がある(というか、全てそうだった)。

感想

  • 既存ライブラリのおかげで簡単にプーリングできた。
  • Poolboy, mcd 両方とも、Erlang のライブラリ。Elixir を学ぶなら、Erlang を勉強しないとだめっぽい(動作を理解するのと、ライブラリの情報)。

Phoenixのデプロイ

Erlang (Elixir) の機能の中で気になっているのが、ホットデプロイだ。といっても、そういう機能があるからといって気軽にデプロイできるものでもないらしいけど。

デプロイに関するスライド。

デプロイ方法

Exrm

Exrm (Elixir Release Manager) を使うのがよさげ。 Phoenix 公式でも紹介されている。 設定方法などはそちらを参照。

パッケージ作成

MIX_ENV=prod mix release で本番環境用のリリースパッケージが rel/hello_phoenix/releases の下にバージョンごとに作成される。

起動
$ ./rel/hello_phoenix/bin/hello_phoenix start

停止するときは stop で。

更新

mix.ex に書かれているバージョンを上げ、MIX_ENV=prod mix release でパッケージを作成する。 (ここでは バージョンをv0.0.1 からv0.0.2に上るとする。)

v0.0.1のアプリが稼働中の状態でv0.0.2に更新するには

 rel/hello_phoenix/bin/hello_phoenix upgrade 0.0.2

で、OK。

自分の環境で試した限りでは、更新時に接続できないということはなかった。