単一の障害が一括操作に失敗する必要がありますか?


11

私が取り組んでいるAPIには、IDの配列を受け入れる一括削除操作があります:

["1000", ..., "2000"]

削除操作は自由に実装できたので、すべてをトランザクション対応にすることにしました。つまり、1つのIDが無効な場合、リクエスト全体が失敗します。これを厳密モードと呼びます。

try{
savepoint = conn.setSavepoint();

for(id : IDs)
    if( !deleteItem(id) ){
        conn.rollback(savepoint);
        sendHttp400AndBeDoneWithIt();
        return;
    }

conn.commit();
}

別の方法(ソフトウェアスイートの別の場所で実装)は、バックエンドでできることを実行し、アレイでエラーを報告することです。ソフトウェアのその部分はより少ないリクエストを扱うので、理論的にはレスポンスが巨大な配列になることはありません。


リソース不足のサーバーで発生した最近のバグにより、コードを再度確認し、今は元の決定に疑問を抱いていますが、今回はベストプラクティスではなくビジネスニーズによって動機付けられています。たとえば、リクエスト全体が失敗した場合、ユーザーは再試行する必要がありますが、いくつかのアイテムが削除された場合、ユーザーはアクションを終了し、管理者に残りの作業を依頼できます(バグの修正に取り組んでいる間) !)。これが許容モードになります。

私はこの問題に関するガイダンスをオンラインで探してみましたが、手ぶらで出てきました。だから私はあなたに来ます:この種のバルク操作で最も期待されることは何ですか?もっと厳しくするべきですか、それとももっと寛容にすべきですか?


9
場合によります。削除する必要のあるものを削除しない場合の費用はいくらですか?(コストは、不正なデータ、頭痛、望ましくない動作、管理者がそれを修正するのにかかる時間などとして定義されています。)それは受け入れられますか?あなたがすべてを失敗しないという結果で生きることができるならば、それのために行きなさい。問題が多すぎる場合は、そうしないでください。ソフトウェアと結果を知っているので、判断を下す必要があります。
Becuzz

1
@Becuzzコストは、ユーザーが1つまたは2つの残り物に気づき、それに関するチケットを開くことです。現在の状況は「omg delete is broken」です。幸いなことに、ユーザーは廊下にいるので、今回はあまり問題になりません。要点は、可能な限り正しいことをするのが好きであり、10年以上のコードベースがあれば、神はいくつかのことを正しく行うことができることを知っている
-rath

これは、スケーラビリティが必要かどうかにも依存すると思います。多くのIDを取得するつもりがない場合は、それほど重要ではありません。100万個以上のIDを取得しようとしている場合、またはそれ以上の場合、それが発生しないことを完全に確信していない場合、1つの無効なIDのために完全にリセットするために、IDの削除に1時間費やすことができます。
imnota4

1
@ imnota4私が考慮していなかった素晴らしい点。UIはリクエストを最大約250に制限しますが、バックエンドには制限がありません。コメントを回答として再投稿してください。
-rath

1
許可モードでは、IDのすべてのスタックで失敗を再現する必要がないため、管理者の仕事も簡単になります。また、各エラーの原因を応答で通知することも役立ちます。原因を見ると、最終ユーザーが「omg delete is broken」チケットなしで問題を解決できる可能性があります。
ライヴ

回答:


9

削除エンドポイントの「厳密な」バージョンまたは「適切な」バージョンを実行しても問題ありませんが、何が起こったのかをユーザーに明確に伝える必要があります。

このエンドポイントで削除アクションを実行しています。可能性のあるDELETE /resource/bulk/ものまたは類似したもの。私は好き嫌いはありません。ここで重要なのは、厳格であろうと良かろうと決心しても、何が起こったのかを正確に報告する必要があるということです。

たとえば、使用したAPIには、DELETE /v1/student/バルクIDを受け入れるエンドポイントがありました。テスト中に定期的にリクエストを送信し、200応答を取得し、すべてが正常であると仮定しますが、後でリストの全員がまだデータベースにある(非アクティブに設定されている)か、エラーのために実際に削除されていないことがわかりますGET /v1/student予期していなかったデータを取り戻したため、将来の呼び出しを台無しにしました。

これに対する解決策は、削除されていないIDを含む本文を応答に追加する後の更新で提供されました。これは-私の知る限り-一種のベストプラクティスです。

結論として、何をするにしても、エンドユーザーに何が起こっているのか、そしておそらく何が起こっているのかを知らせる方法を提供するようにしてください。IE、厳密な形式を選択した場合、応答は次のようになります400 - DELETE failed on ID 1221 not found。「素敵な」バージョンを選択した場合、それは可能性があります207 - {message:"failed, some ids not deleted", failedids:{1221, 23432, 1224}}(私の悪いjsonフォーマット)。

幸運を!


6
207 Multi-Statusその部分的な障害対応に適切である可能性があります
リチャードティングル

1
行くぞ!実際に思い出せませんでした!実際に標準に達しているので、先に進み、それで答えを更新します。
アダムウェルズ

2

厳格かつ寛容でなければなりません。

通常、バルクロードは2段階に分けられます。

  • 検証
  • 読み込み中

検証フェーズでは、すべてのレコードが厳密に調べられ、データ仕様の要件を満たしていることを確認します。数秒で数千のレコードを簡単に検査できます。有効なレコードはロードされる新しいファイルに配置され、無効なレコードにはフラグが付けられて削除され、通常は別のファイル(スキップファイル)に配置されます。その後、検証に失敗したレコードに対して通知が送信されるため、トラブルシューティングの目的で検査および診断できます。

データが検証されると、ロードされます。通常、長時間実行されるトランザクションを回避するのに十分な大きさである場合、または障害が発生した場合に回復しやすくなる場合、バッチでロードされます。バッチサイズは、データセットの大きさに依存します。レコードが数千個しかない場合、1つのバッチで問題ありません。ここでは、失敗を許容することができますが、失敗したバッチしきい値を設定して操作全体を停止することができます。[N]個のバッチが失敗すると、サーバー全体が停止した場合など、操作全体が停止する可能性があります。通常、データはすでに検証されているため、この時点でエラーは発生しませんが、環境の問題などが原因で発生した場合は、失敗したバッチをリロードするだけです。これにより、リカバリが少し簡単になります。


DBの値に対してIDを検証するのではなく、それらを削除して、それがどうなるかを確認しようとします。そうしないと、永遠にかかります。N個の失敗後に
中止する

2

単一の障害が一括操作に失敗する必要がありますか?

これに対する標準的な答えはありません。ユーザーのニーズと結果を調査し、トレードオフを評価する必要があります。OPは必要な情報の一部を提供しましたが、次のように進めます。

質問1:「個々の削除が失敗した場合のユーザーへの結果はどうなりますか?」

答えは、設計/実装された動作の残りを駆動する必要があります。

OPのように述べられているように、ユーザーが例外に気づいてトラブルチケットを開くだけで、それ以外の場合は影響を受けない場合(削除されていないアイテムは後続のタスクに影響しません)、自動通知で寛容になりますあなたへ。

ユーザーが続行する前に、失敗した削除を解決する必要がある場合は、明らかにstrictの方が望ましいです。

ユーザーにオプション(たとえば、基本的に、デフォルトとしてstrictまたはpermissiveを使用した基本的に失敗を無視するフラグ)を与えることは、最もユーザーフレンドリーなアプローチです。

質問2:「まだデー​​タストアにある削除されていないアイテムを使用して後続のタスクが実行される場合、データの一貫性/一貫性の問題はありますか?」

繰り返しになりますが、答えは最良の設計/動作を駆動します。はい->厳密、いいえ->許容、多分->厳密またはユーザー選択(特に、結果を正確に判断するためにユーザーを信頼できる場合)。


0

これは、スケーラビリティが必要かどうかによって決まると思います。多くのIDを取得するつもりがない場合は、それほど重要ではありません。100万個以上のIDを取得しようとしている場合、またはそれ以上の場合、それが発生しないことを完全に確信していない場合、1つの無効なIDのために完全にリセットするために、IDの削除に1時間費やすことができます。


-1

ここで重要な点は、大量のものを削除することの意味です。

これらのIDは何らかの形で論理的に関連していますか、それとも単に利便性/パフォーマンス-これらのバッチグループ化ですか?

どういうわけか、大まかに、接続の場合、私は行くだろうstrict。それが単なるバッチモードである場合(たとえば、ユーザーが最後の作業時間に「保存」をクリックし、それからのみバッチが送信される場合)、そのpermissiveバージョンを使用します。

他の答えが示すように:いずれにしても、「ユーザー」に何が起こったかを正確に伝えてください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.