Skip to main content

rskit_provider/
tower_bridge.rs

1//! Bridge between `tower::Service` and [`RequestResponse`].
2//!
3//! Wraps any `tower::Service<I, Response=O, Error=AppError>` so it can be
4//! used wherever `RequestResponse<I, O>` is expected.
5
6use std::marker::PhantomData;
7use std::sync::Arc;
8
9use parking_lot::Mutex;
10use rskit_errors::AppResult;
11use tower::ServiceExt;
12
13use crate::traits::{Provider, RequestResponse};
14
15/// Wraps a `tower::Service` as a `RequestResponse` provider.
16///
17/// The inner service is kept behind a `Mutex` because `tower::Service::call`
18/// requires `&mut self`.
19pub struct TowerProvider<S, I, O> {
20    name: &'static str,
21    service: Arc<Mutex<S>>,
22    _phantom: PhantomData<fn(I) -> O>,
23}
24
25impl<S, I, O> TowerProvider<S, I, O>
26where
27    S: tower::Service<I, Response = O, Error = rskit_errors::AppError> + Send + Clone + 'static,
28    S::Future: Send + 'static,
29    I: Send + 'static,
30    O: Send + 'static,
31{
32    /// Create a new [`TowerProvider`] wrapping `service` with the given `name`.
33    pub fn new(name: &'static str, service: S) -> Self {
34        Self {
35            name,
36            service: Arc::new(Mutex::new(service)),
37            _phantom: PhantomData,
38        }
39    }
40}
41
42#[async_trait::async_trait]
43impl<S, I, O> Provider for TowerProvider<S, I, O>
44where
45    S: tower::Service<I, Response = O, Error = rskit_errors::AppError> + Send + Clone + 'static,
46    S::Future: Send + 'static,
47    I: Send + 'static,
48    O: Send + 'static,
49{
50    fn name(&self) -> &'static str {
51        self.name
52    }
53}
54
55#[async_trait::async_trait]
56impl<S, I, O> RequestResponse<I, O> for TowerProvider<S, I, O>
57where
58    S: tower::Service<I, Response = O, Error = rskit_errors::AppError> + Send + Clone + 'static,
59    S::Future: Send + 'static,
60    I: Send + 'static,
61    O: Send + 'static,
62{
63    async fn execute(&self, input: I) -> AppResult<O> {
64        // Clone the inner service to avoid holding the lock across .await
65        let mut svc = self.service.lock().clone();
66        svc.ready().await?;
67        svc.call(input).await
68    }
69}