1use borrow_bag::{Handle, Lookup};
5use futures_util::future::{self, FutureExt};
6use log::trace;
7use std::panic::RefUnwindSafe;
8use std::pin::Pin;
9
10use crate::handler::HandlerFuture;
11use crate::middleware::chain::NewMiddlewareChain;
12use crate::pipeline::set::PipelineSet;
13use crate::pipeline::Pipeline;
14use crate::state::{request_id, State};
15
16pub trait PipelineHandleChain<P>: RefUnwindSafe {
30 fn call<F>(&self, pipelines: &PipelineSet<P>, state: State, f: F) -> Pin<Box<HandlerFuture>>
33 where
34 F: FnOnce(State) -> Pin<Box<HandlerFuture>> + Send + 'static;
35}
36
37impl<P, T, N, U> PipelineHandleChain<P> for (Handle<Pipeline<T>, N>, U)
39where
40 T: NewMiddlewareChain,
41 T::Instance: Send + 'static,
42 U: PipelineHandleChain<P>,
43 P: Lookup<Pipeline<T>, N>,
44 N: RefUnwindSafe,
45{
46 fn call<F>(&self, pipelines: &PipelineSet<P>, state: State, f: F) -> Pin<Box<HandlerFuture>>
47 where
48 F: FnOnce(State) -> Pin<Box<HandlerFuture>> + Send + 'static,
49 {
50 let (handle, ref chain) = *self;
51 match pipelines.borrow(handle).construct() {
52 Ok(p) => chain.call(pipelines, state, move |state| p.call(state, f)),
53 Err(e) => {
54 trace!("[{}] error borrowing pipeline", request_id(&state));
55 future::err((state, e.into())).boxed()
56 }
57 }
58 }
59}
60
61impl<P> PipelineHandleChain<P> for () {
63 fn call<F>(&self, _: &PipelineSet<P>, state: State, f: F) -> Pin<Box<HandlerFuture>>
64 where
65 F: FnOnce(State) -> Pin<Box<HandlerFuture>> + Send + 'static,
66 {
67 trace!("[{}] start pipeline", request_id(&state));
68 f(state)
69 }
70}