akka-httpベースでS3を実装することを完全に断念した私は今、finchの勉強をしている。この記事では、finchというのは一体何なのか?ということをすごくざっくりと説明する。
finchはfinagle-httpの上に作られた、RESTを関数的に書くことを助けるフレームワークである。
finagle-httpとは?
まずfinagle(発音: ふぃねーごー)は、protocol-agnosticな非同期RPCフレームワークである。protocol-agnosticというのは日本語でいうと、「通信プロトコルがどういうものであるかは抽象化されている」ということである。agnosticというのは、コンピュータシステムの世界ではよく使われる言葉である。もっと簡単な言葉でいうと、unwareである。
従ってfinagle-httpとは、protocol=HTTPとなっているfinagleのことである。
finchは、finagle-http、つまり、Service[Request、Response]の世界を作り出すためのフレームワークである。
型で書くと、
finagle.http.Request -> finch.Input -> finch.Endpoint -> finch.Output -> finagle.http.Response
である。ざっくりいうと、真ん中のみっつを、Endpoint#toServiceによってServiceに持ち上げる力を持つ。
toServiceを担うのは、ToService traitである。ToService traitは、ざっくりいうと、合成された(Coproductな)EndpointからServiceを作り出す力を持つ。
|
|
Endpointは型を持つ。例えば、Endpoint[A]と表記される。これは、「そのEndpointはA型の結果を返す」という意味である。例えば、Ok(“Hello World”)なるものを返すEndpointはEndpoint[String]型を持つ。
CoproductなEndpointはEndpoint[A :+: B]のような型を持つ。これは例えば、/aにアクセスすればAを返すし、/bにアクセスすればBを返すという感じである。
ToServiceはここからServiceを作る。Coproductに関するその処理は、結果的に、A => Byteを作る関数を使う。
|
|
これをEncodeResponseという。(もっと詳しくは、AをResponseにして統一することが目標で、そのためにEncodeResponseを使うということ)
|
|
ここまでの情報で、finchのユーザは、
- 小さなEndpointを作る。
- Endpointを合成する
- 各Endpointの返り値についてEncodeResponseをscopeに入れる
- toServiceを呼び出す
ことで使うことが出来る。
しかし、finch.Outputは0.9.1の現在、正格である。これは、streamingの値を返せないことを意味する。
このためのworkaroundとして、finchは、EndpointがdirectにResponseを返すことも許容する。つまり、Ok(A)ではなく、Ok(finagle.http.Response)を返せるということである。
この時、Coproductは例として、Endpoint[A :+: Response]となる。これをEndpoint[Response :+: Response]にすることが処理の概念的な説明だが、このために、以下のような関数が提供されている。
|
|
まとめる。
この数日間、finagle/finchを調査している。簡単なRESTサーバは実装出来ることが分かったが、S3をきれいに(もちろん高性能に)実装出来るかは、もう少し検討が必要そうだ。
finchは、Gitterチャンネルがあり、ここで質問すれば分からないことも分かるようになる。(しかし主要開発者の人は頭が良すぎるのか、読めば簡単に分かるくらいの感じで来る。しかし、コードを見て分かるとおり、高度に関数的であり、shapelessという魔物も使っており、明らかに簡単には読めない)
finchは0.9.1で、1.0への着陸準備に入っているライブラリであり、機能としては揃っている印象がある。設計としては、sprayに近く(shapelessを使ってる点もね)、sprayのユーザであれば拒否反応は比較的少ないはずだ。ただし、関数的な書き方は完全に強制される。ドキュメントが一応あるので読むといい。モナドがどうとかいうことばかり書いてあるから。