Backoff
in package
Stateful exponential-backoff helper for the long-poll retry loop — port of `aiogram.utils.backoff.Backoff`.
Semantics (matching upstream Backoff.__next__):
-
__constructseeds bothcurrentDelayandnextDelaywithconfig.minDelay. The firstnext()call therefore returnsminDelay, mirroring upstream where the first iteration sleeps the minimum and only subsequent iterations grow. -
next()returns the (now-current) delay AND advances state. It is the only mutator besidesreset(). -
Growth is
min(maxDelay, currentDelay * factor + jitter), withjitterdrawn uniformly from[-config.jitter, +config.jitter]. Upstream usesnormalvariate(mean=min(value*factor, max_delay), sigma=jitter)— we deviate here:Spec deviation: uniform jitter, not normal jitter. Normal jitter can spike above maxDelay (unbounded tail), forcing a separate clamp. Uniform jitter in
[-jitter, +jitter]is bounded and gives the same "smear the retry burst" guarantee callers care about. The cap is applied AFTER the jitter is added (min(max, value*factor + jitter)) so nextDelay can never exceed maxDelay regardless of jitter draw.The deviation is invisible to consumers: only the statistical shape of the per-call delay differs, never the bounds.
-
asleep()suspends the current Fiber viaAmp\delay()forcurrentDelayseconds, then advances. This is the loop's primary entry point;next()andreset()exist for tests and for callers that want to drive the schedule manually.
Not final readonly: the instance is mutable by design (counter,
delay state). BackoffConfig is the immutable half.
Table of Contents
Properties
- $config : BackoffConfig
- $counter : int
- Number of times `next()` (or `asleep()`) has advanced the schedule.
- $currentDelay : float
- $nextDelay : float
Methods
- __construct() : mixed
- asleep() : void
- Suspend the calling Fiber for `currentDelay` seconds via `Amp\delay()`, then advance the schedule. The Revolt event loop continues servicing other fibers during the wait — this is the cooperative analogue of `time.sleep` from upstream's sync `sleep()`, and the direct port of upstream's async `asleep`.
- currentDelay() : float
- next() : float
- Advance one step: rotate `nextDelay -> currentDelay`, compute the new `nextDelay`, bump the counter, and return the (now-current) delay so callers can pass it to `sleep`/`delay`.
- nextDelay() : float
- reset() : void
Properties
$config read-only
public
BackoffConfig
$config
$counter
Number of times `next()` (or `asleep()`) has advanced the schedule.
public
int
$counter
= 0
Reset to 0 by reset(). Public — upstream exposes counter as a
read-only property; PHP readonly on an int counter would require a
setter ceremony that costs more than it saves here.
$currentDelay
private
float
$currentDelay
$nextDelay
private
float
$nextDelay
Methods
__construct()
public
__construct(BackoffConfig $config) : mixed
Parameters
- $config : BackoffConfig
asleep()
Suspend the calling Fiber for `currentDelay` seconds via `Amp\delay()`, then advance the schedule. The Revolt event loop continues servicing other fibers during the wait — this is the cooperative analogue of `time.sleep` from upstream's sync `sleep()`, and the direct port of upstream's async `asleep`.
public
asleep() : void
currentDelay()
public
currentDelay() : float
Return values
floatnext()
Advance one step: rotate `nextDelay -> currentDelay`, compute the new `nextDelay`, bump the counter, and return the (now-current) delay so callers can pass it to `sleep`/`delay`.
public
next() : float
Upstream calls this __next__ because Python iterates the backoff
via next(backoff). PHP has no equivalent magic; next() is the
plain name we expose.
Return values
floatnextDelay()
public
nextDelay() : float
Return values
floatreset()
public
reset() : void