persevero
Execute fallible operations multiple times.
Installation
gleam add persevero@1
Usage
A simple example:
import gleam/http/request
import gleam/httpc
import gleam/io
import persevero
pub fn main() {
let assert Ok(request) = request.to("https://www.apple.com")
let response = {
use <- persevero.execute(
wait_stream: persevero.exponential_backoff(50, 2),
allow: persevero.all_errors,
mode: persevero.MaxAttempts(3),
)
httpc.send(request)
}
case response {
Ok(response) if response.status == 200 -> io.debug("Give me #prawducks. π")
_ -> io.debug("Guess I'll dev on Linux. π")
}
}
A ridiculous example:
import gleam/http/request
import gleam/httpc
import gleam/io
import persevero
pub fn main() {
let assert Ok(request) = request.to("https://www.apple.com")
let response =
persevero.custom_backoff(wait_time: 1000, next_wait_time: fn(previous) {
{ previous + 100 } * 2
})
|> persevero.apply_multiplier(3)
|> persevero.apply_jitter(20)
|> persevero.apply_cap(10_000)
|> persevero.apply_constant(7)
|> persevero.execute(
allow: fn(error) {
case error {
httpc.InvalidUtf8Response -> True
_ -> False
}
},
mode: persevero.MaxAttempts(10),
operation: fn() { httpc.send(request) },
)
case response {
Ok(response) if response.status == 200 -> io.debug("Give me #prawducks. π")
_ -> io.debug("Guess I'll dev on Linux. π")
}
}
Instead of defining a maximum number of attempts, you can use an expiry mode. This will cause the operation to cease retrying after a specified duration. Itβs important to note that the expiry mode will not interrupt an operation that is currently in progress; the ongoing attempt will be allowed to complete before the operation is considered expired.
use <- persevero.execute(
wait_stream: persevero.constant_backoff(100),
allow: persevero.all_errors,
mode: persevero.Expiry(10_000),
)
Use raw yielder
s for
ultimate wait stream manipulation:
use <- persevero.execute(
wait_stream: yielder.range(1, 100) |> yielder.intersperse(0),
allow: persevero.all_errors,
mode: persevero.MaxAttempts(3),
)
Note that persevero
generates a final wait stream with a 0 value at the
beginning, in the execute
function, after all transformations to the stream
have been applied, so the first attempt will never sleep. You do not need to
account for this in your custom wait stream.
Targets
persevero
supports the Erlang target.