From 52c3e281f339ee68e5587fc633d40065a92da969 Mon Sep 17 00:00:00 2001 From: nWacky Date: Fri, 1 Nov 2019 19:37:55 +0300 Subject: [PATCH] Refactor `GraphQLTypeAsync` to use `async-trait` --- juniper/src/macros/scalar.rs | 12 ++++--- juniper/src/schema/schema.rs | 21 +++++++------ juniper/src/types/async_await.rs | 24 ++++++-------- juniper/src/types/containers.rs | 50 ++++++++++++++---------------- juniper/src/types/pointers.rs | 38 +++++++++++++++-------- juniper/src/types/scalars.rs | 14 ++++----- juniper_codegen/src/derive_enum.rs | 8 +++-- juniper_codegen/src/util.rs | 9 ++++-- 8 files changed, 96 insertions(+), 80 deletions(-) diff --git a/juniper/src/macros/scalar.rs b/juniper/src/macros/scalar.rs index 4f3ae84e..32c8b988 100644 --- a/juniper/src/macros/scalar.rs +++ b/juniper/src/macros/scalar.rs @@ -423,12 +423,16 @@ macro_rules! graphql_scalar { ) { - fn resolve_async<'a>( + fn resolve_async<'a, 'async_trait>( &'a self, info: &'a Self::TypeInfo, - selection_set: Option<&'a [$crate::Selection<$crate::__juniper_insert_generic!($($scalar)+)>]>, - executor: &'a $crate::Executor, - ) -> futures::future::BoxFuture<'a, $crate::Value<$crate::__juniper_insert_generic!($($scalar)+)>> { + selection_set: Option<&'a [$crate::Selection<'a, $crate::__juniper_insert_generic!($($scalar)+)>]>, + executor: &'a $crate::Executor<'a, Self::Context, $crate::__juniper_insert_generic!($($scalar)+)>, + ) -> futures::future::BoxFuture<'async_trait, $crate::Value<$crate::__juniper_insert_generic!($($scalar)+)>> + where + 'a: 'async_trait, + Self: 'async_trait, + { use $crate::GraphQLType; use futures::future; let v = self.resolve(info, selection_set, executor); diff --git a/juniper/src/schema/schema.rs b/juniper/src/schema/schema.rs index 14c3f2c2..23b36c8e 100644 --- a/juniper/src/schema/schema.rs +++ b/juniper/src/schema/schema.rs @@ -77,6 +77,7 @@ where } #[cfg(feature = "async")] +#[async_trait::async_trait] impl<'a, CtxT, S, QueryT, MutationT> crate::GraphQLTypeAsync for RootNode<'a, QueryT, MutationT, S> where @@ -85,25 +86,25 @@ where QueryT::TypeInfo: Send + Sync, MutationT: crate::GraphQLTypeAsync, MutationT::TypeInfo: Send + Sync, - CtxT: Send + Sync, - for<'b> &'b S: ScalarRefValue<'b>, + CtxT: Send + Sync + 'a, + for<'c> &'c S: ScalarRefValue<'c>, { - fn resolve_field_async<'b>( + async fn resolve_field_async<'b>( &'b self, - info: &'b Self::TypeInfo, + info: &'b >::TypeInfo, field_name: &'b str, - arguments: &'b Arguments, - executor: &'b Executor, - ) -> crate::BoxFuture<'b, ExecutionResult> { + arguments: &'b Arguments<'b, S>, + executor: &'b Executor<'b, >::Context, S>, + ) -> ExecutionResult { use futures::future::{ready, FutureExt}; match field_name { "__schema" | "__type" => { - let v = self.resolve_field(info, field_name, arguments, executor); - Box::pin(ready(v)) + self.resolve_field(info, field_name, arguments, executor) } _ => self .query_type - .resolve_field_async(info, field_name, arguments, executor), + .resolve_field_async(info, field_name, arguments, executor) + .await, } } } diff --git a/juniper/src/types/async_await.rs b/juniper/src/types/async_await.rs index 6e87a8cb..ec2b0e42 100644 --- a/juniper/src/types/async_await.rs +++ b/juniper/src/types/async_await.rs @@ -13,8 +13,7 @@ use crate::BoxFuture; use super::base::{is_excluded, merge_key_into, Arguments, GraphQLType}; -// todo: async trait -//#[async_trait] +#[async_trait] pub trait GraphQLTypeAsync: GraphQLType + Send + Sync where Self::Context: Send + Sync, @@ -22,43 +21,38 @@ where S: ScalarValue + Send + Sync, for<'b> &'b S: ScalarRefValue<'b>, { - fn resolve_field_async<'a>( + async fn resolve_field_async<'a>( &'a self, info: &'a Self::TypeInfo, field_name: &'a str, arguments: &'a Arguments<'a, S>, executor: &'a Executor<'a, Self::Context, S>, - ) -> BoxFuture<'a, ExecutionResult> { + ) -> ExecutionResult { panic!("resolve_field must be implemented by object types"); } - fn resolve_async<'a>( + async fn resolve_async<'a>( &'a self, info: &'a Self::TypeInfo, selection_set: Option<&'a [Selection<'a, S>]>, executor: &'a Executor<'a, Self::Context, S>, - ) -> BoxFuture<'a, Value> { + ) -> Value { if let Some(selection_set) = selection_set { - resolve_selection_set_into_async(self, info, selection_set, executor) + resolve_selection_set_into_async(self, info, selection_set, executor).await } else { panic!("resolve() must be implemented by non-object output types"); } } - fn resolve_into_type_async<'a>( + async fn resolve_into_type_async<'a>( &'a self, info: &'a Self::TypeInfo, type_name: &str, selection_set: Option<&'a [Selection<'a, S>]>, executor: &'a Executor<'a, Self::Context, S>, - ) -> BoxFuture<'a, ExecutionResult> { + ) -> ExecutionResult { if Self::name(info).unwrap() == type_name { - Box::pin( - async move { - let x = self.resolve_async(info, selection_set, executor).await; - Ok(x) - } - ) + Ok(self.resolve_async(info, selection_set, executor).await) } else { panic!("resolve_into_type_async must be implemented by unions and interfaces"); } diff --git a/juniper/src/types/containers.rs b/juniper/src/types/containers.rs index 06634072..7f6d1374 100644 --- a/juniper/src/types/containers.rs +++ b/juniper/src/types/containers.rs @@ -257,6 +257,7 @@ where } #[cfg(feature = "async")] +#[async_trait::async_trait] impl crate::GraphQLTypeAsync for Vec where T: crate::GraphQLTypeAsync, @@ -265,18 +266,18 @@ where CtxT: Send + Sync, for<'b> &'b S: ScalarRefValue<'b>, { - fn resolve_async<'a>( + async fn resolve_async<'a>( &'a self, - info: &'a Self::TypeInfo, - selection_set: Option<&'a [Selection]>, - executor: &'a Executor, - ) -> crate::BoxFuture<'a, Value> { - let f = resolve_into_list_async(executor, info, self.iter()); - Box::pin(f) + info: &'a >::TypeInfo, + selection_set: Option<&'a [Selection<'a, S>]>, + executor: &'a Executor<'a, >::Context, S>, + ) -> Value { + resolve_into_list_async(executor, info, self.iter()).await } } #[cfg(feature = "async")] +#[async_trait::async_trait] impl crate::GraphQLTypeAsync for &[T] where T: crate::GraphQLTypeAsync, @@ -285,18 +286,18 @@ where CtxT: Send + Sync, for<'b> &'b S: ScalarRefValue<'b>, { - fn resolve_async<'a>( + async fn resolve_async<'a>( &'a self, - info: &'a Self::TypeInfo, - selection_set: Option<&'a [Selection]>, - executor: &'a Executor, - ) -> crate::BoxFuture<'a, Value> { - let f = resolve_into_list_async(executor, info, self.iter()); - Box::pin(f) + info: &'a >::TypeInfo, + selection_set: Option<&'a [Selection<'a, S>]>, + executor: &'a Executor<'a, >::Context, S>, + ) -> Value { + resolve_into_list_async(executor, info, self.iter()).await } } #[cfg(feature = "async")] +#[async_trait::async_trait] impl crate::GraphQLTypeAsync for Option where T: crate::GraphQLTypeAsync, @@ -305,18 +306,15 @@ where CtxT: Send + Sync, for<'b> &'b S: ScalarRefValue<'b>, { - fn resolve_async<'a>( + async fn resolve_async<'a>( &'a self, - info: &'a Self::TypeInfo, - selection_set: Option<&'a [Selection]>, - executor: &'a Executor, - ) -> crate::BoxFuture<'a, Value> { - let f = async move { - match *self { - Some(ref obj) => executor.resolve_into_value_async(info, obj).await, - None => Value::null(), - } - }; - Box::pin(f) + info: &'a >::TypeInfo, + selection_set: Option<&'a [Selection<'a, S>]>, + executor: &'a Executor<'a, >::Context, S>, + ) -> Value { + match *self { + Some(ref obj) => executor.resolve_into_value_async(info, obj).await, + None => Value::null(), + } } } diff --git a/juniper/src/types/pointers.rs b/juniper/src/types/pointers.rs index 1e8478a1..7b47fcb6 100644 --- a/juniper/src/types/pointers.rs +++ b/juniper/src/types/pointers.rs @@ -137,31 +137,43 @@ where } #[cfg(feature = "async")] +#[async_trait::async_trait] impl<'e, S, T> crate::GraphQLTypeAsync for &'e T where S: ScalarValue + Send + Sync, T: crate::GraphQLTypeAsync, T::TypeInfo: Send + Sync, T::Context: Send + Sync, - for<'b> &'b S: ScalarRefValue<'b>, + for<'c> &'c S: ScalarRefValue<'c>, { - fn resolve_field_async<'b>( + async fn resolve_field_async<'b>( &'b self, - info: &'b Self::TypeInfo, + info: &'b >::TypeInfo, field_name: &'b str, - arguments: &'b Arguments, - executor: &'b Executor, - ) -> crate::BoxFuture<'b, ExecutionResult> { - crate::GraphQLTypeAsync::resolve_field_async(&**self, info, field_name, arguments, executor) + arguments: &'b Arguments<'b, S>, + executor: &'b Executor<'b, >::Context, S>, + ) -> ExecutionResult { + crate::GraphQLTypeAsync::resolve_field_async( + &**self, + info, + field_name, + arguments, + executor + ).await } - fn resolve_async<'a>( + async fn resolve_async<'a>( &'a self, - info: &'a Self::TypeInfo, - selection_set: Option<&'a [Selection]>, - executor: &'a Executor, - ) -> crate::BoxFuture<'a, Value> { - crate::GraphQLTypeAsync::resolve_async(&**self, info, selection_set, executor) + info: &'a >::TypeInfo, + selection_set: Option<&'a [Selection<'a, S>]>, + executor: &'a Executor<'a, >::Context, S>, + ) -> Value { + crate::GraphQLTypeAsync::resolve_async( + &**self, + info, + selection_set, + executor + ).await } } diff --git a/juniper/src/types/scalars.rs b/juniper/src/types/scalars.rs index e0b084fc..53876003 100644 --- a/juniper/src/types/scalars.rs +++ b/juniper/src/types/scalars.rs @@ -197,19 +197,19 @@ where } #[cfg(feature = "async")] +#[async_trait::async_trait] impl<'e, S> crate::GraphQLTypeAsync for &'e str where S: ScalarValue + Send + Sync, for<'b> &'b S: ScalarRefValue<'b>, { - fn resolve_async<'a>( + async fn resolve_async<'a>( &'a self, - info: &'a Self::TypeInfo, - selection_set: Option<&'a [Selection]>, - executor: &'a Executor, - ) -> crate::BoxFuture<'a, crate::Value> { - use futures::future; - future::FutureExt::boxed(future::ready(self.resolve(info, selection_set, executor))) + info: &'a >::TypeInfo, + selection_set: Option<&'a [Selection<'a, S>]>, + executor: &'a Executor<'a, >::Context, S>, + ) -> crate::Value { + self.resolve(info, selection_set, executor) } } diff --git a/juniper_codegen/src/derive_enum.rs b/juniper_codegen/src/derive_enum.rs index d1262e7d..607d2d1f 100644 --- a/juniper_codegen/src/derive_enum.rs +++ b/juniper_codegen/src/derive_enum.rs @@ -213,12 +213,16 @@ pub fn impl_enum(ast: &syn::DeriveInput, is_internal: bool) -> TokenStream { __S: #juniper_path::ScalarValue + Send + Sync, for<'__b> &'__b __S: #juniper_path::ScalarRefValue<'__b> { - fn resolve_async<'a>( + fn resolve_async<'a, 'async_trait>( &'a self, info: &'a Self::TypeInfo, selection_set: Option<&'a [#juniper_path::Selection<__S>]>, executor: &'a #juniper_path::Executor, - ) -> futures::future::BoxFuture<'a, #juniper_path::Value<__S>> { + ) -> futures::future::BoxFuture<'async_trait, #juniper_path::Value<__S>> + where + 'a: 'async_trait, + Self: 'async_trait + { use #juniper_path::GraphQLType; use futures::future; let v = self.resolve(info, selection_set, executor); diff --git a/juniper_codegen/src/util.rs b/juniper_codegen/src/util.rs index d6a71d59..2afee57c 100644 --- a/juniper_codegen/src/util.rs +++ b/juniper_codegen/src/util.rs @@ -925,14 +925,17 @@ impl GraphQLTypeDefiniton { impl#impl_generics #juniper_crate_name::GraphQLTypeAsync<#scalar> for #ty #type_generics_tokens #where_async { - fn resolve_field_async<'b>( + fn resolve_field_async<'b, 'async_trait>( &'b self, info: &'b Self::TypeInfo, field: &'b str, args: &'b #juniper_crate_name::Arguments<#scalar>, executor: &'b #juniper_crate_name::Executor, - ) -> futures::future::BoxFuture<'b, #juniper_crate_name::ExecutionResult<#scalar>> - where #scalar: Send + Sync, + ) -> futures::future::BoxFuture<'async_trait, #juniper_crate_name::ExecutionResult<#scalar>> + where + #scalar: Send + Sync, + 'b: 'async_trait, + Self: 'async_trait, { use futures::future; use #juniper_crate_name::GraphQLType;