use crate::context::DeferList; use crate::registry::Registry; use crate::{ContextSelectionSet, OutputValueType, Pos, QueryResponse, Result, Type}; use std::borrow::Cow; use std::sync::atomic::AtomicUsize; pub struct Deferred(T); impl From for Deferred { fn from(value: T) -> Self { Self(value) } } impl Type for Deferred { fn type_name() -> Cow<'static, str> { T::type_name() } fn create_type_info(registry: &mut Registry) -> String { T::create_type_info(registry) } } #[async_trait::async_trait] impl OutputValueType for Deferred { async fn resolve(&self, ctx: &ContextSelectionSet<'_>, pos: Pos) -> Result { if let Some(defer_list) = ctx.defer_list { let obj = self.0.clone(); let schema_env = ctx.schema_env.clone(); let query_env = ctx.query_env.clone(); let field_selection_set = ctx.item.clone(); let path = ctx.path_node.as_ref().map(|path| path.to_json()); defer_list.append(async move { let inc_resolve_id = AtomicUsize::default(); let defer_list = DeferList::default(); let ctx = query_env.create_context( &schema_env, None, &field_selection_set, &inc_resolve_id, Some(&defer_list), ); let data = obj.resolve(&ctx, pos).await?; Ok(( QueryResponse { path, data, extensions: None, cache_control: Default::default(), }, defer_list, )) }); Ok(serde_json::Value::Null) } else { OutputValueType::resolve(&self.0, ctx, pos).await } } }