do-over 0.1.0

Async resilience policies for Rust inspired by Polly
Documentation
//! Core policy trait for resilience patterns.
//!
//! All resilience policies in do_over implement the [`Policy`] trait, which
//! provides a uniform interface for executing operations with resilience.

use std::future::Future;

/// The core trait implemented by all resilience policies.
///
/// `Policy<E>` provides a uniform interface for wrapping async operations
/// with resilience patterns like retry, circuit breaker, timeout, etc.
///
/// # Type Parameter
///
/// * `E` - The error type that the policy can produce
///
/// # Examples
///
/// Using a policy to execute an operation:
///
/// ```rust
/// use do_over::{policy::Policy, retry::RetryPolicy};
/// use std::time::Duration;
///
/// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
/// let policy = RetryPolicy::fixed(3, Duration::from_millis(100));
///
/// let result = policy.execute(|| async {
///     // Your async operation here
///     Ok::<_, std::io::Error>("success")
/// }).await?;
/// # Ok(())
/// # }
/// ```
///
/// # Implementing Policy
///
/// To create a custom policy, implement this trait:
///
/// ```rust
/// use do_over::policy::Policy;
/// use std::future::Future;
///
/// struct LoggingPolicy;
///
/// #[async_trait::async_trait]
/// impl<E: Send + Sync> Policy<E> for LoggingPolicy {
///     async fn execute<F, Fut, T>(&self, f: F) -> Result<T, E>
///     where
///         F: Fn() -> Fut + Send + Sync,
///         Fut: Future<Output = Result<T, E>> + Send,
///         T: Send,
///     {
///         println!("Executing operation...");
///         let result = f().await;
///         println!("Operation completed");
///         result
///     }
/// }
/// ```
#[async_trait::async_trait]
pub trait Policy<E>: Send + Sync {
    /// Execute an async operation with this policy's resilience behavior.
    ///
    /// # Arguments
    ///
    /// * `f` - A closure that returns a Future producing `Result<T, E>`
    ///
    /// # Returns
    ///
    /// The result of the operation, potentially modified by the policy
    /// (e.g., retried, timed out, etc.)
    async fn execute<F, Fut, T>(&self, f: F) -> Result<T, E>
    where
        F: Fn() -> Fut + Send + Sync,
        Fut: Future<Output = Result<T, E>> + Send,
        T: Send;
}