use crate::cook::execution::command::RetryConfig;
use std::time::Duration;
use stillwater::retry::RetryPolicy;
use tracing::warn;
pub fn default_claude_retry_policy() -> RetryPolicy {
RetryPolicy::exponential(Duration::from_secs(5))
.with_max_retries(5)
.with_jitter(0.25)
.with_max_delay(Duration::from_secs(120))
}
pub fn shell_retry_policy() -> RetryPolicy {
RetryPolicy::exponential(Duration::from_secs(2)).with_max_retries(2)
}
pub fn parse_retry_policy(config: Option<&RetryConfig>) -> RetryPolicy {
match config {
Some(cfg) => {
let base = match cfg.strategy.as_str() {
"constant" => RetryPolicy::constant(cfg.initial_delay),
"linear" => RetryPolicy::linear(cfg.initial_delay),
"exponential" => RetryPolicy::exponential(cfg.initial_delay),
_ => {
warn!(
"Unknown retry strategy '{}', using exponential",
cfg.strategy
);
RetryPolicy::exponential(cfg.initial_delay)
}
};
let mut policy = base.with_max_retries(cfg.max_attempts);
if let Some(jitter) = cfg.jitter {
policy = policy.with_jitter(jitter);
}
policy = policy.with_max_delay(cfg.max_delay);
policy
}
None => default_claude_retry_policy(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_claude_retry_policy() {
let _policy = default_claude_retry_policy();
}
#[test]
fn test_shell_retry_policy_configuration() {
let _policy = shell_retry_policy();
}
#[test]
fn test_parse_retry_policy_with_config() {
let config = RetryConfig {
strategy: "exponential".to_string(),
max_attempts: 3,
initial_delay: Duration::from_secs(2),
max_delay: Duration::from_secs(30),
jitter: Some(0.1),
exponential_base: None,
};
let _policy = parse_retry_policy(Some(&config));
}
#[test]
fn test_parse_retry_policy_constant_strategy() {
let config = RetryConfig {
strategy: "constant".to_string(),
max_attempts: 5,
initial_delay: Duration::from_secs(1),
max_delay: Duration::from_secs(60),
jitter: None,
exponential_base: None,
};
let _policy = parse_retry_policy(Some(&config));
}
#[test]
fn test_parse_retry_policy_linear_strategy() {
let config = RetryConfig {
strategy: "linear".to_string(),
max_attempts: 4,
initial_delay: Duration::from_secs(3),
max_delay: Duration::from_secs(90),
jitter: Some(0.2),
exponential_base: None,
};
let _policy = parse_retry_policy(Some(&config));
}
#[test]
fn test_parse_retry_policy_unknown_strategy_falls_back() {
let config = RetryConfig {
strategy: "unknown".to_string(),
max_attempts: 3,
initial_delay: Duration::from_secs(5),
max_delay: Duration::from_secs(60),
jitter: None,
exponential_base: None,
};
let _policy = parse_retry_policy(Some(&config));
}
#[test]
fn test_parse_retry_policy_none_uses_default() {
let _policy = parse_retry_policy(None);
let _default = default_claude_retry_policy();
}
}