2010年1月11日月曜日

[REST][読書メモ] 変化するURI, 非同期処理

間違って消してしまったので再投稿・・・

==


RESTful Webサービス』を読んでいて、ちょうど今突き当たっている問題のヒントを発見したのでふたたびメモ。注意して読んだつもりだけど、初心者なので誤解があるかも。

ひとつは、PUT操作でリソース状態を変更すると、URIが変わるケース。 たとえばユーザーアカウント名を変えられるシステムで、ユーザーリソースURIにアカウント名が含まれている場合。アカウント名を変更するとURIが変わってしまう。

これに似た要求があったとき、なんだか私はとても違和感をおぼえた。まぁ、一意でさえあれば変化しようと問題ないのかな・・・と若干もやもやしつつ実装したんだけど。

このあたりの議論が "8.13 永続的なURIと読み取り可能なURI"にあった。

URIの構築の仕方には2つのポリシーがある。
①「永続的なURI」の立場
URIは、変化する現実とは関わりをもたない単なる記号であるべき。(Tim Berners-Lee の言葉で「URIの不透明性」というらしい。)
ユーザアカウントでいうと、URIはDBもしくはアプリが生成する(一般にはランダムな)Global Unique IDから構築される。なので一度生成されたら、ユーザ情報がどう変化しようがURIは同じ。
②「変化するURI」の立場
URIは、意味をもち、ユーザインタフェースとしてはたらくべき。(Jacob Nielsen という人が提唱しているらしい。)この立場に立つと、(意味をもつURIはリソース状態を含んでいるために)、リソース状態が変化したら、それに応じてURIも変化する場合がある。
ユーザアカウントでいうと、URIは人が理解できるアカウント名から構築される。アカウント名は一意だが変化する可能性があり、当然URIも変化する。

そして筆者は(どちらが正しいか、という結論は留保しつつ)一貫して②の立場に立つ。
これをROAの振る舞いで言い換えると、URIを変化させるようなPUTリクエストに対するレスポンスは、 「レスポンスコード301(Moved Permanently)を送信し、ユーザーの新しいURIを Location ヘッダーに設定する必要がある(P206)」 とのこと。

私が感じた違和感は、①のポリシーをどこかで刷り込まれていたことにあるらしい。もちろん意識してなかったけど。

なるほどなぁ。

で、ここから先はパーマネントURI派の私の勝手な考えなのだけれど、インタフェースとしての(意味のある、変化する)URIを提供するのはいいとして、それと別にパーマネントなURIもやっぱり必要ではないかと。若干手間が増えるけど、2つのURIが同じものを指すのは別にいいわけだし、相互リンクだって張れるし。
いま「火星」という名前で呼ばれている惑星は、名前が「M42星」に変わろうが「地球Jr.」に変わろうがものとしては同じわけで、状態とともにころころ変わるURIとは別に、終始一貫したIDとしてのURIを持つのが自然な気がする。
うーんでも別にリソースは抽象概念でもいいわけだから、具体的な物体としての火星(と呼ばれているもの)でなく、「火星」という名前と物理的な惑星をひっくるめたリソースなんだよ、ともいえるのか。
だんだん概念遊びになってきたのでやめよう。。。 抽象論苦手^^;


あともうひとつは、非同期処理。
作成・更新にとても時間のかかるリソース(具体的には大きなバイナリファイル)があって、概念的にはPUTで問題ないんだけど、現実的には処理が終わるまで待ってられない(というかタイムアウトする)、というのでどうしようかと思っていた。

こんなケースが "8.8.2 非同期処理" に書かれていた。
考え方は単純で、終わらないのは仕方ないんだから、とりあえずリクエストを受け付けた旨だけクライアントに返せばいいじゃん、というもの。レスポンスコードは202(Accepted)を使う。受け付けた非同期処理の進行状況は、リソースとして提供する。
もう少し具体的には、
  1. クライアントは非同期処理受付けURIにPOSTリクエストを送る
  2. サーバは新たに「ジョブ」リソースを作成して、そのURIとともにレスポンスコード202を返す
  3. クライアントは、処理の状況を知るために指定された「ジョブ」のURIにGETリクエストを送る
  4. 処理が完了したら、その「ジョブ」リソースは削除していい(必要なら残す)
という手順を踏む。
進行状況をどう監視するか、「ジョブ」リソースをどう更新するか、など実装上クリアしなければいけない問題はたぶんいくつもあるけれど、方針はとてもすっきりしている。うまくROAのリソース操作に落とし込んだものだなぁと、なんだか狐につままれた感がする。

なお、トランザクションも非同期処理と同じ考え方で説明されている。非同期処理と違うのは、新たに割り当てられた「トランザクション」リソースに対して、クライアントがPUTメソッドを送る点。この場合、クライアントは能動的にリソース状態を更新することになる。もちろん「コミット」「ロールバック」命令もPUTで送る。これ、実際に実装する勇者?はいるんだろうか。

定義や理論にも紙幅を割いてるけど、こういう現実的な問題への対処法がほかにも書かれているので、RESTfulなサービスに関わっている人はやっぱり必読だと思う。
5、6章の例は、読んでてわくわくしたしw

0 件のコメント:

コメントを投稿