[Elixir in Action]OTP/GenServerを学んで非同期/並行処理を学ぶ

Elixir in Actionの続き。ようやっと3分の2くらい。写経もほどほどに実施しながらだとこのくらいですかね。 Chatpter6、7ではOpen Telecom Platformと、その上に構成されるGenServerに関する内容をざーっと通してました。 自前のloopで作っていた簡易サーバから、GenServerへと一般化、どのように処理しているのか?をボトルネックを解消していくという話の流れのなかで説明していっています。 サーバの基本的な役割は以下 Spawn でプロセスを分ける loopでプロセスを回す processの状態を管理する messageに反応する 送信元に応答を返す(送る) 最終的にはGenServerに近づいていくので、大きくここら辺は割愛。 ただ、 非常に考え方は重要 だし、ここら辺がErlang/Elixirのアーキテクチャとして選ぶ価値があると判断される箇所だと思うので、ちゃんと理解する方が良さそうです。 Elixir/Erlangのサーバで重要な役割を持つのは以下。 gen_server init, handle_call, handle_castなどのcallbacksを持つ 想定していない処理を無視するために、 def handle_info(_, state), do: something といった処理も入れる superevisor errorハンドリングやリカバリを担う application gen_event gen_fsm single processで処理される時のボトルネックは、多くのリクエストが溜まるにつれて応答(process)が遅くなること。 そこで、concurrentに処理できるように拡張する。ただ、cncurrentに処理できるように spawn により別プロセスで処理可能にすると、同期的に処理したい時が複雑になる。そこで、Elixir/Erlangでは以下のように GenServer.reply を使い、うまいこと非同期処理を利用している。 single processでリクエストを操作し、その実際の処理は子プロセスに実施させる。必ずこの方法が良いというわけではないが、本書ではこの方法を解の1つとして紹介していた。 ボトルネックの話でいうと、databaseを相手にしはじめると、DBとアプリをつなぐ間のpoolを処理するためのプロセスも関係してきますが、そこら辺はEctoでは poolboy が役割を担っているそうな。 poolboy Getting Startedを読んでなくていきなりこれでは辛いけれど、Getting Startedの後なら特にconcurrencyやfault toleranceの話を知る上ではこれは読んで価値ありそうです。特に、Erlang/Elixirに限らず、concurrencyやfault toleranceの考え方は参考になると思います。 補足コード Process.registerは以下…More

[Elixir in Action]BEAMとしてのprincipleとその実現のための処理系

principle against Erlang Minimize, isolate, and recover from the effects of runtime errors (fault torelance) Handle a load increase by adding more hardware resources without changing or redeploying the code (scalability) Run your system on multiple machines so that others can take over if one machine crashes (distribution) それらを達成するために、BEAM VMの処理系が作られてきました。 BEAMのprocessはOSのprocessではない OSのthreadがBEAMのSchedulerを持つ BEAMのSchedulerが、BEAMのprocessを管理する BEAMの1processの初期メモリは1~2KBなので、OSの1processのMByte単位のメモリ使用量に比べて遥かに小さいし、論理的にはBEAMのprocessは約26,8百万のprocessを実行できる BEAMのprocessは、scalabilityを達成するように、資源の追加に対して自動でその資源を使うようになっている…More

[Elixir in Action]polymorphismで拡張していく

Data abstractionsに書かれている章でした。 ここが終わったので、いよいよElixir/Erlangの真骨頂であるHigh Availabilityなシステムを構築するための説明に入ります。 structure moduleは、抽象データを作るために使われる。 map structs mapとstructsは同じように使われることが多い。 ただ、違うところもある。 例えばパターンマッチ このように、structはmapの特殊な形として使われる。 ちなみに、Recordというモジュールもあって、これは主にErlangライブラリを使う時には、Recordをimportして使いましょう、というものらしい。 polymorphism Elixirでは、polymorphismは protocol によって実現される。 defprotocol ではインターフェースを定義して、 defimpl でその実装を加えていく。 例えば、 to_string を独自のmodule、 Sample に加えるなら、 とすると、その結果として と得られる。(IO.putsはString.Chars.to_stringを指している) このprotocolは、他にも Inspect や Access といったものもある。 Elixirでは、このように元となる protocol に対して defimpl 内の実装を増やすことで機能を拡張していく。More

[Elixir in Action]Guard clauseの優先度

control flowの章の、 [Elixir in Action]Erlang/Elixirの再帰計算におけるnon-tail recursionとtail recursion 以外のことを。 以下のように、文字列バイナリも左辺/右辺のマッチングによって分けることができます。 以下のように、連続したマッチングもできます。 以下のように書いた場合、パターンマッチングでは上から順にマッチングを試みます。そのため a(other) が最も先頭にきたらそれがマッチングされます。 Elixirでは、以下のようなGuard clauseによっても適用される関数を条件付けすることができます。この時、 when で使われる型には優先度が存在します。 優先度は以下。 つまり、上記の Sample.a/1 に対してatomの :not_a_number を適用した場合、 が適用されます。エラーはありません。 そのため、数字だけを受け付けるようにするために以下のように書きます。 これで、 :not_a_number のようなものは FunctionClauseError がraiseされるようになります。 Cmprehensionsは、 for x <- [list], do: {何か} で構成される。 into などの要素を使ったりすると、繰り返しをより簡潔にかけたりする。なるほど。 Streamの説明もありましたが、Stream、色々できそうですね。 File.stream! でStreamにした後にごにょごにょStreamで操作した最後にto_list などでlistにして処理をする、といった例が載ってましたが、イマドキぽい感じがします 🙂More

[Elixir][Phoenix]簡単なWebアプリを生成してみた

やったこと備忘録。 最近、細々とElixir 1.0.5 x Phoenix 0.15.0ベースで、簡単な投票Webアプリケーションを作成してみました。 時間にして、作成自体、1日はいかない感じ。EctoやPhoenixを調べながらやって、1日といったところでしょうか。 使ってみた感想としては、PhoenxiはまんまRailsに近しいな、ということですね。 Railsに明るくなくとも、このくらいのアプリだとある程度書き進めることもできます。 ちなみに、私は明るくない側の人間です。 実装したことはこちら リポジトリはこちら Phoenixの他に、ログインなどの状態を保ちたいので、Guardianという認証ライブラリを使いました。 これ書いてて感じたのですが、文法的な表現は確かにElixirのように書くのですが、Supervisorなんかは別に書くわけではないし、なんかElixirを書いている!という感じがしなくもない… 最近Elixir in Actionを読んでいるのですが、ErlangからみたElixirという側面の強い情報を仕入れているのですが、なかなか面白いですね。学び始めて少しして、急にQiitaなんかでもやってみた系記事を見始めたのですが、それよりも前の古参の方々や学び始めた人、ここら辺を最初の一歩としてインプットしてるのかな。 Elixirのテスト関連を中心に色々知見を深めたい。More

[Elixir in Action]Read building blocks

Elixir in Action、Programming ElixirやGetting Startedなんかとは趣が異なって、BEAM VM上で動作するElixirという仕組みを色々深堀しているのですね。説明していること自体はかぶる箇所が多々あるのですが、より言語自体というよりも、その言語によって何を成すか?という目的に対してこの機能がある、といった感じで話が進んでいる感じ。 ところどころ、Erlang混じりの解説やリンクが登場するのはErlangを専門とする著者だから、の特徴かな。これ読んでいると、Erlangの言語的な表記というよりは、内部処理の知見もたまってくるという。 少し読んだところの特徴を抜粋。個人的なメモです。 Elixirは、moduleとfunctionに分けられる Elixirは純粋な関数型言語ではない。そのため、幾つか副作用がある関数が存在する。 データはimmutable。加工したデータは、異なるmemory locationに書き出される。ただし、shallow copyされたデータは共通の元となるデータをなるべく共有している。 booleanは true と false のatom nullabilityは無いので、 nil のatomを使う String typeは無い。binariesかlistで使う。 character listは、3-rd party製のErlangなんかが要求する時のみに使うことが良い。あとはbinary string使いましょう。 complex typeはlist、tuple、mapsだけ Range、Keyword list、HashDict、HashSetはデータシステムの元 keyword-listは値の小さな構造体で使う HashDictは、より大きなコレクションで性能を上げたい時に使おう HashSetはユニークな値の集合 & オペレータでlambdaを使おう Getting started では、 fn x -> function end を簡略化するために & を使ってましたね 粒度が結構違うメモなのですが、Elixirでの命名規則は以下の模様。 Elixirでの命名規則としての ?、! ? : true or false…More

[Elixir]Guardianでログインを固める on Phoenix

ちょっとしたWebサイトを作ろうとして、Elixirを最近触っていることもあってElixir x Phoenixで構築し始めている最近です。 その中で簡単なログイン機能を追加しようとしたところ、awesome-elixirにてGuardianなる開発途中の認証ライブラリを見つけました。開発者はRack Authenticationのwardenの開発者でもあるのですね。ほー。 試したのは、v0.5.0 Readmeを見ながら作業かなーと思っていたのですが、サンプル実装を公開していることを知り、まずはそこから動かしてみることにしました。 ただ、動かしてみるとPhoenixが0.13.1ベース。 私が今使っているのは0.15.0ベース。 …. ということで、サンプルをPhoenix 0.13.1ベースから0.15.0ベースに書き換えました。開発者の方へPRも投げたので、もしかするとマージされるかも。 変更ブランチはこちら https://github.com/KazuCocoa/phoenix_guardian/tree/upgrade_to_phoenix_015 差分はこちら https://github.com/KazuCocoa/phoenix_guardian/commit/c5bf0edf1fd64ecbf7d16ac0a45fb4f2fd10be6b 上記をcloneして以下の通りに実行すれば、Phoenix 0.15.0上でアプリを起動、ログイン試したり諸々できます。 主な修正はPhoenixの0.13.1=>0.14.0へのアップグレードガイド、0.14.0=>0.15.0へのアップグレードガイドをみるとわかるのですが、この例のChannelで使うSocket周りに破壊的な変更が入っているのと、controllerで :plug action を呼ぶ必要がなくなっているところです。 なんだかんだでこうやって簡単な例からコード追うと理解が進んで良いですね。 session管理の箇所とか、色々参考になりました。 作者が簡単な説明をこことかで説明しているので、そこをまず読んでみると良いかもしれません。あと、サンプル実装は mix phoenix.new で生成されたアプリをそのまま使っているので、差分をコードリーディングすると良さそう。 ちなみに、このサンプルアプリ、以下のようにsession情報を見ながら動作をみることができるので理解の助けになりそうです。 Rubyを継承してか?Elixir、なんかゲームみたいなライブラリ名が結構ありますね。More