外部送信APIでは、一時障害時の自動retryをやめました。タイムアウトや接続断のように見える状況ほど、二重送信と受付不明が起きやすいです。
前提は、受付IDなど「受け付けた証拠」が返りうる外部送信API一般です。特定ベンダー名は出しません。
シリーズ「Zoho WidgetとLambdaの連携」の第4回です。
前回: Zoho WidgetとLambdaの連携 第3回:PDFプレビューと直送保存の分離
次回: Zoho WidgetとLambdaの連携 第5回:CRM上の進行管理と結果確認Poller
この記事の内容
- 受付と最終成功の違い
- 外部送信で自動retryしない理由
- 未受付・受付不明・人手確認での次アクションの違い
受付と最終成功
| 用語 | 意味 |
|---|---|
| 受付 | 相手が依頼を受け取った証拠がある状態(受付IDなど) |
| 最終成功 | 相手側の処理完了。画面の送信ボタン成功とは別 |
| 受付不明 | タイムアウト等で、受け付けたかを自システムが確定できない状態 |
受付IDが無いのに「失敗したと思い再送」すると、相手側では既に受け付け済みだった場合に二重送信になります。
構成要素
| 要素 | 役割 |
|---|---|
| Widget | 送信ボタン。成功しても最終完了とは表示しない |
| 入口Lambda | 送信要求を受け、後段へ渡す |
| 副作用Lambda | 外部APIへ依頼し、履歴状態を更新する |
| 履歴レコード | 送信状態の正本 |
| 外部送信API | 受付IDを返しうる相手 |
| 運用(人手確認) | 不明・不整合を外部とCRMで突合する |
自動再送をやめた理由
利用者は送信を押します。実装は、保存済み履歴IDを渡して外部送信APIに依頼し、受付結果を履歴へ書きます。PDF本体は再送しません。正本は履歴上の保存済みPDFです。
最初はHTTPクライアントのデフォルトretry、タイムアウト後の再実行、画面再押下のサーバ側同一扱いを検討しました。外部送信ではいずれも不適切です。
タイムアウトは失敗確定ではありません。相手側では受け付け済みで、自システムだけが応答を失っていることがあります。その状態で再送すると、二重送信と正規の再操作を後から区別できません。
画面成功は受付まで
入口側の送信要求成功は、原則として外部APIが依頼を受け付けたところまでです。最終配達完了ではありません。画面文言も完了と断定しません。詳細状態の正本は履歴です。最終結果の表示場所は第5回です。
状態遷移はおおよそ、保存済み → 送信開始中 → 受付済み → 送信中 → 最終成功/失敗/人手確認です。最終成功後に遅れて失敗コードが来ても、成功状態を安易に戻しません。
PDF未保存なら送信要求は拒否し、「送信前にPDF保存が完了していません」系の公開文言を返します。
失敗ごとの分岐
ベンダー固有ステータス名は出しません。判定の目安は次のとおりです。
| 見え方 | 判定 | 自動retry | その後 |
|---|---|---|---|
| 未受付が明確 | 明確なクライアントエラー等で受付IDが無い | しない | 状態を戻し、明示の再操作を許可しうる |
| 受付不明 | タイムアウトや接続断等で受付証拠が無い | しない | 人手確認へ遷移。送り直ししない |
| 受付後のCRM更新失敗 | 受付IDはあるが履歴更新が失敗 | 送り直ししない | 照会のうえ人手確認 |
| GETやtoken refresh | 読取・認証更新 | してよい | 通信レイヤのretry |
「未受付が明確」と「受付不明」は次アクションが異なります。前者のみ、状態復帰後の明示再操作を許す余地があります。後者は送り直さず人手確認へ遷移します。タイムアウト時に黙って再送すると、受付済みケースの二重送信を区別できません。
| retryしてよい | retryしない |
|---|---|
| トークン更新、参照GET、一覧取得 | 外部送信の依頼そのもの |
| 冪等と分かっている読取 | 受付後の破壊的更新の盲目的再実行 |
「落ちたらもう一回」をHTTPライブラリ既定に任せると、二重送信と再操作の境界が運用からも見えなくなります。曖昧さを残さない方を選びました。
連打と人手確認
送信ボタン連打を安全な再送としては扱いません。状態ガードとidempotency(同一要求の副作用を1回に近づける仕組み)で二重副作用を抑えます。UIが再押下できても、サーバが同一送信を増やさないようにします。
人手確認はシステム停止ではなく、自動では確定できないため人が突合する状態です。履歴を人手確認状態にし、運用が外部の受付状況とCRMを突合します。ここで自動再送を入れると、受付不明を人手確認へ閉じる方針と矛盾します。人手確認後に自動復旧はしません。
保存と送信を分ける理由
| 失敗時点 | 残るもの | 次の手 |
|---|---|---|
| PDF保存前 | 入力 | 保存から再開 |
| 保存後・送信前 | 保存済みPDF | 送信要求のみ再開 |
| 受付後・CRM更新失敗 | 外部受付の可能性 | 照会と人手確認 |
| 受付成功 | 進行情報つき履歴 | 確認用Lambdaへ委譲 |
1リクエストに保存と送信を詰めると、この切り分けが壊れます。履歴更新の競合では上書きしません。HTTPでは412 Precondition Failedになりやすいです。確認用側も同様です。
画面成功は最終成功ではありません。外部送信は一時エラーでも自動retryしません。受付不明や受付後の不整合は人手確認へ遷移します。保存と送信は分けます。