Doručovanie a opakovania
Každý pokus beží v DeliverWebhook vo fronte webhooks.queue.outbound. Pokusy sa počítajú v databáze ($tries = 0), takže uvoľnenia pri obmedzení nikdy nevyčerpajú --tries workera; $timeout je celkový limit + 20 s.
Jeden pokus
- Riadok sa zaberie dispatch tokenom jobu — duplicitný alebo nahradený job nič neodošle.
- Ak bol endpoint medzitým vypnutý alebo zmazaný, doručenie sa zruší bez požiadavky.
- Obmedzenie na endpoint (rate_limit_per_minute alebo outbound.rate_limit.per_minute, 60) prebehne pred akýmkoľvek prekladom DNS. Obmedzený pokus riadok odloží bez spotreby pokusu; job sa uvoľní a riadok zaberie znova.
- Podpíše sa s novou webhook-timestamp (počas prechodného obdobia oboma kľúčmi) a pošle sa User-Agent — outbound.user_agent, prázdne = „{app.name} Webhooks“, alebo vlastná hlavička user-agent endpointu.
- Odošle sa cez ochranu pred SSRF: každý krok overený a pripnutý, limit pripojenia 5 s, celkovo 10 s naprieč krokmi, odpoveď čítaná len do outbound.max_response_bytes (4 096) — so zapnutou aj vypnutou ochranou.
- Zaznamená sa OutboundAttempt: číslo, séria, manual, trvanie, stav, výňatok bezpečný pre UTF-8, response_truncated, Retry-After, pripojená adresa, kód chyby a naša vlastná správa — nikdy správa dodávateľa.
Obmedzenie zabezpečuje HTTP Client Rate Limits — adaptívne, rešpektuje Retry-After príjemcu a namiesto blokovania workera job uvoľní:
// in effect, per attempt (built through the injected manager, not the facade):
Http::rateLimit(RateLimits::releasingJob($job)->perMinute($n)->by("webhooks:out:{$endpointId}")->adaptive()->maxWait($maxDelay))Výsledky
| Výsledok | Následok |
|---|---|
2xx | succeeded; počítadlo zlyhaní endpointu sa vynuluje; DeliverySucceeded. |
410 Gone | failed; endpoint sa vypne (gone), kým je zapnuté outbound.disable_on_gone. |
| Zablokovaný cieľ, pripnutie, ktoré nemožno udržať, nemožnosť podpísať | Okamžite failed (konečné). |
| Čokoľvek iné — 3xx (nesledované), 4xx, 5xx, timeout, spojenie, TLS, DNS | Opakuje sa do max_attempts (8) s DeliveryFailed(final: false, nextAttemptAt); potom failed a DeliveryFailed(final: true). |
| Neočakávaná výnimka počas pokusu | Nahlási sa, zaznamená ako unexpected a opakuje ako v riadku vyššie — nikdy neostane v stave sending a nikdy sa nezapočíta do automatického vypnutia endpointu. |
Stavy: pending → sending → succeeded | retrying → … | failed | cancelled.
| Kód chyby | Význam |
|---|---|
http_status | Príjemca odpovedal stavom mimo 2xx. |
redirect_not_followed | 3xx pri vypnutých presmerovaniach (opakuje sa). |
timeout · connection · tls | Zlyhala sieť. |
unresolved | Hostiteľ sa nepreložil (opakuje sa). |
blocked | Ochrana pred SSRF cieľ odmietla — konečné, uložené napríklad ako blocked (private_address). |
cannot_pin | Spojenie sa nepodarilo pripnúť na overené adresy — konečné. |
too_many_redirects · redirect_downgrade | Viac ako max_redirects alebo https → http. |
signing | Schéma nevie podpisovať (bez SignsOutboundWebhooks, endpoint RFC 9421 bez id kľúča) — konečné, bez požiadavky. |
worker_lost | Riadok v stave sending, ktorého nárok vypršal — worker skončil; pravidelný beh to zaznamená a zopakuje. |
unexpected | Neočakávaná výnimka počas pokusu. |
Opakovania
delay(n) = min(base · multiplier^(n-1), cap) — base 60 s, multiplier 4, cap 9 h — potom ± rozptyl (10 %), nikdy menej ako 1 s. Retry-After (sekundy alebo HTTP dátum, pri akomkoľvek stave) oneskorenie zvýši naň, najviac na outbound.retry.max_retry_after (1 deň). outbound.retry.schedule nahradí vzorec vlastným zoznamom. Predvolené hodnoty:
| Pokus | Oneskorenie pred ním | Od prvého |
|---|---|---|
| 1 | — | 0 |
| 2 | 1 m | 1 m |
| 3 | 4 m | 5 m |
| 4 | 16 m | 21 m |
| 5 | 1 h 4 m | 1 h 25 m |
| 6 | 4 h 16 m | 5 h 41 m |
| 7 | 9 h | 14 h 41 m |
| 8 | 9 h | 23 h 41 m |
Oneskorenie do queue.max_delay (900 s) je oneskorený job; dlhšie čakajú na pravidelný beh webhooks:retry — spustite plánovač. Jeden beh odošle najviac outbound.sweep_batch (1 000) jobov, takže nahromadené doručenia po výpadku sa spracujú postupne. Pravidelný beh tiež znova odošle job, ktorý mešká viac ako outbound.requeue_after (každá ďalšia kópia čaká dvakrát dlhšie, najviac hodinu, aby sa pomalý front nezaplnil kópiami), a zaznamená worker_lost pre riadok v stave sending, ktorého worker skončil.
Automatické vypnutie
consecutive_failures počíta doručenia, ktoré skončili ako failed — každý úspech ho vynuluje a doručenie, ktorého posledný pokus bol unexpected (chyba na vašej strane), sa nepočíta. Pri outbound.disable_after (5) sa endpoint vypne jednou podmienenou aktualizáciou, takže súbežné workery vyvolajú EndpointDisabled presne raz, a jeho čakajúce a opakované doručenia sa zrušia. Prechodný výpadok endpoint nikdy nevypne, len dlhodobý. Odpoveď 410 Gone ho vypne okamžite.
Opätovné doručenie
Webhooks::outbound()->redeliver($delivery); // or: php artisan webhooks:redeliver msg_…Pre doručenia succeeded, failed alebo cancelled na zapnutom endpointe: nová séria, pokusy späť na 0, rovnaké webhook-id (príjemcovia podľa neho deduplikujú — pre novú správu odošlite znova), každý pokus označený manual. Práve prebieha → DeliveryInProgressException; vymazané telo → PayloadPrunedException; vypnutý endpoint → EndpointNotAcceptingException.
Po výpadku — všetky zlyhané doručenia naraz
$result = Webhooks::for($team)->outbound()->redeliverFailed($endpoint, since: now()->subDay(), includeCancelled: true);
$result->queued; // redelivered
$result->skippedPruned; // their body was already pruned — cannot be sent againKaždé zlyhané doručenie endpointu (vytvorené od $since; s includeCancelled aj tie, ktoré zrušilo jeho vypnutie) sa opätovne doručí ako vyššie, po dávkach. Endpoint musí byť najprv zapnutý — zapnutie samo neodošle to, čo vypnutie zrušilo:
php artisan webhooks:enable outbound 12 # an auto-disabled endpoint first
php artisan webhooks:redeliver --endpoint=12 --since=2026-11-07 --cancelledPrejavte lásku k open source
Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.
Ďalšie spôsoby podpory vrátane kryptomienOdoslaním daru súhlasíte s našimi podmienkami prijímania darov.
Chcete to zabudovať do svojho produktu?
Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.