Resource versioning (ETags)

gdataはETagによるバージョン管理(排他制御)を行うことができるProtocol Reference - Google Data Protocol - Google Code。正確には参照時の更新チェックと更新時の排他制御に利用できる。参照時の更新チェックはIf-None-MatchヘッダとETagによる方法であり、よくHTMLのクライアントキャッシュに利用されているやつでETagにマッチしなければコンテンツを返すという挙動である。ただし、一般的にはIf-Modified-Sinceヘッダとタイムスタンプを利用するケースの方が多い気がする。更新はgdata特有なのかRESTで一般的なのか不明だが、If-MatchヘッダとETagを併用することで、マッチすれば更新するという挙動にしている。なお、タイムスタンプによる(If-Modified-Since)による制御はサポートされていないようだドキュメントに記述がない。もしかしたらサポートしているのかもしれない。

gdataではweak ETagとstrong ETagという二種類のETag用意しており、strong ETagは排他制御用のETagである。デフォルトはweak ETagであり、更新処理時にweak ETagを指定すると排他制御が効かなかったり、エラーが返ってきたりするようだ。挙動に関する記述がドキュメントにおいて一貫していない。更新処理ではエラーになって、削除処理ではエラーとせずに排他制御なしで削除するように書かれていた。なお、strong ETagをサポートしないentryに関してはそもそも排他制御ができないことになる。

排他制御は更新処理と削除処理に分けられる。どちらも利用手順に差はないようだ。まず、排他制御をかけたい場合はIf-MatchヘッダとETagを併用する。ただし、If-Matchヘッダを指定しない場合は、要素のgd:etagの値を利用してくれるようだ。あと、強制的に更新したい場合は If-Match: * を指定すればよい。唯一の違いはweak ETagの扱いで、If-Matchヘッダにweak ETagを指定した場合に更新処理はエラーにするようだが削除処理はエラーとせずに必ず削除する仕様のようだ。あと、削除処理をする場合は、まず検索して最新のETagを取得するようにとの指針が明記されていた。

今後検証をする上で確認するポイントは以下が挙げられる。

  • ETagの値。例えばCellEntryの場合にそれぞれ別の値となっているのか。同じ値であった場合、個別の排他制御が出来ないことになる。SpreadsheetsDataAPIのドキュメントに記述があったような気もする。
  • CellEntryで値の存在しないセルに更新をかける場合、ETagが存在しないため排他制御ができない。DBの行挿入時の排他制御と同じ問題が起こるが、こちらはロックをかけてくれない。厳密に管理したい場合あらかじめ半角空白を入れておくような対処法が必要になるのだろうか。
  • SpreadsheetServiceのHTTPヘッダは追加のみで削除が本当に削除できないのかチェックする。そもそも、SpreadsheetServiceそのものはFacadeのような位置づけでnewしただけではリクエストを投げないのだから、認証情報を引き回せれば毎回newしてもいい気がする。あと、アプリケーション名か。そもそもWebアプリケーション(マルチ・ユーザ)環境でも使えるように作ってあるはずなのだから、HTTPヘッダを一か所でしか指定できないのはおかしい気がする。ソースをちゃんと見た方がよさそう。
  • バッチリクエストにもETagに関する記述があったのでチェックしておこう。