From 858be6b885deb96e7d06e3a0177dbbbecf66d5fd Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Mon, 4 May 2026 08:32:43 +0300 Subject: [PATCH] Split how-it-works key config; document max_polling_interval MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The unified "Key configuration" table in how-it-works.md mixed broker-scoped (`timeline_key`, `payloads_key`) and subscriber-scoped (`polling_interval`, `max_concurrent`, `lease_ttl`) knobs and omitted `max_polling_interval` (default `5.0` s, see `schemas.py:11`). A reader trying to compute idle-queue latency from `polling_interval` alone would be off by orders of magnitude. Split the table into "Broker constructor" (adds `start_timeout`) and "Per-subscriber" (adds `max_polling_interval` with the `max_polling_interval × 1.5` worst-case latency note). Add `max_polling_interval` to the `@router.subscriber` example in `router.md` and a one-liner clarifying that all subscriber options are accepted by routers. --- docs/introduction/how-it-works.md | 11 ++++++++++- docs/usage/router.md | 5 ++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/docs/introduction/how-it-works.md b/docs/introduction/how-it-works.md index 539998c..c18ddf5 100644 --- a/docs/introduction/how-it-works.md +++ b/docs/introduction/how-it-works.md @@ -51,10 +51,19 @@ The default ack policy is `NACK_ON_ERROR`: the timer is acknowledged on success, ## Key configuration +### Broker constructor (`TimersBroker(...)`) + | Parameter | Default | Description | |-----------|---------|-------------| | `timeline_key` | `timers_timeline` | Prefix for sorted set keys (`{timeline_key}:{topic}`) | | `payloads_key` | `timers_payloads` | Prefix for hash keys (`{payloads_key}:{topic}`) | -| `polling_interval` | `0.05` s | How often to poll when no timers are due | +| `start_timeout` | `3.0` s | Max wait for the first Redis ping during startup | + +### Per-subscriber (`@broker.subscriber("topic", ...)`) + +| Parameter | Default | Description | +|-----------|---------|-------------| +| `polling_interval` | `0.05` s | Base poll interval used when the queue has work or just transitioned from idle | +| `max_polling_interval` | `5.0` s | Ceiling for the adaptive idle backoff — `polling_interval` doubles up to this value on consecutive empty polls. Worst-case delivery latency on a previously-idle queue is `max_polling_interval × 1.5` (with ±50% jitter) | | `max_concurrent` | `5` | Max handlers running concurrently per subscriber; also bounds fetch batch size | | `lease_ttl` | `30` s | How long a worker holds the lease before another worker may re-claim | diff --git a/docs/usage/router.md b/docs/usage/router.md index 5a8cb23..becea73 100644 --- a/docs/usage/router.md +++ b/docs/usage/router.md @@ -56,9 +56,12 @@ You can configure polling behaviour per subscriber: ```python @router.subscriber( "high-priority", - polling_interval=0.01, # poll every 10ms + polling_interval=0.01, # poll every 10ms when the queue has work + max_polling_interval=0.5, # cap idle-backoff at 500ms (default 5s) max_concurrent=20, # up to 20 handlers may run in parallel lease_ttl=60, # hold lease for up to 60 seconds ) async def handle_urgent(message: str) -> None: ... ``` + +All `@broker.subscriber` options are accepted by `@router.subscriber` and `TimersRoute` — see the [subscriber page](./subscriber.md) for the full list.