retry.ry
module retry
purpose: Retry a failing action with exponential backoff and jitter.
import std.time
import std.random
public type GaveUp
purpose: The action still failed after the last attempt.
has attempts: Integer
has last_error: Text
end
public function with_backoff(
action: function() returns Outcome or fails with Failure,
attempts: Integer
)
returns Outcome
or fails with GaveUp
needs time, random
for any Outcome, Failure where Failure can ToText
purpose: Run the action until it succeeds, waiting roughly twice as long after each failure.
tags: resilience, backoff
let mutable last_error be "no attempt was made"
let mutable delay_ms be 100
for each attempt from 1 to attempts
match action()
when success(outcome) then return outcome
when failure(error) then
change last_error to "attempt {attempt}: {error.to_text()}"
let jitter_ms be random.integer(lowest: 0, highest: delay_ms.quotient(4))
time.sleep(time.milliseconds(delay_ms + jitter_ms))
change delay_ms to delay_ms * 2
end
end
fail with GaveUp(attempts: attempts, last_error: last_error)
end