Use FieldResult for data(), add data_unchecked() for panic

This commit is contained in:
Blaine Bublitz 2020-07-06 16:54:57 -07:00
parent 33f0407dc6
commit c48f126fcd
9 changed files with 29 additions and 20 deletions

View File

@ -11,11 +11,11 @@ struct Query;
#[Object] #[Object]
impl Query { impl Query {
async fn borrow_from_context_data<'ctx'>( async fn borrow_from_context_data<'ctx>(
&self, &self,
ctx: &'ctx Context<'_> ctx: &'ctx Context<'_>
) -> &'ctx String { ) -> FieldResult<&'ctx String> {
ctx.data::<String> ctx.data::<String>()
} }
} }
``` ```

View File

@ -28,7 +28,7 @@ impl MyObject {
ctx: &Context<'_>, ctx: &Context<'_>,
#[arg(desc = "Id of object")] id: i64 #[arg(desc = "Id of object")] id: i64
) -> FieldResult<String> { ) -> FieldResult<String> {
let conn = ctx.data::<DbPool>().take(); let conn = ctx.data::<DbPool>()?.take();
Ok(conn.query_something(id)?.name) Ok(conn.query_something(id)?.name)
} }
} }

View File

@ -11,11 +11,11 @@ struct Query;
#[Object] #[Object]
impl Query { impl Query {
async fn borrow_from_context_data<'ctx'>( async fn borrow_from_context_data<'ctx>(
&self, &self,
ctx: &'ctx Context<'_> ctx: &'ctx Context<'_>
) -> &'ctx String { ) -> FieldResult<&'ctx String> {
ctx.data::<String> ctx.data::<String>()
} }
} }
``` ```

View File

@ -26,7 +26,7 @@ impl MyObject {
ctx: &Context<'_>, ctx: &Context<'_>,
#[arg(desc = "Id of object")] id: i64 #[arg(desc = "Id of object")] id: i64
) -> FieldResult<String> { ) -> FieldResult<String> {
let conn = ctx.data::<DbPool>().take(); let conn = ctx.data::<DbPool>()?.take();
Ok(conn.query_something(id)?.name) Ok(conn.query_something(id)?.name)
} }
} }

View File

@ -2,7 +2,8 @@ use crate::extensions::Extensions;
use crate::parser::query::{Directive, Field, SelectionSet}; use crate::parser::query::{Directive, Field, SelectionSet};
use crate::schema::SchemaEnv; use crate::schema::SchemaEnv;
use crate::{ use crate::{
InputValueType, Lookahead, Pos, Positioned, QueryError, QueryResponse, Result, Type, Value, FieldResult, InputValueType, Lookahead, Pos, Positioned, QueryError, QueryResponse, Result,
Type, Value,
}; };
use async_graphql_parser::query::Document; use async_graphql_parser::query::Document;
use async_graphql_parser::UploadValue; use async_graphql_parser::UploadValue;
@ -399,12 +400,20 @@ impl<'a, T> ContextBase<'a, T> {
/// ///
/// If both `Schema` and `Query` have the same data type, the data in the `Query` is obtained. /// If both `Schema` and `Query` have the same data type, the data in the `Query` is obtained.
/// ///
/// Returns a FieldError if the specified type data does not exist.
pub fn data<D: Any + Send + Sync>(&self) -> FieldResult<&D> {
self.data_opt::<D>()
.ok_or_else(|| format!("Data `{}` does not exist.", std::any::type_name::<D>()).into())
}
/// Gets the global data defined in the `Context` or `Schema`.
///
/// # Panics /// # Panics
/// ///
/// It will panic if the specified data type does not exist. /// It will panic if the specified data type does not exist.
pub fn data<D: Any + Send + Sync>(&self) -> &D { pub fn data_unchecked<D: Any + Send + Sync>(&self) -> &D {
self.data_opt::<D>() self.data_opt::<D>()
.expect("The specified data type does not exist.") .unwrap_or_else(|| panic!("Data `{}` does not exist.", std::any::type_name::<D>()))
} }
/// Gets the global data defined in the `Context` or `Schema`, returns `None` if the specified type data does not exist. /// Gets the global data defined in the `Context` or `Schema`, returns `None` if the specified type data does not exist.

View File

@ -549,8 +549,8 @@ pub use async_graphql_derive::InputObject;
/// #[Object] /// #[Object]
/// impl TypeA { /// impl TypeA {
/// /// Returns data borrowed from the context /// /// Returns data borrowed from the context
/// async fn value_a<'a>(&self, ctx: &'a Context<'_>) -> &'a str { /// async fn value_a<'a>(&self, ctx: &'a Context<'_>) -> FieldResult<&'a str> {
/// ctx.data::<String>().as_str() /// Ok(ctx.data::<String>()?.as_str())
/// } /// }
/// ///
/// /// Returns data borrowed self /// /// Returns data borrowed self

View File

@ -16,13 +16,13 @@ pub async fn test_mutation_execution_order() {
impl MutationRoot { impl MutationRoot {
async fn append1(&self, ctx: &Context<'_>) -> bool { async fn append1(&self, ctx: &Context<'_>) -> bool {
async_std::task::sleep(Duration::from_secs(1)).await; async_std::task::sleep(Duration::from_secs(1)).await;
ctx.data::<List>().lock().await.push(1); ctx.data_unchecked::<List>().lock().await.push(1);
true true
} }
async fn append2(&self, ctx: &Context<'_>) -> bool { async fn append2(&self, ctx: &Context<'_>) -> bool {
async_std::task::sleep(Duration::from_millis(500)).await; async_std::task::sleep(Duration::from_millis(500)).await;
ctx.data::<List>().lock().await.push(2); ctx.data_unchecked::<List>().lock().await.push(2);
true true
} }
} }

View File

@ -157,7 +157,7 @@ pub async fn test_subscription_with_ctx_data() {
#[Object] #[Object]
impl MyObject { impl MyObject {
async fn value(&self, ctx: &Context<'_>) -> i32 { async fn value(&self, ctx: &Context<'_>) -> i32 {
*ctx.data::<i32>() *ctx.data_unchecked::<i32>()
} }
} }
@ -166,7 +166,7 @@ pub async fn test_subscription_with_ctx_data() {
#[Subscription] #[Subscription]
impl SubscriptionRoot { impl SubscriptionRoot {
async fn values(&self, ctx: &Context<'_>) -> impl Stream<Item = i32> { async fn values(&self, ctx: &Context<'_>) -> impl Stream<Item = i32> {
let value = *ctx.data::<i32>(); let value = *ctx.data_unchecked::<i32>();
futures::stream::once(async move { value }) futures::stream::once(async move { value })
} }
@ -217,7 +217,7 @@ pub async fn test_subscription_with_token() {
#[Subscription] #[Subscription]
impl SubscriptionRoot { impl SubscriptionRoot {
async fn values(&self, ctx: &Context<'_>) -> FieldResult<impl Stream<Item = i32>> { async fn values(&self, ctx: &Context<'_>) -> FieldResult<impl Stream<Item = i32>> {
if ctx.data::<Token>().0 != "123456" { if ctx.data_unchecked::<Token>().0 != "123456" {
return Err("forbidden".into()); return Err("forbidden".into());
} }
Ok(futures::stream::once(async move { 100 })) Ok(futures::stream::once(async move { 100 }))

View File

@ -78,7 +78,7 @@ pub async fn test_subscription_ws_transport_with_token() {
#[Subscription] #[Subscription]
impl SubscriptionRoot { impl SubscriptionRoot {
async fn values(&self, ctx: &Context<'_>) -> FieldResult<impl Stream<Item = i32>> { async fn values(&self, ctx: &Context<'_>) -> FieldResult<impl Stream<Item = i32>> {
if ctx.data::<Token>().0 != "123456" { if ctx.data_unchecked::<Token>().0 != "123456" {
return Err("forbidden".into()); return Err("forbidden".into());
} }
Ok(futures::stream::iter(0..10)) Ok(futures::stream::iter(0..10))