Merge pull request #891 from DoumanAsh/split_execution
Introduce ability to pre-parse Request's query
This commit is contained in:
commit
300cbe54c7
|
@ -365,6 +365,7 @@ impl std::str::FromStr for Protocols {
|
|||
/// A websocket message received from the client
|
||||
#[derive(Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
#[allow(clippy::large_enum_variant)] //Request is at fault
|
||||
pub enum ClientMessage {
|
||||
/// A new connection
|
||||
ConnectionInit {
|
||||
|
|
|
@ -4,7 +4,9 @@ use std::fmt::{self, Debug, Formatter};
|
|||
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
|
||||
use crate::{Data, ParseRequestError, UploadValue, Value, Variables};
|
||||
use crate::parser::parse_query;
|
||||
use crate::parser::types::ExecutableDocument;
|
||||
use crate::{Data, ParseRequestError, ServerError, UploadValue, Value, Variables};
|
||||
|
||||
/// GraphQL request.
|
||||
///
|
||||
|
@ -42,6 +44,9 @@ pub struct Request {
|
|||
/// Disable introspection queries for this request.
|
||||
#[serde(skip)]
|
||||
pub disable_introspection: bool,
|
||||
|
||||
#[serde(skip)]
|
||||
pub(crate) parsed_query: Option<ExecutableDocument>,
|
||||
}
|
||||
|
||||
impl Request {
|
||||
|
@ -55,6 +60,7 @@ impl Request {
|
|||
data: Data::default(),
|
||||
extensions: Default::default(),
|
||||
disable_introspection: false,
|
||||
parsed_query: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,6 +93,24 @@ impl Request {
|
|||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Performs parsing of query ahead of execution.
|
||||
///
|
||||
/// This effectively allows to inspect query information, before passing request to schema for
|
||||
/// execution as long as query is valid.
|
||||
pub fn parsed_query(&mut self) -> Result<&ExecutableDocument, ServerError> {
|
||||
if self.parsed_query.is_none() {
|
||||
match parse_query(&self.query) {
|
||||
Ok(parsed) => self.parsed_query = Some(parsed),
|
||||
Err(error) => return Err(error.into()),
|
||||
}
|
||||
}
|
||||
|
||||
//forbid_unsafe effectively bans optimize away else branch here so use unwrap
|
||||
//but this unwrap never panics
|
||||
Ok(self.parsed_query.as_ref().unwrap())
|
||||
}
|
||||
|
||||
/// Set a variable to an upload value.
|
||||
///
|
||||
/// `var_path` is a dot-separated path to the item that begins with `variables`, for example
|
||||
|
@ -141,6 +165,7 @@ impl Debug for Request {
|
|||
/// **Reference:** <https://www.apollographql.com/blog/batching-client-graphql-queries-a685f5bcd41b/>
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
#[allow(clippy::large_enum_variant)] //Request is at fault
|
||||
pub enum BatchRequest {
|
||||
/// Single query
|
||||
Single(Request),
|
||||
|
|
|
@ -427,13 +427,19 @@ where
|
|||
let query_data = Arc::new(std::mem::take(&mut request.data));
|
||||
extensions.attach_query_data(query_data.clone());
|
||||
|
||||
let request = extensions.prepare_request(request).await?;
|
||||
let mut request = extensions.prepare_request(request).await?;
|
||||
let mut document = {
|
||||
let query = &request.query;
|
||||
let fut_parse = async { parse_query(&query).map_err(Into::<ServerError>::into) };
|
||||
let parsed_doc = request.parsed_query.take();
|
||||
let fut_parse = async move {
|
||||
match parsed_doc {
|
||||
Some(parsed_doc) => Ok(parsed_doc),
|
||||
None => parse_query(query).map_err(Into::into),
|
||||
}
|
||||
};
|
||||
futures_util::pin_mut!(fut_parse);
|
||||
extensions
|
||||
.parse_query(&query, &request.variables, &mut fut_parse)
|
||||
.parse_query(query, &request.variables, &mut fut_parse)
|
||||
.await?
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue