~/bend-docscommunity

retry.bend checks

raw source on the hub · import bend-kit-hairpin@0.2.1.0/retry.bend as Retry

Retry policy: a shared attempt budget, an operation deadline, bounded backoff, and a circuit breaker. All times are ms on one monotonic clock. The caller reads the clock; these defs are pure.

1 import
import Base

Types

type Budget source · line 7 · raw

Data

left: attempts the whole operation may still start, the first one included. Nested layers share one Budget. deadline: no attempt starts at or after this time. None: no deadline.

type Deny source · line 10 · raw

Data

type Gate source · line 15 · raw

Data

type Circuit source · line 21 · raw

Data

threshold: failures in a row, each inside window ms of the newest, that open the circuit. cooldown: ms it stays open. probes: attempts allowed at once while half-open.

type State source · line 26 · raw

Data

Closed: the failures since the last success that are still inside the window, newest first. Open: no attempt before until. Half: probes in flight.

type Breaker source · line 31 · raw

Data

type Outcome source · line 37 · raw

Data

Settled: a success, or a failure that another try would repeat. Unsafe: a transient failure of a request that must not repeat. Transient: another try can help; after is the server's wait in ms.

type Policy source · line 44 · raw

Data

attempts: tries in one layer, the first one included. base: the first backoff in ms. cap: the longest wait in ms. deadline: ms from the start of the operation to its deadline. None: no deadline.

type Plan source · line 47 · raw

Data

Definitions

def Budget.new source · line 53 · raw

@+attempts:Nat -> @+now:Nat -> @ms:Maybe<&2, Nat> -> Budget

def Budget.late source · line 60 · raw

@+now:Nat -> @d:Maybe<&2, Nat> -> Bool

def prune source · line 70 · raw

@+now:Nat -> @+window:Nat -> @fs:List<&2, Nat> -> List<&2, Nat>

The failure times still inside the window: now < t + window. Newest first, so the first old time ends the list.

def Circuit.probes source · line 77 · raw

@c:Circuit -> Nat

def Circuit.cooldown source · line 81 · raw

@c:Circuit -> Nat

def half.admit source · line 85 · raw

@go:Bool -> @+k:Nat -> Pair(State, Bool)

def open.admit source · line 92 · raw

@early:Bool -> @+p:Nat -> @+u:Nat -> Pair(State, Bool)

def State.admit source · line 101 · raw

@+c:Circuit -> @s:State -> @+now:Nat -> Pair(State, Bool)

Closed admits. Open admits nothing before until; at or after until it turns half-open and admits a probe. Half-open admits while fewer than probes are in flight.

def closed.trip source · line 110 · raw

@under:Bool -> @fs:List<&2, Nat> -> @+until:Nat -> State

def closed.fail source · line 117 · raw

@+c:Circuit -> @fs:List<&2, Nat> -> @+now:Nat -> State

def State.done source · line 125 · raw

@+c:Circuit -> @s:State -> @+now:Nat -> @failed:Bool -> State

A closed success clears the failures. A closed failure opens the circuit when the window then holds threshold failures. A half-open success closes it; a half-open failure opens it again for cooldown. An attempt that ends while open changes nothing.

def Breaker.new source · line 142 · raw

@c:Circuit -> Breaker

def Breaker.on source · line 145 · raw

@+c:Circuit -> @x:Pair(State, Bool) -> Pair(Breaker, Bool)

def Breaker.admit source · line 149 · raw

@br:Breaker -> @+now:Nat -> Pair(Breaker, Bool)

def Breaker.done source · line 156 · raw

@br:Breaker -> @+now:Nat -> @failed:Bool -> Breaker

def admit.ok source · line 165 · raw

@ok:Bool -> @br:Breaker -> @+p:Nat -> @d:Maybe<&2, Nat> -> Pair(Breaker, Pair(Budget, Gate))

def admit.breaker source · line 172 · raw

@x:Pair(Breaker, Bool) -> @+p:Nat -> @d:Maybe<&2, Nat> -> Pair(Breaker, Pair(Budget, Gate))

def admit.late source · line 176 · raw

@late:Bool -> @br:Breaker -> @left:Nat -> @d:Maybe<&2, Nat> -> @+now:Nat -> Pair(Breaker, Pair(Budget, Gate))

def admit source · line 189 · raw

@br:Breaker -> @b:Budget -> @+now:Nat -> Pair(Breaker, Pair(Budget, Gate))

Ask to start one attempt at now. The deadline is checked first, then the budget, then the breaker. Only GateGo takes one attempt from the budget.

def delay source · line 196 · raw

@n:Nat -> @+base:Nat -> @+cap:Nat -> Nat

min(cap, base * 2^n), doubled one step at a time, so no step passes cap.

def jitter source · line 205 · raw

@+d:Nat -> @+r:Nat -> Nat

Equal jitter: d / 2, plus r mod (d / 2 + 1). The wait is in [d / 2, d] for every r.

def wait source · line 210 · raw

@after:Maybe<&2, Nat> -> @p:Policy -> @+n:Nat -> @+r:Nat -> Nat

The wait before retry n (0 first): the server's wait when it gave one, else the jittered backoff. At most cap.

def plan.left source · line 219 · raw

@left:Nat -> @+w:Nat -> @d:Maybe<&2, Nat> -> @+now:Nat -> Plan

def plan.at source · line 226 · raw

@+w:Nat -> @b:Budget -> @+now:Nat -> Plan

def plan source · line 232 · raw

@o:Outcome -> @p:Policy -> @b:Budget -> @+n:Nat -> @+now:Nat -> @+r:Nat -> Plan

After an attempt ends at now: stop, or wait ms and then ask admit again. Settled and Unsafe always stop. A transient outcome stops when the budget is spent or the wait would reach the deadline.

def failed source · line 242 · raw

@o:Outcome -> Bool

Unsafe and Transient count as failures for the breaker.