Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/integration/03-webhooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ EVEYS_OCPP_WEBHOOK_ENABLE_TX_STARTED=1
## Delivery semantics

- **At-least-once.** A delivery may be retried; the backend MUST be idempotent on `X-Eveys-Event-Id`.
- **Retries (in-loop)**: 5 attempts with exponential backoff: 1 s, 5 s, 30 s, 2 min, 10 min. After 5 failures the envelope is enqueued into the durable backlog (see below) rather than dropped.
- **Retries (in-loop)**: 5 attempts with exponential backoff: 1 s, 5 s, 15 s, 30 s, 60 s. After 5 failures the envelope is enqueued into the durable backlog (see below) rather than dropped.
- **Durable backlog (tail)**: any envelope the dispatcher couldn't deliver in-loop is persisted into the `webhook_delivery_backlog` Postgres table. A background drainer keeps retrying on a coarser cadence (5 min, 15 min, 30 min, 1 h, 2 h, 4 h, 6 h, then held at 6 h) until either the row delivers or ages past the retention window (`EVEYS_OCPP_WEBHOOK_BACKLOG_RETENTION_HOURS`, default 7 days). Retention aging is the only path to `dead=true`; the `eveys_ocpp_webhook_backlog_deadletter_total` counter fires — alert on any non-zero increment.
- **Per-charger ordering not guaranteed.** Two events from the same charger may arrive out of order. The backend should use `occurred_at` for ordering, not arrival time. Same caveat as Kafka — `cp_id` is the partition key on Kafka, but webhooks are unordered.
- **HTTP status interpretation**:
Expand Down
2 changes: 1 addition & 1 deletion src/eveys_ocpp/webhooks/dispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
# Backoff schedule per docs/integration/03-webhooks.md § Delivery
# semantics. Indexed by attempt number (0 = first attempt; we sleep
# this many seconds BEFORE the (n+1)th attempt).
_BACKOFF_SECONDS: tuple[float, ...] = (1.0, 5.0, 30.0, 120.0, 600.0)
_BACKOFF_SECONDS: tuple[float, ...] = (1.0, 5.0, 15.0, 30.0, 60.0)


class WebhookDispatcher:
Expand Down
Loading