Skip to main content

hyper_util/client/pool/
singleton.rs

1//! Singleton pools
2//!
3//! This ensures that only one active connection is made.
4//!
5//! The singleton pool wraps a `MakeService<T, Req>` so that it only produces a
6//! single `Service<Req>`. It bundles all concurrent calls to it, so that only
7//! one connection is made. All calls to the singleton will return a clone of
8//! the inner service once established.
9//!
10//! This fits the HTTP/2 case well.
11//!
12//! ## Example
13//!
14//! ```rust,ignore
15//! let mut pool = Singleton::new(some_make_svc);
16//!
17//! let svc1 = pool.call(some_dst).await?;
18//!
19//! let svc2 = pool.call(some_dst).await?;
20//! // svc1 == svc2
21//! ```
22
23use std::sync::{Arc, Mutex};
24use std::task::{self, Poll};
25
26use tower_service::Service;
27
28use self::internal::{SingletonError, SingletonFuture, State};
29
30type BoxError = Box<dyn std::error::Error + Send + Sync>;
31
32#[cfg(docsrs)]
33pub use self::internal::Singled;
34
35/// A singleton pool over an inner service.
36///
37/// The singleton wraps an inner service maker, bundling all calls to ensure
38/// only one service is created. Once made, it returns clones of the made
39/// service.
40#[derive(Debug)]
41pub struct Singleton<M, Dst>
42where
43    M: Service<Dst>,
44{
45    mk_svc: M,
46    state: Arc<Mutex<State<M::Future, M::Response>>>,
47}
48
49impl<M, Target> Singleton<M, Target>
50where
51    M: Service<Target>,
52    M::Response: Clone,
53{
54    /// Create a new singleton pool over an inner make service.
55    pub fn new(mk_svc: M) -> Self {
56        Singleton {
57            mk_svc,
58            state: Arc::new(Mutex::new(State::Empty)),
59        }
60    }
61
62    // pub fn clear? cancel?
63
64    /// Retains the inner made service if specified by the predicate.
65    pub fn retain<F>(&mut self, mut predicate: F)
66    where
67        F: FnMut(&mut M::Response) -> bool,
68    {
69        let mut locked = self.state.lock().unwrap();
70        match *locked {
71            State::Empty => {}
72            State::Making(..) => {}
73            State::Made(ref mut svc) => {
74                if !predicate(svc) {
75                    *locked = State::Empty;
76                }
77            }
78        }
79    }
80
81    /// Returns whether this singleton pool is empty.
82    ///
83    /// If this pool has created a shared instance, or is currently in the
84    /// process of creating one, this returns false.
85    pub fn is_empty(&self) -> bool {
86        matches!(*self.state.lock().unwrap(), State::Empty)
87    }
88}
89
90impl<M, Target> Service<Target> for Singleton<M, Target>
91where
92    M: Service<Target>,
93    M::Response: Clone,
94    M::Error: Into<BoxError>,
95{
96    type Response = internal::Singled<M::Future, M::Response>;
97    type Error = SingletonError;
98    type Future = SingletonFuture<M::Future, M::Response>;
99
100    fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
101        if let State::Empty = *self.state.lock().unwrap() {
102            return self
103                .mk_svc
104                .poll_ready(cx)
105                .map_err(|e| SingletonError::new(e.into()));
106        }
107        Poll::Ready(Ok(()))
108    }
109
110    fn call(&mut self, dst: Target) -> Self::Future {
111        let mut locked = self.state.lock().unwrap();
112        match *locked {
113            State::Empty => {
114                let fut = self.mk_svc.call(dst);
115                let mut batch = internal::Batch::new(fut);
116                let id = batch.register_driver();
117                *locked = State::Making(batch);
118                SingletonFuture::Participating {
119                    id,
120                    state: self.state.clone(),
121                    rx: None,
122                }
123            }
124            State::Making(ref mut batch) => {
125                let (id, rx) = batch.register_waiter();
126                SingletonFuture::Participating {
127                    id,
128                    state: self.state.clone(),
129                    rx: Some(rx),
130                }
131            }
132            State::Made(ref svc) => SingletonFuture::Made {
133                svc: Some(svc.clone()),
134                state: Arc::downgrade(&self.state),
135            },
136        }
137    }
138}
139
140impl<M, Target> Clone for Singleton<M, Target>
141where
142    M: Service<Target> + Clone,
143{
144    fn clone(&self) -> Self {
145        Self {
146            mk_svc: self.mk_svc.clone(),
147            state: self.state.clone(),
148        }
149    }
150}
151
152// Holds some "pub" items that otherwise shouldn't be public.
153/// Baton-passing implementation.
154///
155/// While a singleton service is being made, one participating future is
156/// responsible for driving that work. If that future is canceled, the work
157/// should not be canceled for every other caller waiting on the same service.
158/// Baton-passing lets another participant take over, so cancellation remains
159/// local to the future that was dropped.
160mod internal {
161    use std::fmt;
162    use std::pin::Pin;
163    use std::sync::{Arc, Mutex, Weak};
164    use std::task::{self, Poll, Waker};
165
166    use tokio::sync::oneshot;
167    use tower_service::Service;
168
169    use super::BoxError;
170
171    pub enum SingletonFuture<F, S> {
172        Participating {
173            id: WaiterId,
174            state: Arc<Mutex<State<F, S>>>,
175            rx: Option<oneshot::Receiver<Result<S, SharedError>>>,
176        },
177        Made {
178            svc: Option<S>,
179            state: Weak<Mutex<State<F, S>>>,
180        },
181    }
182
183    impl<F, S> Unpin for SingletonFuture<F, S> {}
184
185    // XXX: pub because of the enum SingletonFuture
186    pub enum State<F, S> {
187        Empty,
188        Making(Batch<F, S>),
189        Made(S),
190    }
191
192    impl<F, S: fmt::Debug> fmt::Debug for State<F, S> {
193        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194            match self {
195                State::Empty => f.write_str("Empty"),
196                State::Making(..) => f.write_str("Making"),
197                State::Made(svc) => f.debug_tuple("Made").field(svc).finish(),
198            }
199        }
200    }
201
202    // XXX: pub because of the enum SingletonFuture
203    pub struct Batch<F, S> {
204        future: Option<Pin<Box<F>>>,
205        next_id: WaiterId,
206        driver: Option<Driver>,
207        waiters: Vec<Waiter<S>>,
208    }
209
210    #[derive(Copy, Clone, Debug, Eq, PartialEq)]
211    pub struct WaiterId(usize);
212
213    struct Driver {
214        id: WaiterId,
215        waker: Option<Waker>,
216    }
217
218    struct Waiter<S> {
219        id: WaiterId,
220        waker: Option<Waker>,
221        tx: oneshot::Sender<Result<S, SharedError>>,
222    }
223
224    /// A cached service returned from a [`Singleton`].
225    ///
226    /// Implements `Service` by delegating to the inner service. If
227    /// `poll_ready` returns an error, this will clear the cache in the related
228    /// `Singleton`.
229    ///
230    /// [`Singleton`]: super::Singleton
231    ///
232    /// # Unnameable
233    ///
234    /// This type is normally unnameable, forbidding naming of the type within
235    /// code. The type is exposed in the documentation to show which methods
236    /// can be publicly called.
237    #[derive(Debug)]
238    pub struct Singled<F, S> {
239        inner: S,
240        state: Weak<Mutex<State<F, S>>>,
241    }
242
243    impl<F, S, E> Future for SingletonFuture<F, S>
244    where
245        F: Future<Output = Result<S, E>>,
246        E: Into<BoxError>,
247        S: Clone,
248    {
249        type Output = Result<Singled<F, S>, SingletonError>;
250
251        fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
252            match &mut *self {
253                SingletonFuture::Participating { id, state, rx } => {
254                    if let Some(receiver) = rx.as_mut() {
255                        match Pin::new(receiver).poll(cx) {
256                            Poll::Ready(Ok(Ok(svc))) => {
257                                return Poll::Ready(Ok(Singled::new(svc, Arc::downgrade(state))));
258                            }
259                            Poll::Ready(Ok(Err(err))) => {
260                                return Poll::Ready(Err(SingletonError(err)));
261                            }
262                            Poll::Ready(Err(_canceled)) => {
263                                *rx = None;
264                            }
265                            Poll::Pending => {}
266                        }
267                    }
268
269                    let state_weak = Arc::downgrade(state);
270                    let mut locked = state.lock().unwrap();
271
272                    match &mut *locked {
273                        State::Making(batch) => match batch.poll(*id, cx) {
274                            Poll::Pending => Poll::Pending,
275                            Poll::Ready(Ok(svc)) => {
276                                batch.send_result(Ok(svc.clone()));
277                                *locked = State::Made(svc.clone());
278                                Poll::Ready(Ok(Singled::new(svc, state_weak)))
279                            }
280                            Poll::Ready(Err(err)) => {
281                                batch.send_result(Err(err.clone()));
282                                *locked = State::Empty;
283                                Poll::Ready(Err(SingletonError(err)))
284                            }
285                        },
286                        State::Made(svc) => Poll::Ready(Ok(Singled::new(svc.clone(), state_weak))),
287                        State::Empty => {
288                            unreachable!("singleton participant polled after making was canceled")
289                        }
290                    }
291                }
292                SingletonFuture::Made { svc, state } => {
293                    Poll::Ready(Ok(Singled::new(svc.take().unwrap(), state.clone())))
294                }
295            }
296        }
297    }
298
299    impl<F, S> Drop for SingletonFuture<F, S> {
300        fn drop(&mut self) {
301            if let SingletonFuture::Participating { id, state, .. } = self {
302                if let Ok(mut locked) = state.lock() {
303                    if let State::Making(batch) = &mut *locked {
304                        if batch.remove(*id) {
305                            *locked = State::Empty;
306                        }
307                    }
308                }
309            }
310        }
311    }
312
313    impl<F, S> Singled<F, S> {
314        fn new(inner: S, state: Weak<Mutex<State<F, S>>>) -> Self {
315            Singled { inner, state }
316        }
317    }
318
319    impl<F, S, Req> Service<Req> for Singled<F, S>
320    where
321        S: Service<Req>,
322    {
323        type Response = S::Response;
324        type Error = S::Error;
325        type Future = S::Future;
326
327        fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), Self::Error>> {
328            // We notice if the cached service dies, and clear the singleton cache.
329            match self.inner.poll_ready(cx) {
330                Poll::Ready(Err(err)) => {
331                    if let Some(state) = self.state.upgrade() {
332                        *state.lock().unwrap() = State::Empty;
333                    }
334                    Poll::Ready(Err(err))
335                }
336                other => other,
337            }
338        }
339
340        fn call(&mut self, req: Req) -> Self::Future {
341            self.inner.call(req)
342        }
343    }
344
345    impl<F, S> Batch<F, S> {
346        pub(super) fn new(future: F) -> Self {
347            Batch {
348                future: Some(Box::pin(future)),
349                next_id: WaiterId(0),
350                driver: None,
351                waiters: Vec::new(),
352            }
353        }
354
355        pub(super) fn register_driver(&mut self) -> WaiterId {
356            let id = self.next_id;
357            self.next_id.0 += 1;
358            self.driver = Some(Driver { id, waker: None });
359            id
360        }
361
362        pub(super) fn register_waiter(
363            &mut self,
364        ) -> (WaiterId, oneshot::Receiver<Result<S, SharedError>>) {
365            let id = self.next_id;
366            self.next_id.0 += 1;
367            let (tx, rx) = oneshot::channel();
368            self.waiters.push(Waiter {
369                id,
370                waker: None,
371                tx,
372            });
373            (id, rx)
374        }
375
376        fn remove(&mut self, id: WaiterId) -> bool {
377            if let Some(pos) = self.waiters.iter().position(|waiter| waiter.id == id) {
378                self.waiters.swap_remove(pos);
379                return false;
380            }
381
382            if self.driver.as_ref().is_some_and(|driver| driver.id == id) {
383                if let Some(waiter) = self.waiters.pop() {
384                    let waker = waiter.waker;
385                    self.driver = Some(Driver {
386                        id: waiter.id,
387                        waker,
388                    });
389                    self.wake_driver();
390                    return false;
391                }
392
393                self.driver = None;
394                self.future = None;
395                return true;
396            }
397
398            false
399        }
400
401        fn poll<E>(
402            &mut self,
403            id: WaiterId,
404            cx: &mut task::Context<'_>,
405        ) -> Poll<Result<S, SharedError>>
406        where
407            F: Future<Output = Result<S, E>>,
408            E: Into<BoxError>,
409            S: Clone,
410        {
411            if !self.driver.as_ref().is_some_and(|driver| driver.id == id) {
412                self.store_waker(id, cx.waker());
413                return Poll::Pending;
414            }
415
416            let future = self.future.as_mut().expect("batch future missing");
417            match future.as_mut().poll(cx) {
418                Poll::Pending => {
419                    self.store_driver_waker(cx.waker());
420                    Poll::Pending
421                }
422                Poll::Ready(Ok(svc)) => {
423                    self.future = None;
424                    Poll::Ready(Ok(svc))
425                }
426                Poll::Ready(Err(err)) => {
427                    let err = box_error_into_shared(err.into());
428                    self.future = None;
429                    Poll::Ready(Err(err))
430                }
431            }
432        }
433
434        fn send_result(&mut self, result: Result<S, SharedError>)
435        where
436            S: Clone,
437        {
438            for waiter in std::mem::take(&mut self.waiters) {
439                let _ = waiter.tx.send(result.clone());
440            }
441        }
442
443        fn store_waker(&mut self, id: WaiterId, waker: &Waker) {
444            if let Some(waiter) = self.waiters.iter_mut().find(|waiter| waiter.id == id) {
445                if waiter
446                    .waker
447                    .as_ref()
448                    .is_none_or(|current| !current.will_wake(waker))
449                {
450                    waiter.waker = Some(waker.clone());
451                }
452            }
453        }
454
455        fn store_driver_waker(&mut self, waker: &Waker) {
456            if let Some(driver) = &mut self.driver {
457                if driver
458                    .waker
459                    .as_ref()
460                    .is_none_or(|current| !current.will_wake(waker))
461                {
462                    driver.waker = Some(waker.clone());
463                }
464            }
465        }
466
467        fn wake_driver(&mut self) {
468            if let Some(driver) = &mut self.driver {
469                if let Some(waker) = driver.waker.take() {
470                    waker.wake();
471                }
472            }
473        }
474    }
475
476    // An opaque error type. By not exposing the type, nor being specifically
477    // Box<dyn Error>, we can change the inner representation later.
478    #[derive(Debug)]
479    pub struct SingletonError(pub(super) SharedError);
480
481    impl SingletonError {
482        pub(super) fn new(error: BoxError) -> Self {
483            SingletonError(box_error_into_shared(error))
484        }
485    }
486
487    impl std::fmt::Display for SingletonError {
488        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
489            f.write_str("singleton connection error")
490        }
491    }
492
493    impl std::error::Error for SingletonError {
494        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
495            Some(&*self.0)
496        }
497    }
498
499    type SharedError = Arc<dyn std::error::Error + Send + Sync>;
500
501    fn box_error_into_shared(error: BoxError) -> SharedError {
502        error.into()
503    }
504}
505
506#[cfg(test)]
507mod tests {
508    use std::error::Error;
509    use std::pin::Pin;
510    use std::task::Poll;
511
512    use tower_service::Service;
513
514    use super::Singleton;
515
516    #[tokio::test]
517    async fn first_call_drives_subsequent_wait() {
518        let (mock_svc, mut handle) = tower_test::mock::pair::<(), &'static str>();
519
520        let mut singleton = Singleton::new(mock_svc);
521
522        handle.allow(1);
523        std::future::poll_fn(|cx| singleton.poll_ready(cx))
524            .await
525            .unwrap();
526        // First call: should go into Driving
527        let fut1 = singleton.call(());
528        // Second call: should go into Waiting
529        let fut2 = singleton.call(());
530
531        // Expect exactly one request to the inner service
532        let ((), send_response) = handle.next_request().await.unwrap();
533        send_response.send_response("svc");
534
535        // Both futures should resolve to the same value
536        fut1.await.unwrap();
537        fut2.await.unwrap();
538    }
539
540    #[tokio::test]
541    async fn made_state_returns_immediately() {
542        let (mock_svc, mut handle) = tower_test::mock::pair::<(), &'static str>();
543        let mut singleton = Singleton::new(mock_svc);
544
545        handle.allow(1);
546        std::future::poll_fn(|cx| singleton.poll_ready(cx))
547            .await
548            .unwrap();
549        // Drive first call to completion
550        let fut1 = singleton.call(());
551        let ((), send_response) = handle.next_request().await.unwrap();
552        send_response.send_response("svc");
553        fut1.await.unwrap();
554
555        // Second call should not hit inner service
556        singleton.call(()).await.unwrap();
557    }
558
559    #[tokio::test]
560    async fn cached_service_poll_ready_error_clears_singleton() {
561        // Outer mock returns an inner mock service
562        let (outer, mut outer_handle) =
563            tower_test::mock::pair::<(), tower_test::mock::Mock<(), &'static str>>();
564        let mut singleton = Singleton::new(outer);
565
566        // Allow the singleton to be made
567        outer_handle.allow(2);
568        std::future::poll_fn(|cx| singleton.poll_ready(cx))
569            .await
570            .unwrap();
571
572        // First call produces an inner mock service
573        let fut1 = singleton.call(());
574        let ((), send_inner) = outer_handle.next_request().await.unwrap();
575        let (inner, mut inner_handle) = tower_test::mock::pair::<(), &'static str>();
576        send_inner.send_response(inner);
577        let mut cached = fut1.await.unwrap();
578
579        // Now: allow readiness on the inner mock, then inject error
580        inner_handle.allow(1);
581
582        // Inject error so next poll_ready fails
583        inner_handle.send_error(std::io::Error::new(
584            std::io::ErrorKind::Other,
585            "cached poll_ready failed",
586        ));
587
588        // Drive poll_ready on cached service
589        let err = std::future::poll_fn(|cx| cached.poll_ready(cx))
590            .await
591            .err()
592            .expect("expected poll_ready error");
593        assert_eq!(err.to_string(), "cached poll_ready failed");
594
595        // After error, the singleton should be cleared, so a new call drives outer again
596        outer_handle.allow(1);
597        std::future::poll_fn(|cx| singleton.poll_ready(cx))
598            .await
599            .unwrap();
600        let fut2 = singleton.call(());
601        let ((), send_inner2) = outer_handle.next_request().await.unwrap();
602        let (inner2, mut inner_handle2) = tower_test::mock::pair::<(), &'static str>();
603        send_inner2.send_response(inner2);
604        let mut cached2 = fut2.await.unwrap();
605
606        // The new cached service should still work
607        inner_handle2.allow(1);
608        std::future::poll_fn(|cx| cached2.poll_ready(cx))
609            .await
610            .expect("expected poll_ready");
611        let cfut2 = cached2.call(());
612        let ((), send_cached2) = inner_handle2.next_request().await.unwrap();
613        send_cached2.send_response("svc2");
614        cfut2.await.unwrap();
615    }
616
617    #[tokio::test]
618    async fn cancel_waiter_does_not_affect_others() {
619        let (mock_svc, mut handle) = tower_test::mock::pair::<(), &'static str>();
620        let mut singleton = Singleton::new(mock_svc);
621
622        std::future::poll_fn(|cx| singleton.poll_ready(cx))
623            .await
624            .unwrap();
625        let fut1 = singleton.call(());
626        let fut2 = singleton.call(());
627        drop(fut2); // cancel one waiter
628
629        let ((), send_response) = handle.next_request().await.unwrap();
630        send_response.send_response("svc");
631
632        fut1.await.unwrap();
633    }
634
635    #[tokio::test]
636    async fn maker_error_is_shared_with_waiters() {
637        let (mock_svc, mut handle) = tower_test::mock::pair::<(), &'static str>();
638        let mut singleton = Singleton::new(mock_svc);
639
640        std::future::poll_fn(|cx| singleton.poll_ready(cx))
641            .await
642            .unwrap();
643
644        let fut1 = singleton.call(());
645        let fut2 = singleton.call(());
646        let fut3 = singleton.call(());
647
648        let ((), send_response) = handle.next_request().await.unwrap();
649        send_response.send_error(std::io::Error::new(
650            std::io::ErrorKind::Other,
651            "maker failed",
652        ));
653
654        let err1 = fut1.await.unwrap_err();
655        let err2 = fut2.await.unwrap_err();
656        let err3 = fut3.await.unwrap_err();
657
658        let src1 = err1.source().expect("driver source");
659        let src2 = err2.source().expect("waiter source");
660        let src3 = err3.source().expect("waiter source");
661
662        assert_eq!(src1.to_string(), "maker failed");
663        assert!(std::ptr::addr_eq(src1, src2));
664        assert!(std::ptr::addr_eq(src1, src3));
665    }
666
667    #[tokio::test]
668    async fn cancel_driver_hands_off_to_waiter() {
669        let (mock_svc, mut handle) = tower_test::mock::pair::<(), &'static str>();
670        let mut singleton = Singleton::new(mock_svc);
671
672        std::future::poll_fn(|cx| singleton.poll_ready(cx))
673            .await
674            .unwrap();
675        let mut fut1 = singleton.call(());
676        let fut2 = singleton.call(());
677
678        // poll driver just once, and then drop
679        std::future::poll_fn(move |cx| {
680            let _ = Pin::new(&mut fut1).poll(cx);
681            Poll::Ready(())
682        })
683        .await;
684
685        let ((), send_response) = handle.next_request().await.unwrap();
686        send_response.send_response("svc");
687
688        fut2.await.unwrap();
689    }
690
691    #[tokio::test]
692    async fn cancel_driver_promotes_parked_waiter() {
693        let (mock_svc, mut handle) = tower_test::mock::pair::<(), &'static str>();
694        let mut singleton = Singleton::new(mock_svc);
695
696        std::future::poll_fn(|cx| singleton.poll_ready(cx))
697            .await
698            .unwrap();
699        let mut fut1 = singleton.call(());
700        let fut2 = singleton.call(());
701
702        // Start the make future so dropping fut1 below exercises driver
703        // handoff during an in-flight connection attempt.
704        std::future::poll_fn(|cx| {
705            assert!(Pin::new(&mut fut1).poll(cx).is_pending());
706            Poll::Ready(())
707        })
708        .await;
709
710        // Poll the waiter once so it parks and stores a waker in the batch.
711        // This covers promotion of an already-parked waiter, not just a
712        // registered-but-never-polled waiter.
713        let mut waiter = tokio_test::task::spawn(fut2);
714        assert!(waiter.poll().is_pending());
715        assert!(!waiter.is_woken());
716
717        // When the driver is dropped, the promoted parked waiter must be
718        // woken so it can take over driving the shared make future.
719        drop(fut1);
720        assert!(waiter.is_woken());
721
722        // Poll after promotion, before the maker responds, so the waiter
723        // actually takes over as driver and stores its own waker.
724        assert!(waiter.poll().is_pending());
725
726        let ((), send_response) = handle.next_request().await.unwrap();
727        send_response.send_response("svc");
728
729        assert!(waiter.is_woken());
730        match waiter.poll() {
731            Poll::Ready(Ok(_)) => {}
732            other => panic!("expected promoted waiter to complete, got {other:?}"),
733        }
734    }
735
736    #[tokio::test]
737    async fn cancel_all_waiters_clears_singleton() {
738        let (mock_svc, _handle) = tower_test::mock::pair::<(), &'static str>();
739        let mut singleton = Singleton::new(mock_svc);
740
741        std::future::poll_fn(|cx| singleton.poll_ready(cx))
742            .await
743            .unwrap();
744        let fut1 = singleton.call(());
745        let fut2 = singleton.call(());
746
747        drop(fut1);
748        drop(fut2);
749
750        assert!(singleton.is_empty());
751    }
752
753    #[tokio::test]
754    async fn cancel_non_driver_waiter_does_not_block_others() {
755        let (mock_svc, mut handle) = tower_test::mock::pair::<(), &'static str>();
756        let mut singleton = Singleton::new(mock_svc);
757
758        std::future::poll_fn(|cx| singleton.poll_ready(cx))
759            .await
760            .unwrap();
761        let fut1 = singleton.call(());
762        let fut2 = singleton.call(());
763        let fut3 = singleton.call(());
764        drop(fut2);
765
766        let ((), send_response) = handle.next_request().await.unwrap();
767        send_response.send_response("svc");
768
769        fut1.await.unwrap();
770        fut3.await.unwrap();
771    }
772}