1

リストの更新を定期的に受け取る Web サービスを設計しています。この時点で、リストは単一のエンティティ ( /lists/myList) または多くのリソースを持つ実際のコレクション( ) としてモデル化でき/lists/myList/entries/<ID>ます。リストは大きく (数百万のエントリ)、更新は小規模です (多くの場合、10 未満の変更)。

クライアントは配布する Web サービスの URL とリストを取得します。例:

次に、設定どおりにリストと更新をプッシュします。Web サービス URL の背後に何らかのデータベースが存在する可能性がありますが、不明です。

私は調査してきましたが、JSON パッチ形式を使用した HTTP PATCH が最良のアプローチであるようです。

コンテキストと例: 各リストには、識別名、優先順位、および何百万ものエントリがあります。各エントリには、ID (クライアントによって決定される) といくつかのオプションの属性があります。優先度 1 と 2 つのリスト エントリを持つリスト "requiredItems" を作成する例:

PUT /lists/requiredItems
Content-Type: application/json


{
  "priority": 1,
  "entries": {
    "1": {
      "color": "red",
      "validUntil": "2016-06-29T08:45:00Z"
    },
    "2": {
      "country": "US"
    }
  }
}

更新の場合、クライアントはまずサーバー上でリストがどのように見えるかを知る必要があります。このために、リスト エンティティにプロパティ「リビジョン」を追加します。

次に、この属性を照会します。

GET /lists/requiredItems?property=revision

次に、クライアントは、サーバー上のリビジョンとクライアントが認識している最新のリビジョンとの間で何を変更する必要があるかを確認し、JSON パッチを作成します。例:

PATCH /list/requiredItems
Content-Type: application/json-patch+json

[
  { "op": "test", "path": "revision", "value": 3 },
  { "op": "add", "path": "entries/3", "value": { "color": "blue" } },
  { "op": "remove", "path": "entries/1" },
  { "op": "remove", "path": "entries/2/country" },
  { "op": "add", "path": "entries/2/color", "value": "green" },
  { "op": "replace", "path": "revision", "value": 10 }
]

質問:

  • このアプローチには、あまり使用されない HTTP 動詞 PATCH が原因で、クライアント サポートがわずかに少ないという欠点があります。HTTP の互換性 (冪等性など) を犠牲にすることなく、より互換性のあるアプローチはありますか?
  • 個々のリスト エントリを個別のリソースとしてモデル化し、PUTandをDELETE(おそらくETagand/orと共にIf-Match) 使用することはオプションのように思えます ( PUT /lists/requiredItems/entries/3, DELETE /lists/requiredItems/entries/1 PUT /lists/requiredItems/revision)。しかし、更新チェーンの途中でネットワークが切断されたときに、これらすべての操作が確実に適用されるようにするにはどうすればよいでしょうか? HTTP PATCH は複数のリソースで動作できますか?
  • リストを「バージョン管理」するためのより良い方法はありますか?おそらく暗黙のうちに、リストの更新方法も改善されますか? クライアントがリビジョン番号を決定することに注意してください。
  • でリビジョン番号を照会するのは正しいGET /lists/requiredItems?property=revisionですか? のような別のリソースにする必要があり/lists/requiredItems/revisionますか?別のリソースにする必要がある場合、アトミックに更新するにはどうすればよいですか (つまり、リストとリビジョンの両方が更新されるか、両方が更新されないか)?
  • JSON パッチで最初にリビジョン値をテストしてから、同じパッチで3更新することはできますか?10
4

2 に答える 2

1

私自身の質問に答えます。私の最初の箇条書きは意見に基づいている可能性があり、指摘されているように、1 つの投稿で多くの質問をしました。それにもかかわらず、他の人 ( VoiceOfUnreason ) と私自身の追加調査によって回答された内容の要約を次に示します。

ETag は、HTTP のリソース「ハッシュ」です。これらを If-Match ヘッダーと組み合わせて、バージョン管理システムを持つことができます。ただし、通常、ETag ヘッダーは、作成 (PUT) または更新 (POST/PATCH) されるリソースの ETag を宣言するために使用されません。通常、リソースを格納するサーバーが ETag を決定します。これを明示的に禁止するものは見つかりませんでしたが、多くの実装では、サーバーが ETag を決定し、PUT または PATCH が提供されたときに混乱すると想定する場合があります。

別のリビジョン リソースは、バージョン管理のための ETag の有効な代替手段です。このリソースは、リビジョンであるリソースと同時に更新する必要があります。

トランザクション自体を ReST リソースとしてモデル化しない限り、HTTP レベルでコミット/ロールバック トランザクションを持つことは意味的に強制できません。

ただし、PATCH の一部のプロパティを使用すると、これを使用できます。

  • HTTP PATCH はアトミックである必要があり、複数のリソースで動作できます。RFC5789 :
    • サーバーは、変更のセット全体をアトミックに適用する必要があり、(たとえば、この操作中の GET への応答で) 部分的に変更された表現を提供してはなりません。パッチ ドキュメント全体を正常に適用できない場合、サーバーは変更を適用してはなりません。
    • PATCH メソッドは、Request-URI によって識別されるリソースに影響を与えます。また、他のリソースに副作用がある場合もあります。つまり、PATCH を適用することで、新しいリソースを作成したり、既存のリソースを変更したりできます。PATCH は安全でも冪等でもない
  • JSON PATCH は、複数のリソースに対する複数の操作で構成することができ、すべてを適用するか、何も適用しない必要があるため、暗黙的なトランザクションになります。RFC6902 :
    操作は、配列に表示される順序で順次適用されます。

したがって、リビジョンを個別のリソースとしてモデル化し、同時に更新することができます。現在のリビジョンのクエリは、単純な GET です。トランザクションのコミットは、最初にリビジョンのテスト、次にリソースに対する操作、最後にリビジョン リソースを更新する操作を含む単一の PATCH 要求です。

サーバーは引き続き、メイン リソースの ETag としてリビジョンを公開することを選択できます。

于 2016-07-17T13:44:13.267 に答える