Make Router Sync without breaking the API (#2481)

This commit is contained in:
Jonas Platte 2024-01-02 20:18:07 +01:00 committed by GitHub
parent ae244b1eb1
commit af13c53938
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 16 additions and 14 deletions

View file

@ -1,4 +1,4 @@
use std::{convert::Infallible, fmt};
use std::{convert::Infallible, fmt, sync::Mutex};
use crate::extract::Request;
use tower::Service;
@ -9,7 +9,7 @@ use crate::{
Router,
};
pub(crate) struct BoxedIntoRoute<S, E>(Box<dyn ErasedIntoRoute<S, E>>);
pub(crate) struct BoxedIntoRoute<S, E>(Mutex<Box<dyn ErasedIntoRoute<S, E>>>);
impl<S> BoxedIntoRoute<S, Infallible>
where
@ -20,10 +20,10 @@ where
H: Handler<T, S>,
T: 'static,
{
Self(Box::new(MakeErasedHandler {
Self(Mutex::new(Box::new(MakeErasedHandler {
handler,
into_route: |handler, state| Route::new(Handler::with_state(handler, state)),
}))
})))
}
}
@ -35,20 +35,20 @@ impl<S, E> BoxedIntoRoute<S, E> {
F: FnOnce(Route<E>) -> Route<E2> + Clone + Send + 'static,
E2: 'static,
{
BoxedIntoRoute(Box::new(Map {
inner: self.0,
BoxedIntoRoute(Mutex::new(Box::new(Map {
inner: self.0.into_inner().unwrap(),
layer: Box::new(f),
}))
})))
}
pub(crate) fn into_route(self, state: S) -> Route<E> {
self.0.into_route(state)
self.0.into_inner().unwrap().into_route(state)
}
}
impl<S, E> Clone for BoxedIntoRoute<S, E> {
fn clone(&self) -> Self {
Self(self.0.clone_box())
Self(Mutex::new(self.0.lock().unwrap().clone_box()))
}
}

View file

@ -682,4 +682,5 @@ impl<S> fmt::Debug for Endpoint<S> {
fn traits() {
use crate::test_helpers::*;
assert_send::<Router<()>>();
assert_sync::<Router<()>>();
}

View file

@ -14,6 +14,7 @@ use std::{
fmt,
future::Future,
pin::Pin,
sync::Mutex,
task::{Context, Poll},
};
use tower::{
@ -27,7 +28,7 @@ use tower_service::Service;
///
/// You normally shouldn't need to care about this type. It's used in
/// [`Router::layer`](super::Router::layer).
pub struct Route<E = Infallible>(BoxCloneService<Request, Response, E>);
pub struct Route<E = Infallible>(Mutex<BoxCloneService<Request, Response, E>>);
impl<E> Route<E> {
pub(crate) fn new<T>(svc: T) -> Self
@ -36,16 +37,16 @@ impl<E> Route<E> {
T::Response: IntoResponse + 'static,
T::Future: Send + 'static,
{
Self(BoxCloneService::new(
Self(Mutex::new(BoxCloneService::new(
svc.map_response(IntoResponse::into_response),
))
)))
}
pub(crate) fn oneshot_inner(
&mut self,
req: Request,
) -> Oneshot<BoxCloneService<Request, Response, E>, Request> {
self.0.clone().oneshot(req)
self.0.get_mut().unwrap().clone().oneshot(req)
}
pub(crate) fn layer<L, NewError>(self, layer: L) -> Route<NewError>
@ -70,7 +71,7 @@ impl<E> Route<E> {
impl<E> Clone for Route<E> {
fn clone(&self) -> Self {
Self(self.0.clone())
Self(Mutex::new(self.0.lock().unwrap().clone()))
}
}