Always store state in an Arc (#1270)

* Add extension and state benchmarks

* wip

* Arc the state everywhere

* don't require `S: Clone`

* fix example
This commit is contained in:
David Pedersen
2022-08-17 20:08:24 +00:00
committed by GitHub
parent 423308de3c
commit e7f1c88cd4
56 changed files with 199 additions and 141 deletions
+1 -1
View File
@@ -195,7 +195,7 @@ macro_rules! impl_traits_for_either {
$($ident: FromRequest<S, B>),*,
$last: FromRequest<S, B>,
B: Send,
S: Send,
S: Send + Sync,
{
type Rejection = $last::Rejection;
+4 -4
View File
@@ -33,7 +33,7 @@ use std::ops::{Deref, DerefMut};
/// impl<S, B> FromRequest<S, B> for Session
/// where
/// B: Send,
/// S: Send,
/// S: Send + Sync,
/// {
/// type Rejection = (StatusCode, String);
///
@@ -49,7 +49,7 @@ use std::ops::{Deref, DerefMut};
/// impl<S, B> FromRequest<S, B> for CurrentUser
/// where
/// B: Send,
/// S: Send,
/// S: Send + Sync,
/// {
/// type Rejection = Response;
///
@@ -93,7 +93,7 @@ struct CachedEntry<T>(T);
impl<S, B, T> FromRequest<S, B> for Cached<T>
where
B: Send,
S: Send,
S: Send + Sync,
T: FromRequest<S, B> + Clone + Send + Sync + 'static,
{
type Rejection = T::Rejection;
@@ -145,7 +145,7 @@ mod tests {
impl<S, B> FromRequest<S, B> for Extractor
where
B: Send,
S: Send,
S: Send + Sync,
{
type Rejection = Infallible;
+1 -1
View File
@@ -91,7 +91,7 @@ pub struct CookieJar {
impl<S, B> FromRequest<S, B> for CookieJar
where
B: Send,
S: Send,
S: Send + Sync,
{
type Rejection = Infallible;
+1 -1
View File
@@ -90,7 +90,7 @@ impl<K> fmt::Debug for PrivateCookieJar<K> {
impl<S, B, K> FromRequest<S, B> for PrivateCookieJar<K>
where
B: Send,
S: Send,
S: Send + Sync,
K: FromRef<S> + Into<Key>,
{
type Rejection = Infallible;
+1 -1
View File
@@ -108,7 +108,7 @@ impl<K> fmt::Debug for SignedCookieJar<K> {
impl<S, B, K> FromRequest<S, B> for SignedCookieJar<K>
where
B: Send,
S: Send,
S: Send + Sync,
K: FromRef<S> + Into<Key>,
{
type Rejection = Infallible;
+1 -1
View File
@@ -61,7 +61,7 @@ where
B: HttpBody + Send,
B::Data: Send,
B::Error: Into<BoxError>,
S: Send,
S: Send + Sync,
{
type Rejection = FormRejection;
+1 -1
View File
@@ -62,7 +62,7 @@ impl<T, S, B> FromRequest<S, B> for Query<T>
where
T: DeserializeOwned,
B: Send,
S: Send,
S: Send + Sync,
{
type Rejection = QueryRejection;
+2 -2
View File
@@ -110,7 +110,7 @@ impl<E, R> DerefMut for WithRejection<E, R> {
impl<B, E, R, S> FromRequest<S, B> for WithRejection<E, R>
where
B: Send,
S: Send,
S: Send + Sync,
E: FromRequest<S, B>,
R: From<E::Rejection> + IntoResponse,
{
@@ -138,7 +138,7 @@ mod tests {
impl<S, B> FromRequest<S, B> for TestExtractor
where
B: Send,
S: Send,
S: Send + Sync,
{
type Rejection = ();
+12 -8
View File
@@ -6,7 +6,7 @@ use axum::{
response::{IntoResponse, Response},
};
use futures_util::future::{BoxFuture, FutureExt, Map};
use std::{future::Future, marker::PhantomData};
use std::{future::Future, marker::PhantomData, sync::Arc};
mod or;
@@ -24,7 +24,11 @@ pub trait HandlerCallWithExtractors<T, S, B>: Sized {
type Future: Future<Output = Response> + Send + 'static;
/// Call the handler with the extracted inputs.
fn call(self, state: S, extractors: T) -> <Self as HandlerCallWithExtractors<T, S, B>>::Future;
fn call(
self,
state: Arc<S>,
extractors: T,
) -> <Self as HandlerCallWithExtractors<T, S, B>>::Future;
/// Conver this `HandlerCallWithExtractors` into [`Handler`].
fn into_handler(self) -> IntoHandler<Self, T, S, B> {
@@ -70,7 +74,7 @@ pub trait HandlerCallWithExtractors<T, S, B>: Sized {
/// impl<S, B> FromRequest<S, B> for AdminPermissions
/// where
/// B: Send,
/// S: Send,
/// S: Send + Sync,
/// {
/// // check for admin permissions...
/// # type Rejection = ();
@@ -85,7 +89,7 @@ pub trait HandlerCallWithExtractors<T, S, B>: Sized {
/// impl<S, B> FromRequest<S, B> for User
/// where
/// B: Send,
/// S: Send,
/// S: Send + Sync,
/// {
/// // check for a logged in user...
/// # type Rejection = ();
@@ -130,7 +134,7 @@ macro_rules! impl_handler_call_with {
fn call(
self,
_state: S,
_state: Arc<S>,
($($ty,)*): ($($ty,)*),
) -> <Self as HandlerCallWithExtractors<($($ty,)*), S, B>>::Future {
self($($ty,)*).map(IntoResponse::into_response)
@@ -172,13 +176,13 @@ where
T: FromRequest<S, B> + Send + 'static,
T::Rejection: Send,
B: Send + 'static,
S: Clone + Send + 'static,
S: Send + Sync + 'static,
{
type Future = BoxFuture<'static, Response>;
fn call(self, state: S, req: http::Request<B>) -> Self::Future {
fn call(self, state: Arc<S>, req: http::Request<B>) -> Self::Future {
Box::pin(async move {
let mut req = RequestParts::with_state(state.clone(), req);
let mut req = RequestParts::with_state_arc(Arc::clone(&state), req);
match req.extract::<T>().await {
Ok(t) => self.handler.call(state, t).await,
Err(rejection) => rejection.into_response(),
+5 -5
View File
@@ -8,7 +8,7 @@ use axum::{
};
use futures_util::future::{BoxFuture, Either as EitherFuture, FutureExt, Map};
use http::StatusCode;
use std::{future::Future, marker::PhantomData};
use std::{future::Future, marker::PhantomData, sync::Arc};
/// [`Handler`] that runs one [`Handler`] and if that rejects it'll fallback to another
/// [`Handler`].
@@ -37,7 +37,7 @@ where
fn call(
self,
state: S,
state: Arc<S>,
extractors: Either<Lt, Rt>,
) -> <Self as HandlerCallWithExtractors<Either<Lt, Rt>, S, B>>::Future {
match extractors {
@@ -64,14 +64,14 @@ where
Lt::Rejection: Send,
Rt::Rejection: Send,
B: Send + 'static,
S: Clone + Send + 'static,
S: Send + Sync + 'static,
{
// this puts `futures_util` in our public API but thats fine in axum-extra
type Future = BoxFuture<'static, Response>;
fn call(self, state: S, req: Request<B>) -> Self::Future {
fn call(self, state: Arc<S>, req: Request<B>) -> Self::Future {
Box::pin(async move {
let mut req = RequestParts::with_state(state.clone(), req);
let mut req = RequestParts::with_state_arc(Arc::clone(&state), req);
if let Ok(lt) = req.extract::<Lt>().await {
return self.lhs.call(state, lt).await;
+1 -1
View File
@@ -104,7 +104,7 @@ where
B::Data: Into<Bytes>,
B::Error: Into<BoxError>,
T: DeserializeOwned,
S: Send,
S: Send + Sync,
{
type Rejection = BodyAlreadyExtracted;
+1 -1
View File
@@ -103,7 +103,7 @@ where
B: HttpBody + Send,
B::Data: Send,
B::Error: Into<BoxError>,
S: Send,
S: Send + Sync,
{
type Rejection = ProtoBufRejection;
+1 -1
View File
@@ -178,7 +178,7 @@ pub trait RouterExt<S, B>: sealed::Sealed {
impl<S, B> RouterExt<S, B> for Router<S, B>
where
B: axum::body::HttpBody + Send + 'static,
S: Clone + Send + Sync + 'static,
S: Send + Sync + 'static,
{
#[cfg(feature = "typed-routing")]
fn typed_get<H, T, P>(self, handler: H) -> Self
+1 -1
View File
@@ -53,7 +53,7 @@ where
impl<S, B> Resource<S, B>
where
B: axum::body::HttpBody + Send + 'static,
S: Clone + Send + Sync + 'static,
S: Send + Sync + 'static,
{
/// Create a `Resource` with the given name and state.
///