Webhook
再試行と失敗
成功の基準、9 回の再試行スケジュール、Retry-After、410、停止した配信、再配信、自動無効化、エンドポイントを冪等にする方法を説明します。
Signals は、失敗した POST を決まったスケジュールで約 3 日間再試行します。スケジュールが尽きると、配信は**停止(再配信可能)**になります。何も失われません。アプリや API から再配信できます。このページでは、各段階を説明します。
成功の基準
エンドポイントが 10 秒以内に 2xx のステータスを返すと、配信は成功です。
それ以外はすべて失敗です。4xx や 5xx、3xx のリダイレクト、タイムアウト、接続エラーが該当します。Signals はレスポンスを最大 4 KB まで読み、内容は無視します。
ボディを保存したら、すぐに 200 を返してください。ページの読み取りは、その後バックグラウンドジョブで行います。処理が遅くてタイムアウトすると、同じ POST がもう一度届きます。
再試行スケジュール
1 つの配信は最大 9 回試行されます。待ち時間は、前回の失敗から数えます。多くのエンドポイントが同じ秒に再試行しないよう、各待ち時間は ±10 % ずれます。
| 試行 | タイミング |
|---|---|
| 1 | すぐに |
| 2 | 1 回目の失敗から 1 分後 |
| 3 | 2 回目から 5 分後 |
| 4 | 3 回目から 30 分後 |
| 5 | 4 回目から 2 時間後 |
| 6 | 5 回目から 6 時間後 |
| 7 | 6 回目から 12 時間後 |
| 8 | 7 回目から 24 時間後 |
| 9 | 8 回目から 24 時間後 |
合計で約 2.9 日です。9 回目も失敗すると、配信は**停止(再配信可能)**になります。履歴には残り、再配信できます。
各試行のヘッダー:
Signals-Webhook-Idは、1 つの配信のすべての試行で同じです。ボディのwebhookIdも同じです。Signals-Delivery-Attemptは1から9まで数えます。- ボディには同じ実行、件数、トークンが入り、
sentAtだけが新しくなります。 Signals-Signatureは、試行ごとに新しいタイムスタンプで署名し直されます。
応答の扱い
| あなたの応答 | Signals の動作 |
|---|---|
2xx | 配信済み。完了です。 |
410 Gone | すぐに止めます。配信は停止(再配信可能)になり、Webhook は無効になって「サーバーが 410 Gone を返したため、この URL への送信を停止しました。サーバーを修正してから再度有効にしてください。」と表示されます。 |
Retry-After 付きの 429 または 503 | スケジュールどおりの待ち時間と Retry-After の時間(最大 1 時間)を比べ、長いほうだけ待ってから URL をもう一度呼びます。Retry-After で待ち時間が短くなることはありません。 |
その他の 4xx | スケジュールどおり再試行します。署名チェックの失敗やパスの誤りが多い原因です。 |
5xx、408、タイムアウト、ネットワークエラー | スケジュールどおり再試行します。 |
3xx | スケジュールどおり再試行します。リダイレクトには追従しません。 |
| ブロックされた URL | すぐに**停止(再配信可能)**になります。ホスト名がプライベートまたは内部のアドレスに解決されました。 |
URL の復旧待ち
ある URL への配信が 1 件失敗すると、Signals は次の試行時刻まで、その URL への他の待機中の配信の呼び出しを止めます。それらには URL の復旧待ちと表示されます。リクエストは行われず、スキップされた試行は回数に数えられません。1 回成功すると、URL への送信が再開されます。
失敗の種類
配信履歴シートには、実行ごとに 1 行、失敗した配信ごとに 1 つのラベルが表示されます。
| アプリのラベル | 種類 | 起きたこと | 対処 |
|---|---|---|---|
| HTTP エラー | http_status | サーバーが 5xx、408、413、429 を返しました。ステータスコードが表示されます。 | ログを確認してください。 |
| サーバーが拒否しました(4xx) | client_error | サーバーがその他の 4xx(400、401、404 など)を返しました。 | 署名のコード、パス、前段の認証を確認してください。 |
| URL が存在しません(410) | gone | サーバーが 410 を返しました。Webhook は無効になります。 | エンドポイントを修正し、再度有効にするを押してください。 |
| タイムアウト | timeout | 10 秒以内に応答がありませんでした。 | 先に応答し、処理は後で行ってください。 |
| ネットワークエラー | network | Signals が接続できませんでした。DNS の失敗、接続の拒否、TLS のエラーなどです。 | DNS レコード、証明書、ファイアウォールを確認してください。 |
| リダイレクト(追従しません) | redirect | サーバーが 3xx を返しました。 | Webhook に最終的な URL を保存してください。http から https、www へのリダイレクトに注意してください。 |
| URL がブロックされました | unsafe_url | 送信時に、ホスト名がプライベートまたは内部のアドレスに解決されました。 | 公開ホスト名を使ってください。 |
| URL の復旧待ち | endpoint_unavailable | この URL への最近の配信が失敗したため、Signals が呼び出しを止めています。リクエストは行われず、試行回数も使われていません。 | エンドポイントを修正してください。1 回成功すると解除されます。 |
| イベントが存在しません | event_missing | 実行のイベントがなくなりました。たとえば、プロジェクトが削除された場合です。 | 対処は不要です。 |
| Webhook が一時停止されました | paused | 配信の処理中に Webhook が一時停止されました。 | 再開すると送られます。 |
ステータスのラベル
| ステータス | 意味 |
|---|---|
| 待機中 | 次の試行を待っています。Webhook が一時停止中のときもこの状態です。 |
| 送信中 | 現在送信中です。 |
| 配信済み | エンドポイントが 2xx を返しました。 |
| 失敗 | スケジュール外で、2xx なしに終了しました。たとえば、実行のイベントがなくなった場合です。再配信できます。 |
| 停止(再配信可能) | 9 回の試行がすべて失敗した、サーバーが 410 を返した、または URL がブロックされました。再配信できます。 |
| 再配信済み | 再配信によって、新しい配信に置き換えられました。 |
停止した配信
停止した配信は、実行と件数を保持しています。Signals が自動で送り直すことはありません。再配信するか、無効になった Webhook を再度有効にするか(停止した配信が自動で再配信されます)を、あなたが選びます。
自動無効化
Signals は次の 2 つの場合に Webhook を無効にし、送信を止めます。テスト配信は数えません。
- 3 日間成功がない。 バナーには「3日間一度も配信に成功しなかったため、この URL への送信を停止しました。サーバーを修正してから再度有効にしてください。」と表示されます。
- サーバーが
410を返した。 すぐに無効になります。上記をご覧ください。
Steve チームが Webhook を停止した場合、バナーには「この Webhook は Steve チームが停止しました。準備ができたら再度有効にしてください。」と表示されます。
エンドポイントを修正してから、再度有効にするをクリックします。Signals は止まった位置から続けます。無効だった間に終わった実行が古い順に送られ、停止した配信ももう一度キューに入ります。管理 API で resume: "now" を送ると、その間の実行をスキップできます。
再配信
行のメニューから配信履歴を見るを開きます。
- 失敗した行の再送は、同じ配信をもう一度試します。
webhookIdは変わらず、試行回数は数え直しになります。行は再配信済みになりません。 - 停止した行の再配信は、その実行を新しい配信として送ります。テスト配信にはこのボタンはありません。
- シートの上部にある停止した配信を再配信で、Webhook のすべての停止した配信を再配信します。失敗した行は対象外です。
- API でも再配信でき、実行、時刻、失敗のステータスでも選べます:
POST /api/public/v1/webhooks/{id}/replay。テストと管理をご覧ください。 - 再送と再配信には有効な Webhook が必要です。
再配信は新しい配信です。新しい webhookId を持ち、試行回数は 1 から数え直し、ページトークンも新しくなって、さらに 30 日間有効です。元の行は再配信済みになります。イベントは同じで、eventId も同じです。
履歴は配信を 30 日間保持し、その後削除します。
エンドポイントを冪等にする
同じ POST が複数回届くことがあります。サーバーが処理済みなのにタイムアウトした場合や、リクエストの途中で一時停止した場合です。再配信では、同じ実行が新しい webhookId で届きます。再送では、webhookId は変わりません。2 つのキーを使ってください。
| キー | 場所 | 防げるもの |
|---|---|---|
webhookId | ボディと Signals-Webhook-Id ヘッダー | 1 つの配信の再試行。POST 全体をスキップします。 |
eventId | ページの各要素 | それ以外すべて。再配信、同じページの 2 回の読み取り、ループ途中のクラッシュ。 |
- 処理した
webhookIdを保存し、既知の POST はスキップします。 - 各
eventIdは、メモリ上のセットではなく一意インデックスで保存します。保存済みのイベントはスキップします。 - ボディを保存したら
200を返します。4xxや5xxを返すと、Signals は POST をもう一度送ります。 - 副作用(CRM へのメモ作成、Slack への投稿など)は
eventIdのチェックの後に、できれば同じトランザクションで行ってください。
ループの全体は実行のイベントを読むにあります。