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>`
4//! so it can be 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` requires `&mut self`.
18pub struct TowerProvider<S, I, O> {
19    name: &'static str,
20    service: Arc<Mutex<S>>,
21    _phantom: PhantomData<fn(I) -> O>,
22}
23
24impl<S, I, O> TowerProvider<S, I, O>
25where
26    S: tower::Service<I, Response = O, Error = rskit_errors::AppError> + Send + Clone + 'static,
27    S::Future: Send + 'static,
28    I: Send + 'static,
29    O: Send + 'static,
30{
31    /// Create a new [`TowerProvider`] wrapping `service` with the given `name`.
32    pub fn new(name: &'static str, service: S) -> Self {
33        Self {
34            name,
35            service: Arc::new(Mutex::new(service)),
36            _phantom: PhantomData,
37        }
38    }
39}
40
41#[async_trait::async_trait]
42impl<S, I, O> Provider for TowerProvider<S, I, O>
43where
44    S: tower::Service<I, Response = O, Error = rskit_errors::AppError> + Send + Clone + 'static,
45    S::Future: Send + 'static,
46    I: Send + 'static,
47    O: Send + 'static,
48{
49    fn name(&self) -> &'static str {
50        self.name
51    }
52}
53
54#[async_trait::async_trait]
55impl<S, I, O> RequestResponse<I, O> for TowerProvider<S, I, O>
56where
57    S: tower::Service<I, Response = O, Error = rskit_errors::AppError> + Send + Clone + 'static,
58    S::Future: Send + 'static,
59    I: Send + 'static,
60    O: Send + 'static,
61{
62    async fn execute(&self, input: I) -> AppResult<O> {
63        // Clone the inner service to avoid holding the lock across .await
64        let mut svc = self.service.lock().clone();
65        svc.ready().await?;
66        svc.call(input).await
67    }
68}