
t0mmy
学習履歴詳細
API デザインパターン 28章 リソースリビジョン 読了
やったこと
- API デザインパターン 28章 リソースリビジョン 読了
学んだこと
ポイント
- リビジョン機能とは何か
- どうやって過去の状態に戻るか
- リビジョンを作成する方法
- リビジョンを操作する方法
子リソースをもつリソース(つまり親リソース)のリビジョンの扱い
学び
リビジョン機能とは、リソースを過去の状態に戻す機能
リソースに、リビジョンを一意に識別できる 識別子を付与する
リビジョンの作成方法には、暗黙的な作成と、明示的な作成の二つがある
- 暗黙的な作成では、何らかのイベントを条件に、API側で自動的にリビジョンを作成する
- 明示的な作成では、リビジョンを作成するカスタムメソッドを提供し、利用者の判断でリビジョンを作成してもらう
リビジョンの操作
- リビジョン取得機能は、標準の
GET
メソッドを拡張する形で提供する - リビジョンの復元、削除機能は、カスタムメソッドにて提供する
- リビジョンの復元は、復元したいリビジョンのリソースを、最新のリビジョンとして新規作成することで実現する
- 復元の際、リソースの履歴を削除したり変更したりしてはならない
- リビジョン取得機能は、標準の
ビジネス要求次第では、子リソースもリビジョン管理対象に含める
- ただし、APIの複雑化や、より多くのストレージ容量が必要になることを覚悟する
- 親リソースには、リビジョン機能を提供しないという選択肢もあり
- 言い換えると、子リソースを持たない独立しているリソースのみリビジョン機能を提供する
メモ
基本的にリソースは、最新の状態のみ提供する。
しかし、状況によっては、過去の状態のリソースが必要になることもある。
本章では、リソースを、以前のリビジョンにロールバック可能にする手段を見ていく。
これまでのAPIでは、リソースの過去の状態は考慮しなかった。
過去のリソースの状態を扱うと、リソースの履歴を時系列で見ることが出来る。
これは、利用者にとってメリットになり得る。
概要
リソースの過去の状態を表現するために、「リソースリビジョン」という概念を利用する。
- リソースリビジョン : 一意の識別子と作成時のタイムスタンプでラベル付けられた、リソースのスナップショット
リソースリビジョンは、リソースに以下二つのフィールドを追加することで実現可能。
- リビジョン識別子
- スナップショットが取得されたときのタイムスタンプ
実装
リビジョン識別子
リビジョン識別子は、一般的な識別子と同じくランダムな文字列を使用する。
以下の選択肢はあまり考えられない。
- 連番
- リビジョンを削除すると、1,2,4 のように歯抜けとなり、利用者に混乱を招く
- タイムスタンプ
- 稀に、タイムスタンプ(≒識別子)が衝突する可能性がある
リビジョンを作成する
リビジョンは、暗黙的に作成するか、明示的に作成するか、選択することが出来る。
リビジョンの生成方法は、API全体で一貫していることが重要。
暗黙的なリビジョン
API側で、特定のイベントに合わせて、自動的にリビジョンを作成する戦略。
- リソースのデータが更新されたとき
cron
のような定期実行- 特定のマイルストーン
- 特定のフィールドが更新されたとき
- 特定のカスタムメソッドが実行されたとき
- など
ビジネスの要求に応じて、リビジョンを作成する最適なタイミングを模索すること。
リビジョンは、減らす方向よりも増やす方向をお勧めする。
明示的なリビジョン
リビジョンを作成できるカスタムメソッドを用意し、利用者が明示的に作成できるようにする戦略。
リビジョンの作成は、API利用者が制御できる(責務も負う)。
特定のリビジョンを取得する
標準の get
メソッドを拡張して、過去のリビジョンを指定してリソースを取得する手段を提供する。
Messageリソースのリビジョン 1234
を指定する例
GET chatRooms/1/messages/2@1234
リビジョンを指定しない場合、レスポンスのIDフィールドにはリビジョン情報を含めない( revisionId
フィールドに、リビジョン情報を含める)。
リビジョンを指定した場合、レスポンスのIDフィールドにはリビジョン情報を含める( revisionId
フィールドに、リビジョン情報を含める)。
方針としては、リクエスト時に指定するIDと、レスポンスのIDを一致させること。
リビジョンのリストを取得する
リソースのリビジョン一覧を返す、カスタムメソッドを提供する。
以前のリビジョンを復元する
restoreRevision
カスタムメソッドを使用して、リソースを、ある過去の状態に戻す。
指定されたリビジョンのリソースをコピーし、最新のリビジョンとして新規作成することで実現する。
この機能では、リソースの履歴を削除したり変更してはならない。
リビジョンを削除する
特定のリビジョンに、誤って機密データや機微な情報を含めてしまった場合に使用する。
リソースのリビジョンを削除する、カスタムメソッドを提供する。
この時、標準の delete
メソッドを拡張する形で実装してはならない。
- 標準の
delete
メソッドはリソースの削除を目的としており、 リビジョンを削除する機能とは区別する必要がある- 区別しないと、利用者が混乱する
- 削除は危険な操作のため、混乱をできるだけ避けたい
現在(≒最新)のリビジョンを削除する場合、412 エラー、またはそれに相当するエラーを返す。
- これにより、一つしか存在しないリビジョンを削除するケースも同時に解決できる
また、リビジョンに論理削除の仕組みを提供するべきではない。
子リソースを処理する
子リソースをもつリソース(つまり親リソース)のリビジョンを作成する場合、子リソースをどう扱うか。
正解はなく、ビジネス要件次第。
- 「子リソースごとまとめてリビジョンに含める」というビジネス要件があれば、子リソースごと扱うよう拡張することになる
- 処理が複雑化し、より多くのストレージが必要になるのは間違いない
- 親リソースはリビジョン機能の対象外として定義するのも有り
トレードオフ
リビジョン機能の提供と、APIの複雑化のトレードオフ。
特に、階層を考慮したストレージは、より複雑で、多くのストレージ容量を要する。
扱うこと
- リソースのリビジョンを、時間の経過とともに変更しながら安全に保存する方法
- 個々のリビジョンを識別する方法
- 暗黙的または明示的にリビジョンを作成する方法
- 利用可能なリビジョンをリストアップし、特定のリビジョンを取得する方法
- 前のリビジョンに戻す方法
- リビジョン指定可能なリソースの子リソースをどうすべきか
まとめ
- リソースのリビジョンは、リソースのスナップショットとして機能する
- リビジョンの識別子は、他のリソース同様ランダムな値を用いる
- タイムスタンプや数字が増えるだけの値を用いてはならない
- リビジョンは、暗黙的、あるいは明示的に作成できる
- 暗黙的の例 : リソースが変更されるたび
- 明示的な例 : 利用者からの要求に応じて
- リソースのリビジョンを指定する場合、
@
の後ろにリビジョン識別子を指定するとよい- 例)
GET /chatRooms/1234@5678
- ただし、リビジョンのリスト機能と削除機能は、カスタムメソッドで提供する
- 例)
- リソースは、カスタムメソッドを使用して、以下の手順で前のリビジョンに復元できる
- 前のリビジョンと同じリビジョンを作成
- 作成したリビジョンをアクティブリビジョンとしてマークする
2023年12月10日(日)
1.0時間