AsyncErrorPipeline

Struct AsyncErrorPipeline 

Source
pub struct AsyncErrorPipeline<Fut> { /* private fields */ }
Expand description

Async error pipeline for chainable error handling.

This is the async counterpart to ErrorPipeline, providing fluent, chainable error context accumulation for async operations.

§Examples

§Basic Usage

use error_rail::prelude_async::*;

#[derive(Debug)]
struct Data;

#[derive(Debug)]
struct ApiError;

async fn fetch_data(_id: u64) -> Result<Data, ApiError> {
    Err(ApiError)
}

async fn example(id: u64) -> BoxedResult<Data, ApiError> {
    AsyncErrorPipeline::new(fetch_data(id))
        .with_context("fetching data")
        .finish_boxed()
        .await
}

§With Multiple Contexts

use error_rail::prelude_async::*;

#[derive(Debug)]
struct Order;

#[derive(Debug)]
struct OrderError;

async fn load_order(_order_id: u64) -> Result<Order, OrderError> {
    Err(OrderError)
}

async fn process_order(order_id: u64) -> BoxedResult<Order, OrderError> {
    AsyncErrorPipeline::new(load_order(order_id))
        .with_context(group!(
            message("loading order"),
            metadata("order_id", format!("{}", order_id))
        ))
        .finish_boxed()
        .await
}

Implementations§

Source§

impl<Fut> AsyncErrorPipeline<Fut>

Source

pub fn new(future: Fut) -> Self

Creates a new async error pipeline from a future.

§Arguments
  • future - A future that returns a Result<T, E>
§Examples
use error_rail::async_ext::AsyncErrorPipeline;

let pipeline = AsyncErrorPipeline::new(async { Ok::<_, &str>(42) });
Source

pub fn finish(self) -> Fut

Completes the pipeline and returns the inner future.

This method consumes the pipeline and returns a future that produces the original Result<T, E>.

§Examples
use error_rail::async_ext::AsyncErrorPipeline;

async fn example() -> Result<i32, &'static str> {
    AsyncErrorPipeline::new(async { Ok(42) })
        .finish()
        .await
}
Source§

impl<Fut, T, E> AsyncErrorPipeline<Fut>
where Fut: Future<Output = Result<T, E>>,

Source

pub fn with_context<C>( self, context: C, ) -> AsyncErrorPipeline<impl Future<Output = Result<T, ComposableError<E>>>>

Adds a context that will be attached to any error.

The context is only attached when an error occurs.

Note: if you pass an already-formatted String (e.g. format!(...)), that formatting still happens eagerly before calling .with_context(...).

§Arguments
  • context - Any type implementing IntoErrorContext
§Examples
use error_rail::async_ext::AsyncErrorPipeline;

let pipeline = AsyncErrorPipeline::new(async { Err::<(), _>("error") })
    .with_context("operation context");
Source

pub fn mark_transient_if<F>( self, classifier: F, ) -> AsyncErrorPipeline<impl Future<Output = Result<T, MarkedError<E, F>>>>
where F: Fn(&E) -> bool + Send + 'static, E: Send + 'static, T: Send + 'static,

Marks the error as transient or permanent based on a closure.

This allows for flexible retry control without implementing the crate::traits::TransientError trait for the error type.

§Arguments
  • classifier - A closure that returns true if the error should be treated as transient
§Examples
use error_rail::prelude_async::*;
use error_rail::types::MarkedError;

async fn example() -> Result<(), MarkedError<String, impl Fn(&String) -> bool>> {
    AsyncErrorPipeline::new(async { Err("error".to_string()) })
        .mark_transient_if(|e: &String| e.contains("error"))
        .finish()
        .await
}
Source

pub fn with_context_fn<F, C>( self, f: F, ) -> AsyncErrorPipeline<impl Future<Output = Result<T, ComposableError<E>>>>
where F: FnOnce() -> C, C: IntoErrorContext,

Adds a lazily-evaluated context using a closure.

The closure is only called when an error occurs, avoiding any computation on the success path.

§Arguments
  • f - A closure that produces the error context
§Examples
use error_rail::async_ext::AsyncErrorPipeline;

#[derive(Debug)]
struct User;

#[derive(Debug)]
struct ApiError;

async fn fetch_user(_id: u64) -> Result<User, ApiError> {
    Err(ApiError)
}

let id = 42u64;
let _pipeline = AsyncErrorPipeline::new(fetch_user(id))
    .with_context_fn(|| format!("user_id: {}", id));
Source§

impl<Fut, T, E> AsyncErrorPipeline<Fut>
where Fut: Future<Output = Result<T, ComposableError<E>>>,

Source

pub async fn finish_boxed(self) -> Result<T, Box<ComposableError<E>>>

Completes the pipeline and returns a boxed error result.

This is the recommended way to finish a pipeline when returning from a function, as it provides minimal stack footprint.

§Examples
use error_rail::prelude_async::*;

async fn example() -> BoxedResult<i32, &'static str> {
    AsyncErrorPipeline::new(async { Err("error") })
        .with_context("operation failed")
        .finish_boxed()
        .await
}
Source

pub fn map_err<F, E2>( self, f: F, ) -> AsyncErrorPipeline<impl Future<Output = Result<T, ComposableError<E2>>>>

Maps the error type using a transformation function.

§Arguments
  • f - A function that transforms ComposableError<E> to ComposableError<E2>
§Examples
use error_rail::async_ext::AsyncErrorPipeline;

let pipeline = AsyncErrorPipeline::new(async { Err::<(), _>("error") })
    .with_context("context")
    .map_err(|e| e.map_core(|_| "new error"));

Auto Trait Implementations§

§

impl<Fut> Freeze for AsyncErrorPipeline<Fut>
where Fut: Freeze,

§

impl<Fut> RefUnwindSafe for AsyncErrorPipeline<Fut>
where Fut: RefUnwindSafe,

§

impl<Fut> Send for AsyncErrorPipeline<Fut>
where Fut: Send,

§

impl<Fut> Sync for AsyncErrorPipeline<Fut>
where Fut: Sync,

§

impl<Fut> Unpin for AsyncErrorPipeline<Fut>
where Fut: Unpin,

§

impl<Fut> UnwindSafe for AsyncErrorPipeline<Fut>
where Fut: UnwindSafe,

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more