gust-stdlib 0.2.0

Standard library of reusable Gust state machines (circuit breaker, retry, saga, rate limiter, and more)
Documentation
machine Retry<T> {
    state Ready(max_attempts: i64, base_delay_ms: i64, max_delay_ms: i64, jitter_pct: i64)
    state Attempting(attempt: i64, max_attempts: i64, base_delay_ms: i64, max_delay_ms: i64, jitter_pct: i64)
    state Waiting(attempt: i64, delay_ms: i64, max_attempts: i64, base_delay_ms: i64, max_delay_ms: i64, jitter_pct: i64)
    state Succeeded(value: T, attempts: i64)
    state Failed(error: String, attempts: i64)

    transition begin: Ready -> Attempting
    transition run: Attempting -> Waiting | Succeeded | Failed
    transition wait_complete: Waiting -> Attempting

    async effect execute_operation() -> Result<T, String>
    async effect sleep_ms(duration_ms: i64) -> i64
    effect compute_backoff(base_delay_ms: i64, attempt: i64, max_delay_ms: i64, jitter_pct: i64) -> i64

    on begin() {
        goto Attempting(1, max_attempts, base_delay_ms, max_delay_ms, jitter_pct);
    }

    async on run() {
        let result = perform execute_operation();
        match result {
            Ok(value) => {
                goto Succeeded(value, attempt);
            }
            Err(err) => {
                if attempt >= max_attempts {
                    goto Failed(err, attempt);
                } else {
                    let delay = perform compute_backoff(base_delay_ms, attempt, max_delay_ms, jitter_pct);
                    goto Waiting(attempt, delay, max_attempts, base_delay_ms, max_delay_ms, jitter_pct);
                }
            }
        }
    }

    async on wait_complete() {
        let _slept = perform sleep_ms(delay_ms);
        goto Attempting(attempt + 1, max_attempts, base_delay_ms, max_delay_ms, jitter_pct);
    }
}