Retry logika
Klubero automaticky opakuje doručení webhook požadavků, které selhaly. Tato stránka popisuje retry politiku a jak správně implementovat váš endpoint.
Kdy je požadavek úspěšný
Požadavek je považován za úspěšně doručený, pokud váš endpoint:
| Kritérium | Požadavek |
|---|---|
| Stavový kód | HTTP 2xx (200, 201, 202, 204, ...) |
| Timeout | Odpověď do 10 sekund |
Jakákoli jiná situace spouští retry mechanismus.
Retry politika
Exponenciální backoff
Klubero používá exponenciální backoff strategii:
| Pokus | Interval od předchozího | Kumulativní čas |
|---|---|---|
| 1 | Okamžitě | 0 |
| 2 | 1 minuta | 1 minuta |
| 3 | 5 minut | 6 minut |
| 4 | 15 minut | 21 minut |
| 5 | 1 hodina | 1h 21min |
Pokus 1 Pokus 2 Pokus 3 Pokus 4 Pokus 5
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
├────1 min──────►├────5 min─────►├───15 min──────►├────1 hodina───►│
│ │ │ │ │
KONEC
Maximální počet pokusů
Po 5 neúspěšných pokusech je doručení označeno jako failed a další pokusy nejsou prováděny.
Po vyčerpání všech pokusů je událost ztracena. Data můžete získat přes API pomocí entity_id z logu.
Stavy doručení
| Stav | Popis |
|---|---|
pending | Čeká na doručení nebo na další pokus |
delivered | Úspěšně doručeno |
failed | Doručení selhalo po všech pokusech |
Životní cyklus doručení
┌─────────────────┐
│ PENDING │
└────────┬────────┘
│
┌──────────────┼──────────────┐
▼ │ ▼
┌──────────┐ │ ┌──────────┐
│ HTTP 2xx │ │ │ Selhání │
└────┬─────┘ │ └────┬─────┘
│ │ │
▼ │ ┌──────┴──────┐
┌──────────┐ │ │ Pokus < 5 │
│DELIVERED │ │ └──────┬──────┘
└──────────┘ │ │
│ ┌──────┴──────┐
│ ▼ ▼
│ Retry Pokus = 5
│ (čeká) │
│ │ ▼
│ └────► ┌──────────┐
│ │ FAILED │
└────────────►└──────────┘
Příčiny selhání
HTTP chybové kódy
| Kód | Popis | Retry? |
|---|---|---|
| 2xx | Úspěch | Ne (doručeno) |
| 3xx | Redirect | Ano |
| 4xx | Klientská chyba | Ano |
| 5xx | Serverová chyba | Ano |
Síťové chyby
| Chyba | Popis | Retry? |
|---|---|---|
| Connection refused | Server odmítl spojení | Ano |
| Connection timeout | Nepodařilo se připojit | Ano |
| DNS resolution failed | Nepodařilo se přeložit doménu | Ano |
| SSL/TLS error | Chyba certifikátu | Ano |
| Read timeout | Odpověď nepřišla do 10s | Ano |
Best practices
1. Odpovídejte rychle
Vraťte HTTP 200 co nejdříve a náročné zpracování proveďte asynchronně:
// ✅ SPRÁVNĚ - rychlá odpověď
app.post('/webhooks', async (req, res) => {
// Ověření podpisu
if (!verifySignature(req)) {
return res.status(401).send('Invalid signature');
}
// Okamžitá odpověď
res.status(200).send('OK');
// Asynchronní zpracování (po odpovědi)
processEventAsync(req.body);
});
// ❌ ŠPATNĚ - synchronní zpracování
app.post('/webhooks', async (req, res) => {
await processEvent(req.body); // Může trvat dlouho
res.status(200).send('OK'); // Timeout!
});
2. Implementujte idempotenci
Stejná událost může být doručena vícekrát. Použijte X-Webhook-Delivery pro deduplikaci:
const processedDeliveries = new Map(); // V produkci použijte Redis/DB
app.post('/webhooks', async (req, res) => {
const deliveryId = req.headers['x-webhook-delivery'];
// Kontrola duplikátu
if (processedDeliveries.has(deliveryId)) {
return res.status(200).send('Already processed');
}
// Označení jako zpracované (před zpracováním!)
processedDeliveries.set(deliveryId, Date.now());
// Zpracování
await processEvent(req.body);
res.status(200).send('OK');
});
3. Logujte všechny požadavky
app.post('/webhooks', (req, res) => {
const deliveryId = req.headers['x-webhook-delivery'];
const eventType = req.headers['x-webhook-event'];
logger.info('Webhook received', {
deliveryId,
eventType,
entityId: req.body.entity_id,
timestamp: new Date().toISOString()
});
// Zpracování...
logger.info('Webhook processed', { deliveryId });
res.status(200).send('OK');
});
4. Zpracujte chyby gracefully
app.post('/webhooks', async (req, res) => {
try {
await processEvent(req.body);
res.status(200).send('OK');
} catch (error) {
logger.error('Webhook processing failed', {
error: error.message,
deliveryId: req.headers['x-webhook-delivery']
});
// Vraťte 500 pro spuštění retry
res.status(500).send('Processing failed');
}
});
Monitoring
Kontrola stavu doručení
Sledujte stav doručení pomocí API:
# Všechny neúspěšné doručení
curl -X GET "https://api.klubero.cz/api/v1.0/webhooks/123/logs?status=failed" \
-H "Authorization: Bearer {access_token}"
# Čekající na retry
curl -X GET "https://api.klubero.cz/api/v1.0/webhooks/123/logs?status=pending" \
-H "Authorization: Bearer {access_token}"
Odpověď
{
"success": true,
"data": [
{
"id": 456,
"guid": "660e8400-e29b-41d4-a716-446655440001",
"webhook_id": 123,
"event_type": "user.created",
"entity_id": 12345,
"status": "failed",
"attempts": 5,
"last_attempt": "2024-01-15T11:21:00Z",
"next_retry": null,
"response_code": 500,
"error_message": "Internal Server Error",
"duration_ms": 5023,
"created_at": "2024-01-15T10:00:00Z"
}
]
}
Doporučený alerting
Nastavte monitoring pro:
| Metrika | Práh | Akce |
|---|---|---|
| Míra selhání | > 10% | Zkontrolujte endpoint |
| Průměrná doba odezvy | > 5s | Optimalizujte zpracování |
| Pending logy | > 100 | Zkontrolujte dostupnost |
Řešení problémů
Webhook se nedoručuje
Zkontrolujte:
- Je váš endpoint veřejně dostupný z internetu?
- Používáte HTTPS s platným certifikátem?
- Odpovídá endpoint do 10 sekund?
- Vrací stavový kód 2xx?
Test dostupnosti:
curl -X POST https://vas-endpoint.cz/webhooks \
-H "Content-Type: application/json" \
-d '{"test": true}'
Webhook přichází s velkým zpožděním
Pokud vidíte zpoždění, pravděpodobně váš endpoint neodpověděl včas při prvním pokusu. Zkontrolujte:
- Logy webhooku přes API (
GET /api/v1.0/webhooks/{id}/logs) - Pole
attempts- pokud je > 1, došlo k retry - Pole
error_message- obsahuje důvod selhání
Testování na localhostu
Pro vývoj můžete použít:
ngrok - vytvoří veřejnou URL pro váš lokální server:
ngrok http 3000
# Výstup: https://abc123.ngrok.io -> http://localhost:3000
webhook.site - zobrazí přijaté webhooky v prohlížeči bez nutnosti kódu.
FAQ
Co se stane, když můj server je nedostupný?
Události budou opakovány podle retry politiky. Celková doba pro všechny pokusy je přibližně 1 hodina 21 minut. Po vyčerpání pokusů jsou označeny jako failed.
Mohu získat ztracené události?
Ano. V logu je uložen entity_id, pomocí kterého můžete data načíst přes API.
Proč dostávám stejnou událost vícekrát?
Důvody mohou být:
- Váš endpoint neodpověděl včas (timeout > 10s)
- Odpověděl ne-2xx kódem
- Síťová chyba během odpovědi
Vždy implementujte idempotentní zpracování pomocí X-Webhook-Delivery.
Mohu ručně spustit retry?
Aktuálně není k dispozici API pro manuální retry. Pokud potřebujete data, použijte API k jejich načtení pomocí entity_id z logu.
Jak dlouho jsou logy uchovávány?
Logy jsou automaticky mazány po 30 dnech. Pro dlouhodobé uchovávání exportujte data pravidelně přes API.