Skip to main content

clawdesk-infra

Infrastructure utilities used across the ClawDesk workspace. Provides retry logic with configurable backoff strategies, timeout wrappers, and other cross-cutting infrastructure patterns.

Dependencies

Internal: clawdesk-types

External: tokio, tracing, thiserror

Modules

ModuleDescription
retryRetry execution with configurable policies
backoffBackoff strategies (exponential, linear, constant)

Key Types

/// Retry policy configuration
#[derive(Debug, Clone)]
pub struct RetryPolicy {
pub max_retries: u32,
pub backoff: BackoffStrategy,
pub retry_on: RetryCondition,
}

/// Backoff strategy between retries
#[derive(Debug, Clone)]
pub enum BackoffStrategy {
/// Constant delay between retries
Constant { delay_ms: u64 },
/// Linear increasing delay
Linear { initial_ms: u64, increment_ms: u64 },
/// Exponential backoff with optional jitter
Exponential {
initial_ms: u64,
multiplier: f64,
max_delay_ms: u64,
jitter: bool,
},
}

/// Condition for retrying
#[derive(Debug, Clone)]
pub enum RetryCondition {
Always,
OnError,
Custom(fn(&dyn std::error::Error) -> bool),
}

/// Execute a future with retry policy
pub async fn with_retry<F, Fut, T, E>(
policy: &RetryPolicy,
operation: F,
) -> Result<T, E>
where
F: Fn() -> Fut,
Fut: std::future::Future<Output = Result<T, E>>,
E: std::fmt::Debug,
{
// Retry loop with backoff
}

Example Usage

use clawdesk_infra::{with_retry, RetryPolicy, BackoffStrategy};

let policy = RetryPolicy {
max_retries: 3,
backoff: BackoffStrategy::Exponential {
initial_ms: 100,
multiplier: 2.0,
max_delay_ms: 5000,
jitter: true,
},
retry_on: RetryCondition::OnError,
};

let result = with_retry(&policy, || async {
provider.chat(&model, &messages, &options).await
}).await?;
tip

Use exponential backoff with jitter for external API calls to avoid thundering herd problems during provider outages.