t0mmy

2020年12月30日に参加

学習履歴詳細

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
    • ただし、リビジョンのリスト機能と削除機能は、カスタムメソッドで提供する
  • リソースは、カスタムメソッドを使用して、以下の手順で前のリビジョンに復元できる
    • 前のリビジョンと同じリビジョンを作成
    • 作成したリビジョンをアクティブリビジョンとしてマークする
WebAPI

2023年12月10日(日)

1.0時間