Přeskočit na hlavní obsah

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ériumPožadavek
Stavový kódHTTP 2xx (200, 201, 202, 204, ...)
TimeoutOdpověď do 10 sekund

Jakákoli jiná situace spouští retry mechanismus.


Retry politika

Exponenciální backoff

Klubero používá exponenciální backoff strategii:

PokusInterval od předchozíhoKumulativní čas
1Okamžitě0
21 minuta1 minuta
35 minut6 minut
415 minut21 minut
51 hodina1h 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.

warning

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í

StavPopis
pendingČeká na doručení nebo na další pokus
deliveredÚspěšně doručeno
failedDoruč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ódPopisRetry?
2xxÚspěchNe (doručeno)
3xxRedirectAno
4xxKlientská chybaAno
5xxServerová chybaAno

Síťové chyby

ChybaPopisRetry?
Connection refusedServer odmítl spojeníAno
Connection timeoutNepodařilo se připojitAno
DNS resolution failedNepodařilo se přeložit doménuAno
SSL/TLS errorChyba certifikátuAno
Read timeoutOdpověď nepřišla do 10sAno

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:

MetrikaPráhAkce
Míra selhání> 10%Zkontrolujte endpoint
Průměrná doba odezvy> 5sOptimalizujte zpracování
Pending logy> 100Zkontrolujte dostupnost

Řešení problémů

Webhook se nedoručuje

Zkontrolujte:

  1. Je váš endpoint veřejně dostupný z internetu?
  2. Používáte HTTPS s platným certifikátem?
  3. Odpovídá endpoint do 10 sekund?
  4. 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:

  1. Váš endpoint neodpověděl včas (timeout > 10s)
  2. Odpověděl ne-2xx kódem
  3. 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.