といいつつ、ひとつだけ理解できないというか、納得できないところが。トランザクションのところがなんだかRESTっぽくないのがすごく気になる
Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESSプラスシリーズ)(山本 陽平) - ただのにっき(2010-04-23)
「Web を支える技術」は自分もとてもいい本だと思う (教科書としてすばらしいし復習用としても読みやすいのでイイ) のですが、トランザクションの所だけは分かりづらいなと感じました。その原因は、atomic transaction で解決できる課題を例として使っているという点と、トランザクションと更新クエリのレイヤ分割がされていない、という2つの点によるものではないでしょうか。
HTTP 上でトランザクションを表現する必要があるケースのほとんどは、atomic transaction ではなく、2相コミットもしくは long-running transaction を行う場合だと思います。
たとえば、HTTP 上で2層コミットを行っているシステムの代表例としては、おさいふケータイのチャージ機能が挙げられます (あれって HTTPS ですよね?)。また、たとえば、数量に限定がある商品を課金代行サービスを使って販売する場合等においては、long-running transaction が必須になります。
なので、トランザクションレイヤを RESTful に表現する手法は理解しておいて損がないものだと思います。具体的には、
- トランザクションの開始は POST を使ったトランザクションリソースの生成
- トランザクション開始後は POST ではなく PUT を使い、クライアントがリクエスト ID を指定することで、ネットワーク障害への耐性を確保
- トランザクションのコミットも再送可能じゃないと困るので PUT
- コミットの返り値を確認してからトランザクションリソースを DELETE
といったあたりが基本になると思います。
以下、具体例として、「アライブドアチケット」というチケット販売サイトから、ミュージカル「夜のhidek様」のチケット (2010年5月24日の公演) を購入する例を示します。支払いには Yappo! ペイメントを利用します。
まずは、残席があるか確認します。
GET http://ticket.alivedoor.com/musical/20100524/夜のhidek様/seats-left HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{
"seats-left": 11
}
「夜のhidek様」は、歌舞伎町でも大人気な、あの往年のアイドルが主演する人気ミュージカル。残席が少ないです。今すぐチケットを買わないといけません。トランザクションリソースを生成して、トランザクションを開始します。
POST https://ticket.alivedoor.com/buy HTTP/1.1
Content-Length: 0
HTTP/1.1 201 Created
Location: https://ticket.alivedoor.com/buy/934085
...
次に、座席を確保します。サーバは席が確保できれば「201 Created」を、既に満席になっていれば「409 Conflict」を返します。
PUT https://ticket.alivedoor.com/buy/934085/1 HTTP/1.1
Content-Type: application/json
{
"url" : "http://ticket.alivedoor.com/musical/20100524/夜のhidek様",
"seats" : 2
}
HTTP/1.1 201 Created
...
座席が確保できたら、支払い金額を確認します。
GET https://ticket.alivedoor.com/buy/934085 HTTP/1.1
HTTP/1.1 200 OK
Content-Type: application/json
{
"amount": "10000",
"currency": "JPY"
}
次に、クライアントは Yappo! ペイメントを使って、アライブドアチケットの口座に指定された金額を振り込みます。振込が完了すると、Yappo! ペイメントは振込IDを返すので、その振込IDを指定してトランザクションをコミットします。
PUT https://ticket.alivedoor.com/buy/934085/commit HTTP/1.1
Conetnt-Type: application/json
{
"payment_id" : "https://payment.yappo.jp/paymentid/02394895923408904930"
}
HTTP/1.1 200 OK
...
「200 OK」が返ってきたので、支払が完了し、取引が成立したことがわかります (失敗した場合は「409 Conflict」が返ってくるでしょう)。最後にトランザクションリソースを削除します。
DELETE https://ticket.alivedoor.com/buy/934085 HTTP/1.1
HTTP/1.1 200 OK
...
以上のような流れになると思います。「夜のhidek様」言いたかっただけ (ry
処理の対象となるリソース (上の例では http://ticket.alivedoor.com/musical/20100524/夜のhidek様) が、トランザクション中の Request-URI に含まれていないのが気持ち悪い、という意見もあるかもしれません。ですが自分は、トランザクションリソースを使う場合は、HTTP はトランザクション処理に専念、HTTP 上のペイロードで処理対象のリソースを表現する方が、レイヤが分かれるので良いと考えます。
Recent Comments