55import inspect
66import random
77import time
8- from dataclasses import dataclass , field
8+ from dataclasses import asdict , dataclass , field
99from typing import TYPE_CHECKING , Any , Protocol , runtime_checkable
1010
1111if TYPE_CHECKING :
@@ -19,7 +19,11 @@ class StoreConfig:
1919 path : str = "" # kept for API compat; not used
2020 max_pending : int = 10_000
2121 lease_timeout : float = 30.0
22- backoff_base : float = 1.0
22+ # Hub-internal cap on delivery retries (lease expiry / worker death).
23+ # Has nothing to do with user-level retry policy, which is handled by
24+ # taskiq retry middlewares. Set to 0 to disable redelivery entirely.
25+ max_delivery_attempts : int = 5
26+ delivery_backoff : float = 1.0
2327 backoff_cap : float = 60.0
2428
2529
@@ -34,10 +38,9 @@ class _Task:
3438 payload : bytes
3539 labels : dict [str , Any ]
3640 state : str # ready / leased / done / failed
41+ # Internal delivery-attempt counter (incremented on each dispatch).
42+ # NOT related to user-level retry policy — that lives in middlewares.
3743 attempts : int = 0
38- max_retries : int = 0
39- retry_backoff : float = 1.0
40- retry_jitter : float = 0.0
4144 priority : int = 0
4245 created_at : float = field (default_factory = time .time )
4346 updated_at : float = field (default_factory = time .time )
@@ -49,25 +52,7 @@ class _Task:
4952
5053 def as_dict (self ) -> dict [str , Any ]:
5154 """Return a dict view of this task record."""
52- return {
53- "task_id" : self .task_id ,
54- "task_name" : self .task_name ,
55- "payload" : self .payload ,
56- "labels" : self .labels ,
57- "state" : self .state ,
58- "attempts" : self .attempts ,
59- "max_retries" : self .max_retries ,
60- "retry_backoff" : self .retry_backoff ,
61- "retry_jitter" : self .retry_jitter ,
62- "priority" : self .priority ,
63- "created_at" : self .created_at ,
64- "updated_at" : self .updated_at ,
65- "next_run_at" : self .next_run_at ,
66- "lease_id" : self .lease_id ,
67- "leased_worker_id" : self .leased_worker_id ,
68- "lease_until" : self .lease_until ,
69- "last_error" : self .last_error ,
70- }
55+ return asdict (self )
7156
7257 def as_status_dict (self ) -> dict [str , Any ]:
7358 """Return a JSON-safe dict (no raw bytes) for control-plane status responses."""
@@ -91,18 +76,7 @@ class _Worker:
9176
9277 def as_dict (self ) -> dict [str , Any ]:
9378 """Return a dict view of this worker record."""
94- return {
95- "worker_id" : self .worker_id ,
96- "task_addr" : self .task_addr ,
97- "capacity" : self .capacity ,
98- "inflight" : self .inflight ,
99- "last_seen" : self .last_seen ,
100- "heartbeat_interval" : self .heartbeat_interval ,
101- "lease_timeout" : self .lease_timeout ,
102- "draining" : self .draining ,
103- "status" : self .status ,
104- "version" : self .version ,
105- }
79+ return asdict (self )
10680
10781
10882# ── task context ─────────────────────────────────────────────────────────────
@@ -325,16 +299,21 @@ def __init__(self, config: StoreConfig) -> None:
325299
326300 # ── helpers ───────────────────────────────────────────────────────────────
327301
328- def _backoff (self , attempts : int , backoff_base : float ) -> float :
329- return min (self .config .backoff_cap , backoff_base * (2 ** max (0 , attempts - 1 )))
302+ def _backoff (self , attempts : int ) -> float :
303+ return min (
304+ self .config .backoff_cap ,
305+ self .config .delivery_backoff * (2 ** max (0 , attempts - 1 )),
306+ )
330307
331308 def _requeue_or_fail (self , task : _Task , worker_id : str , error : str ) -> bool :
332309 now = time .time ()
333- if task .attempts > task .max_retries :
310+ # Hub-internal delivery cap. User-level retries are handled by
311+ # retry middlewares, which re-kick the task with updated labels.
312+ if task .attempts > self .config .max_delivery_attempts :
334313 task .state = "failed"
335314 else :
336315 task .state = "ready"
337- task .next_run_at = now + self ._backoff (task .attempts , task . retry_backoff )
316+ task .next_run_at = now + self ._backoff (task .attempts )
338317 task .last_error = error
339318 task .lease_id = None
340319 task .leased_worker_id = None
@@ -367,9 +346,6 @@ def submit(self, envelope: TaskEnvelope) -> None:
367346 payload = envelope .payload ,
368347 labels = envelope .labels ,
369348 state = "ready" ,
370- max_retries = envelope .max_retries ,
371- retry_backoff = envelope .retry_backoff ,
372- retry_jitter = envelope .retry_jitter ,
373349 priority = envelope .priority ,
374350 created_at = envelope .created_at or now ,
375351 updated_at = now ,
0 commit comments