purescript-conveyorにBatch operationの機能を足した
追記
本記事のパッケージは現在メンテされておりません。
サーバー向けパッケージは再実装されたものがこちらにあります。
はじめに
年が明けてますが、PureScript Advent Calendar 2017 - Qiitaの21日目の記事にしてしまいます。
前回、PureScriptでAPIサーバー用のパッケージつくってみた - oreshinyaのブログというようなAPIフレームワークをつくったことを記事にしましたが、 このフレームワークにBatch opearationの機能を足しました。 また、その際に全面的にソースコードを書き直したため、変更点を書きます。
Batch operationってなに
複数のエンドポイントを1回のリクエストで実行する機能です。
複雑なアプリケーションになると、ひとつの画面に必要なデータが非常に多岐に渡ります。 そのような状況下の中、ひとつのAPIで色々な多くのデータを返すか、単機能なAPIを複数回叩くかという選択をすることを最初に考えるかと思います。 このことに対して、何も対策的な仕組みを入れない場合、前者の場合はUIによりすぎたメンテのしにくいAPIによっていくし、後者は何度もリクエスト往復するのでとても時間がかかります。
こういったことに対して、数年前からBFFという概念が公に出るようになりました。 ただ、気合の入ったBFFをしなくても、単純なbatch operationだけでもあると、経験上、わりと快適になるため、自分で使うためのライトユースとして、この機能を足しました。
Servable
のメンバの型が変わった
変更コミットたちです。
Batch operationを入れるために、Servable
のメンバの型を変えました。
以前の型はserve :: c -> s -> Request -> Response -> String -> Maybe (Eff (http :: HTTP | e) Unit)
で、新しい型はserve :: s -> c -> RawData -> Aff e Responder
になります。
大きな変更点は、返り値の型となります。
以前の型では、serve
の実行文脈の中でレスポンスをクライアントに返すことを期待した型付けでしたが、新しい型では、serve
の文脈でレスポンスとなるデータをつくって返すだけになっています。
新しい型にしたことによって、batch operationの実装は、serve
を指定された各エンドポイントのパラメータの配列を用いて、traverse
して複数のレスポンスをまとめればいいだけになりました。
その他の変更
- Request bodyのdecodeに関しては、purescript-simple-jsonに依存するように変更して、
Readable
型クラスを削除した Respondable
型クラスの全面的な書き直しHandler
を削除して、普通にAff
で動くように変更した- 関数の引数の順番とか数とか引数そのものを地味に変えた
- まぁ、なんか色々書き直した
まだ改善できるところはある
現状は、各エンドポイントを順番に処理してるだけなので、concurrentに実行できるようにするとよりよさそうです。
使い方
Servable
のインスタンスをBatch
型で包んで初期化すれば、OKです。
リポジトリのサンプルコードとほぼコピペですが、以下のような感じで初期化します。
runWithContext config 777 $ Batch { contextTest, errorTest, rawDataTest, createBlog }
以下のようなデータをrequestのbodyとして、POST /batch
におくりつけると、
[ {"path": "errorTest"}, {"path": "contextTest"}, {"path": "createBlog", "body": { "title": "hoge", "content": "うんち in batch" }}, {"path": "rawDataTest", "body": "ろーでーた"} ]
以下のようにかえってきます。
[ { "contentType": "application/json", "code": 500, "body": { "messages": [ "Internal server error ;)" ] } }, { "contentType": "application/json", "code": 200, "body": { "yours": "777" } }, { "contentType": "application/json", "code": 200, "body": { "fuck": "title: hoge, content: うんち in batch requested." } }, { "contentType": "application/json", "code": 200, "body": { "yours": "\"ろーでーた\"" } } ]