Add serial
attribute for SimpleObject
and Object
macros. #539
This commit is contained in:
parent
6d28bffcce
commit
b7b9abf40d
|
@ -173,6 +173,8 @@ pub struct SimpleObject {
|
|||
pub visible: Option<Visible>,
|
||||
#[darling(default, multiple, rename = "concrete")]
|
||||
pub concretes: Vec<ConcreteType>,
|
||||
#[darling(default)]
|
||||
pub serial: bool,
|
||||
}
|
||||
|
||||
#[derive(FromMeta, Default)]
|
||||
|
@ -199,6 +201,7 @@ pub struct Object {
|
|||
pub extends: bool,
|
||||
pub use_type_description: bool,
|
||||
pub visible: Option<Visible>,
|
||||
pub serial: bool,
|
||||
}
|
||||
|
||||
pub enum ComplexityType {
|
||||
|
|
|
@ -578,6 +578,11 @@ pub fn generate(
|
|||
}
|
||||
|
||||
let visible = visible_fn(&object_args.visible);
|
||||
let resolve_container = if object_args.serial {
|
||||
quote! { #crate_name::resolver_utils::resolve_container_serial(ctx, self).await }
|
||||
} else {
|
||||
quote! { #crate_name::resolver_utils::resolve_container(ctx, self).await }
|
||||
};
|
||||
|
||||
let expanded = quote! {
|
||||
#item_impl
|
||||
|
@ -645,7 +650,7 @@ pub fn generate(
|
|||
ctx: &#crate_name::ContextSelectionSet<'_>,
|
||||
_field: &#crate_name::Positioned<#crate_name::parser::types::Field>
|
||||
) -> #crate_name::ServerResult<#crate_name::Value> {
|
||||
#crate_name::resolver_utils::resolve_container(ctx, self).await
|
||||
#resolve_container
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -170,6 +170,12 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
};
|
||||
}
|
||||
|
||||
let resolve_container = if object_args.serial {
|
||||
quote! { #crate_name::resolver_utils::resolve_container_serial(ctx, self).await }
|
||||
} else {
|
||||
quote! { #crate_name::resolver_utils::resolve_container(ctx, self).await }
|
||||
};
|
||||
|
||||
let expanded = if object_args.concretes.is_empty() {
|
||||
quote! {
|
||||
#[allow(clippy::all, clippy::pedantic)]
|
||||
|
@ -216,7 +222,7 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
#[#crate_name::async_trait::async_trait]
|
||||
impl #impl_generics #crate_name::OutputType for #ident #ty_generics #where_clause {
|
||||
async fn resolve(&self, ctx: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::ServerResult<#crate_name::Value> {
|
||||
#crate_name::resolver_utils::resolve_container(ctx, self).await
|
||||
#resolve_container
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,7 +287,7 @@ pub fn generate(object_args: &args::SimpleObject) -> GeneratorResult<TokenStream
|
|||
#[#crate_name::async_trait::async_trait]
|
||||
impl #crate_name::OutputType for #concrete_type {
|
||||
async fn resolve(&self, ctx: &#crate_name::ContextSelectionSet<'_>, _field: &#crate_name::Positioned<#crate_name::parser::types::Field>) -> #crate_name::ServerResult<#crate_name::Value> {
|
||||
#crate_name::resolver_utils::resolve_container(ctx, self).await
|
||||
#resolve_container
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -284,6 +284,7 @@ pub type FieldResult<T> = Result<T>;
|
|||
/// | visible | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
|
||||
/// | visible | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
|
||||
/// | secret | Mark this field as a secret, it will not output the actual value in the log. | bool | Y |
|
||||
/// | serial | Resolve each field sequentially. | bool | Y |
|
||||
/// | key | Is entity key(for Federation) | bool | Y |
|
||||
///
|
||||
/// # Valid field return types
|
||||
|
@ -430,6 +431,8 @@ pub use async_graphql_derive::Object;
|
|||
/// | extends | Add fields to an entity that's defined in another service | bool | Y |
|
||||
/// | visible | If `false`, it will not be displayed in introspection. *[See also the Book](https://async-graphql.github.io/async-graphql/en/visibility.html).* | bool | Y |
|
||||
/// | visible | Call the specified function. If the return value is `false`, it will not be displayed in introspection. | string | Y |
|
||||
/// | concretes | Specify how the concrete type of the generic SimpleObject should be implemented. *[See also the Book](https://async-graphql.github.io/async-graphql/en/define_simple_object.html#generic-simpleobjects) | ConcreteType | Y |
|
||||
/// | serial | Resolve each field sequentially. | bool | Y |
|
||||
///
|
||||
/// # Field parameters
|
||||
///
|
||||
|
|
|
@ -84,3 +84,103 @@ pub async fn test_mutation_fragment() {
|
|||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
pub async fn test_serial() {
|
||||
type List = Arc<Mutex<Vec<i32>>>;
|
||||
|
||||
struct MyObj;
|
||||
|
||||
#[Object(serial)]
|
||||
impl MyObj {
|
||||
async fn append1(&self, ctx: &Context<'_>) -> bool {
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
ctx.data_unchecked::<List>().lock().await.push(1);
|
||||
true
|
||||
}
|
||||
|
||||
async fn append2(&self, ctx: &Context<'_>) -> bool {
|
||||
tokio::time::sleep(Duration::from_millis(500)).await;
|
||||
ctx.data_unchecked::<List>().lock().await.push(2);
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
struct QueryRoot;
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {
|
||||
async fn value(&self) -> i32 {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
struct MutationRoot;
|
||||
|
||||
#[Object]
|
||||
impl MutationRoot {
|
||||
async fn obj(&self) -> MyObj {
|
||||
MyObj
|
||||
}
|
||||
}
|
||||
|
||||
let list = List::default();
|
||||
let schema = Schema::build(QueryRoot, MutationRoot, EmptySubscription)
|
||||
.data(list.clone())
|
||||
.finish();
|
||||
schema.execute("mutation { obj { append1 append2 } }").await;
|
||||
assert_eq!(list.lock().await[0], 1);
|
||||
assert_eq!(list.lock().await[1], 2);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
pub async fn test_serial_simple_object() {
|
||||
type List = Arc<Mutex<Vec<i32>>>;
|
||||
|
||||
#[derive(SimpleObject)]
|
||||
#[graphql(complex, serial)]
|
||||
struct MyObj {
|
||||
value: i32,
|
||||
}
|
||||
|
||||
#[ComplexObject]
|
||||
impl MyObj {
|
||||
async fn append1(&self, ctx: &Context<'_>) -> bool {
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
ctx.data_unchecked::<List>().lock().await.push(1);
|
||||
true
|
||||
}
|
||||
|
||||
async fn append2(&self, ctx: &Context<'_>) -> bool {
|
||||
tokio::time::sleep(Duration::from_millis(500)).await;
|
||||
ctx.data_unchecked::<List>().lock().await.push(2);
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
struct QueryRoot;
|
||||
|
||||
#[Object]
|
||||
impl QueryRoot {
|
||||
async fn value(&self) -> i32 {
|
||||
10
|
||||
}
|
||||
}
|
||||
|
||||
struct MutationRoot;
|
||||
|
||||
#[Object]
|
||||
impl MutationRoot {
|
||||
async fn obj(&self) -> MyObj {
|
||||
MyObj { value: 10 }
|
||||
}
|
||||
}
|
||||
|
||||
let list = List::default();
|
||||
let schema = Schema::build(QueryRoot, MutationRoot, EmptySubscription)
|
||||
.data(list.clone())
|
||||
.finish();
|
||||
schema.execute("mutation { obj { append1 append2 } }").await;
|
||||
assert_eq!(list.lock().await[0], 1);
|
||||
assert_eq!(list.lock().await[1], 2);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user