Rebase onto async-await

This commit is contained in:
nWacky 2019-11-06 11:21:06 +03:00
parent 34c380b7af
commit 4834349310
No known key found for this signature in database
GPG key ID: 22EF2C62F6F79FD0
12 changed files with 151 additions and 130 deletions

View file

@ -35,18 +35,17 @@ default = [
[dependencies]
juniper_codegen = { version = "0.14.0", path = "../juniper_codegen" }
async-trait = "0.1.16"
chrono = { version = "0.4.0", optional = true }
fnv = "1.0.3"
futures-preview = { version = "=0.3.0-alpha.19", optional = true }
indexmap = { version = "1.0.0", features = ["serde-1"] }
serde = { version = "1.0.8" }
serde_derive = { version = "1.0.2" }
chrono = { version = "0.4.0", optional = true }
serde_json = { version="1.0.2", optional = true }
url = { version = "2", optional = true }
uuid = { version = "0.7", optional = true }
futures-preview = { version = "=0.3.0-alpha.19", optional = true }
[dev-dependencies]
bencher = "0.1.2"
serde_json = { version = "1.0.2" }

View file

@ -96,25 +96,6 @@ macro_rules! __juniper_insert_generic {
};
}
// TODO: remove me.
#[doc(hidden)]
#[macro_export]
macro_rules! __juniper_extract_generic {
(<$name:ident>) => {
$name
};
(
<$generic:tt $(: $bound: tt)*>
) => {
$generic
};
(
$scalar: ty
) => {
$scalar
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __juniper_parse_object_header {

View file

@ -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<Self::Context, $crate::__juniper_insert_generic!($($scalar)+)>,
) -> 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);

View file

@ -73,13 +73,17 @@ impl Root {
0
}
// TODO: enable once [RFC 2565](https://github.com/rust-lang/rust/issues/60406) is implemented
// fn attr_arg_descr(#[doc = "The arg"] arg: i32) -> i32 { 0 }
// fn attr_arg_descr_collapse(
// #[doc = "The arg"]
// #[doc = "and more details"]
// arg: i32,
// ) -> i32 { 0 }
// TODO: enable once [parameter attributes are supported by proc macros]
// (https://github.com/graphql-rust/juniper/pull/441)
// fn attr_arg_descr(
// #[graphql(description = "The arg")]
// arg: i32) -> i32
// { 0 }
// fn attr_arg_descr_collapse(
// #[graphql(description = "The first arg")]
// #[graphql(description = "and more details")]
// arg: i32,
// ) -> i32 { 0 }
#[graphql(arguments(arg(default = 123,),))]
fn arg_with_default(arg: i32) -> i32 {
@ -559,7 +563,8 @@ fn introspect_field_multi_args_descr_trailing_comma() {
});
}
// TODO: enable once [RFC 2565](https://github.com/rust-lang/rust/issues/60406) is implemented
// TODO: enable once [parameter attributes are supported by proc macros]
// (https://github.com/graphql-rust/juniper/pull/441)
// #[test]
// fn introspect_field_attr_arg_descr() {
// run_args_info_query("attrArgDescr", |args| {
@ -593,7 +598,8 @@ fn introspect_field_multi_args_descr_trailing_comma() {
// });
// }
// TODO: enable once [RFC 2565](https://github.com/rust-lang/rust/issues/60406) is implemented
// TODO: enable once [parameter attributes are supported by proc macros]
// (https://github.com/graphql-rust/juniper/pull/441)
// #[test]
// fn introspect_field_attr_arg_descr_collapse() {
// run_args_info_query("attrArgDescrCollapse", |args| {

View file

@ -77,6 +77,7 @@ where
}
#[cfg(feature = "async")]
#[async_trait::async_trait]
impl<'a, CtxT, S, QueryT, MutationT> crate::GraphQLTypeAsync<S>
for RootNode<'a, QueryT, MutationT, S>
where
@ -85,16 +86,16 @@ where
QueryT::TypeInfo: Send + Sync,
MutationT: crate::GraphQLTypeAsync<S, Context = CtxT>,
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 <Self as crate::GraphQLType<S>>::TypeInfo,
field_name: &'b str,
arguments: &'b Arguments<S>,
executor: &'b Executor<Self::Context, S>,
) -> crate::BoxFuture<'b, ExecutionResult<S>> {
arguments: &'b Arguments<'b, S>,
executor: &'b Executor<'b, <Self as crate::GraphQLType<S>>::Context, S>,
) -> ExecutionResult<S> {
use futures::future::{ready, FutureExt};
match field_name {
"__schema" | "__type" => {

View file

@ -12,6 +12,7 @@ use crate::BoxFuture;
use super::base::{is_excluded, merge_key_into, Arguments, GraphQLType};
#[async_trait::async_trait]
pub trait GraphQLTypeAsync<S>: GraphQLType<S> + Send + Sync
where
Self::Context: Send + Sync,
@ -19,28 +20,42 @@ 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<S>,
executor: &'a Executor<Self::Context, S>,
) -> BoxFuture<'a, ExecutionResult<S>> {
arguments: &'a Arguments<'a, S>,
executor: &'a Executor<'a, Self::Context, S>,
) -> ExecutionResult<S> {
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<S>]>,
executor: &'a Executor<Self::Context, S>,
) -> BoxFuture<'a, Value<S>> {
selection_set: Option<&'a [Selection<'a, S>]>,
executor: &'a Executor<'a, Self::Context, S>,
) -> Value<S> {
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");
}
}
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>,
) -> ExecutionResult<S> {
if Self::name(info).unwrap() == type_name {
Ok(self.resolve_async(info, selection_set, executor).await)
} else {
panic!("resolve_into_type_async must be implemented by unions and interfaces");
}
}
}
// Wrapper function around resolve_selection_set_into_async_recursive.
@ -160,7 +175,7 @@ where
let response_name = response_name.to_string();
let field_future = async move {
// TODO: implement custom future type instead of
// two-level boxing.
// two-level boxing.
let res = instance
.resolve_field_async(info, f.name.item, &args, &sub_exec)
.await;
@ -223,14 +238,14 @@ where
);
if let Some(ref type_condition) = fragment.type_condition {
// FIXME: implement async version.
let sub_result = instance.resolve_into_type(
info,
type_condition.item,
Some(&fragment.selection_set[..]),
&sub_exec,
);
let sub_result = instance
.resolve_into_type_async(
info,
type_condition.item,
Some(&fragment.selection_set[..]),
&sub_exec,
)
.await;
if let Ok(Value::Object(obj)) = sub_result {
for (k, v) in obj {

View file

@ -257,6 +257,7 @@ where
}
#[cfg(feature = "async")]
#[async_trait::async_trait]
impl<S, T, CtxT> crate::GraphQLTypeAsync<S> for Vec<T>
where
T: crate::GraphQLTypeAsync<S, Context = CtxT>,
@ -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<S>]>,
executor: &'a Executor<Self::Context, S>,
) -> crate::BoxFuture<'a, Value<S>> {
let f = resolve_into_list_async(executor, info, self.iter());
Box::pin(f)
info: &'a <Self as crate::GraphQLType<S>>::TypeInfo,
selection_set: Option<&'a [Selection<'a, S>]>,
executor: &'a Executor<'a, <Self as crate::GraphQLType<S>>::Context, S>,
) -> Value<S> {
resolve_into_list_async(executor, info, self.iter()).await
}
}
#[cfg(feature = "async")]
#[async_trait::async_trait]
impl<S, T, CtxT> crate::GraphQLTypeAsync<S> for &[T]
where
T: crate::GraphQLTypeAsync<S, Context = CtxT>,
@ -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<S>]>,
executor: &'a Executor<Self::Context, S>,
) -> crate::BoxFuture<'a, Value<S>> {
let f = resolve_into_list_async(executor, info, self.iter());
Box::pin(f)
info: &'a <Self as crate::GraphQLType<S>>::TypeInfo,
selection_set: Option<&'a [Selection<'a, S>]>,
executor: &'a Executor<'a, <Self as crate::GraphQLType<S>>::Context, S>,
) -> Value<S> {
resolve_into_list_async(executor, info, self.iter()).await
}
}
#[cfg(feature = "async")]
#[async_trait::async_trait]
impl<S, T, CtxT> crate::GraphQLTypeAsync<S> for Option<T>
where
T: crate::GraphQLTypeAsync<S, Context = CtxT>,
@ -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<S>]>,
executor: &'a Executor<Self::Context, S>,
) -> crate::BoxFuture<'a, Value<S>> {
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 <Self as crate::GraphQLType<S>>::TypeInfo,
selection_set: Option<&'a [Selection<'a, S>]>,
executor: &'a Executor<'a, <Self as crate::GraphQLType<S>>::Context, S>,
) -> Value<S> {
match *self {
Some(ref obj) => executor.resolve_into_value_async(info, obj).await,
None => Value::null(),
}
}
}

View file

@ -137,31 +137,33 @@ where
}
#[cfg(feature = "async")]
#[async_trait::async_trait]
impl<'e, S, T> crate::GraphQLTypeAsync<S> for &'e T
where
S: ScalarValue + Send + Sync,
T: crate::GraphQLTypeAsync<S>,
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 <Self as crate::GraphQLType<S>>::TypeInfo,
field_name: &'b str,
arguments: &'b Arguments<S>,
executor: &'b Executor<Self::Context, S>,
) -> crate::BoxFuture<'b, ExecutionResult<S>> {
arguments: &'b Arguments<'b, S>,
executor: &'b Executor<'b, <Self as crate::GraphQLType<S>>::Context, S>,
) -> ExecutionResult<S> {
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<S>]>,
executor: &'a Executor<Self::Context, S>,
) -> crate::BoxFuture<'a, Value<S>> {
crate::GraphQLTypeAsync::resolve_async(&**self, info, selection_set, executor)
info: &'a <Self as crate::GraphQLType<S>>::TypeInfo,
selection_set: Option<&'a [Selection<'a, S>]>,
executor: &'a Executor<'a, <Self as crate::GraphQLType<S>>::Context, S>,
) -> Value<S> {
crate::GraphQLTypeAsync::resolve_async(&**self, info, selection_set, executor).await
}
}

View file

@ -197,19 +197,19 @@ where
}
#[cfg(feature = "async")]
#[async_trait::async_trait]
impl<'e, S> crate::GraphQLTypeAsync<S> 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<S>]>,
executor: &'a Executor<Self::Context, S>,
) -> crate::BoxFuture<'a, crate::Value<S>> {
use futures::future;
future::FutureExt::boxed(future::ready(self.resolve(info, selection_set, executor)))
info: &'a <Self as crate::GraphQLType<S>>::TypeInfo,
selection_set: Option<&'a [Selection<'a, S>]>,
executor: &'a Executor<'a, <Self as crate::GraphQLType<S>>::Context, S>,
) -> crate::Value<S> {
self.resolve(info, selection_set, executor)
}
}

View file

@ -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<Self::Context, __S>,
) -> 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);

View file

@ -1,7 +1,7 @@
use proc_macro::TokenStream;
use proc_macro_error::MacroError;
use quote::{quote};
use quote::quote;
use syn::spanned::Spanned;
use crate::util;

View file

@ -731,15 +731,31 @@ impl GraphQLTypeDefiniton {
}
});
let scalar = self
.scalar
.as_ref()
.map(|s| quote!( #s ))
.unwrap_or_else(|| {
if self.generic_scalar {
// If generic_scalar is true, we always insert a generic scalar.
// See more comments below.
quote!(__S)
} else {
quote!(#juniper_crate_name::DefaultScalarValue)
}
});
let resolve_matches = self.fields.iter().map(|field| {
let name = &field.name;
let code = &field.resolver_code;
if field.is_async {
// TODO: better error message with field/type name.
quote!(
#name => {
panic!("Tried to resolve async field with a sync resolver");
panic!("Tried to resolve async field {} on type {:?} with a sync resolver",
#name,
<Self as #juniper_crate_name::GraphQLType<#scalar>>::name(_info)
);
},
)
} else {
@ -780,20 +796,6 @@ impl GraphQLTypeDefiniton {
)
});
let scalar = self
.scalar
.as_ref()
.map(|s| quote!( #s ))
.unwrap_or_else(|| {
if self.generic_scalar {
// If generic_scalar is true, we always insert a generic scalar.
// See more comments below.
quote!(__S)
} else {
quote!(#juniper_crate_name::DefaultScalarValue)
}
});
// Preserve the original type_generics before modification,
// since alteration makes them invalid if self.generic_scalar
// is specified.
@ -925,21 +927,27 @@ 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<Self::Context, #scalar>,
) -> 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;
match field {
#( #resolve_matches_async )*
_ => {
panic!("Field {} not found on type {}", field, "Mutation");
panic!("Field {} not found on type {:?}",
field,
<Self as #juniper_crate_name::GraphQLType<#scalar>>::name(info)
);
}
}
}
@ -989,7 +997,10 @@ impl GraphQLTypeDefiniton {
match field {
#( #resolve_matches )*
_ => {
panic!("Field {} not found on type {}", field, "Mutation");
panic!("Field {} not found on type {:?}",
field,
<Self as #juniper_crate_name::GraphQLType<#scalar>>::name(_info)
);
}
}
}