Skip to content

Commit c79490b

Browse files
committed
server: Refactor away GraphQLResponse
1 parent 04a92bb commit c79490b

File tree

19 files changed

+269
-539
lines changed

19 files changed

+269
-539
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

graph/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ reqwest = "0.10"
2323
# ethabi, but long term we want to find a way to drop our fork.
2424
ethabi = { git = "https://github.com/graphprotocol/ethabi.git", branch = "master" }
2525
hex = "0.4.2"
26+
http = "0.2"
2627
futures = "0.1.21"
2728
graphql-parser = "0.2.3"
2829
ipfs-api = { version = "0.7.1", features = ["hyper-tls"] }

graph/src/components/graphql.rs

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
use futures::prelude::*;
22

33
use crate::data::graphql::effort::LoadManager;
4-
use crate::data::query::{Query, QueryError, QueryResult};
4+
use crate::data::query::{Query, QueryResult};
55
use crate::data::subscription::{Subscription, SubscriptionError, SubscriptionResult};
66

77
use async_trait::async_trait;
88
use failure::format_err;
99
use failure::Error;
10-
use futures03::compat::Future01CompatExt;
1110
use graphql_parser::query as q;
1211
use std::sync::Arc;
1312

14-
/// Future for query results.
15-
pub type QueryResultFuture = Box<dyn Future<Item = Arc<QueryResult>, Error = QueryError> + Send>;
16-
1713
/// Future for subscription results.
1814
pub type SubscriptionResultFuture =
1915
Box<dyn Future<Item = SubscriptionResult, Error = SubscriptionError> + Send>;
@@ -22,34 +18,32 @@ pub type SubscriptionResultFuture =
2218
#[async_trait]
2319
pub trait GraphQlRunner: Send + Sync + 'static {
2420
/// Runs a GraphQL query and returns its result.
25-
fn run_query(&self, query: Query) -> QueryResultFuture;
21+
async fn run_query(self: Arc<Self>, query: Query) -> Arc<QueryResult>;
2622

2723
/// Runs a GraphqL query up to the given complexity. Overrides the global complexity limit.
28-
fn run_query_with_complexity(
24+
async fn run_query_with_complexity(
2925
&self,
3026
query: Query,
3127
max_complexity: Option<u64>,
3228
max_depth: Option<u8>,
3329
max_first: Option<u32>,
34-
) -> QueryResultFuture;
30+
) -> Arc<QueryResult>;
3531

3632
/// Runs a GraphQL subscription and returns a stream of results.
3733
fn run_subscription(&self, subscription: Subscription) -> SubscriptionResultFuture;
3834

3935
async fn query_metadata(&self, query: Query) -> Result<q::Value, Error> {
40-
self.run_query_with_complexity(query, None, None, None)
41-
.compat()
42-
.await
43-
.map_err(move |e| format_err!("Failed to query metadata: {}", e))
44-
.and_then(move |result| {
45-
// Metadata queries are not cached.
46-
let result = Arc::try_unwrap(result).unwrap();
47-
if result.errors.is_some() {
48-
Err(format_err!("Failed to query metadata: {:?}", result.errors))
49-
} else {
50-
result.data.ok_or_else(|| format_err!("No metadata found"))
51-
}
52-
})
36+
let result = self
37+
.run_query_with_complexity(query, None, None, None)
38+
.await;
39+
40+
// Metadata queries are not cached.
41+
let result = Arc::try_unwrap(result).unwrap();
42+
if result.errors.is_some() {
43+
Err(format_err!("Failed to query metadata: {:?}", result.errors))
44+
} else {
45+
result.data.ok_or_else(|| format_err!("No metadata found"))
46+
}
5347
}
5448

5549
fn load_manager(&self) -> Arc<LoadManager>;

graph/src/components/server/query.rs

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,26 @@
11
use crate::data::query::QueryError;
22
use futures::prelude::*;
3-
use futures::sync::oneshot::Canceled;
43
use serde::ser::*;
54
use std::error::Error;
65
use std::fmt;
76

87
/// Errors that can occur while processing incoming requests.
98
#[derive(Debug)]
109
pub enum GraphQLServerError {
11-
Canceled(Canceled),
1210
ClientError(String),
1311
QueryError(QueryError),
1412
InternalError(String),
1513
}
1614

17-
impl From<Canceled> for GraphQLServerError {
18-
fn from(e: Canceled) -> Self {
19-
GraphQLServerError::Canceled(e)
20-
}
21-
}
22-
2315
impl From<QueryError> for GraphQLServerError {
2416
fn from(e: QueryError) -> Self {
2517
GraphQLServerError::QueryError(e)
2618
}
2719
}
2820

29-
impl From<&'static str> for GraphQLServerError {
30-
fn from(s: &'static str) -> Self {
31-
GraphQLServerError::InternalError(String::from(s))
32-
}
33-
}
34-
35-
impl From<String> for GraphQLServerError {
36-
fn from(s: String) -> Self {
37-
GraphQLServerError::InternalError(s)
38-
}
39-
}
40-
4121
impl fmt::Display for GraphQLServerError {
4222
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4323
match *self {
44-
GraphQLServerError::Canceled(_) => {
45-
write!(f, "GraphQL server error (query was canceled)")
46-
}
4724
GraphQLServerError::ClientError(ref s) => {
4825
write!(f, "GraphQL server error (client error): {}", s)
4926
}
@@ -64,7 +41,6 @@ impl Error for GraphQLServerError {
6441

6542
fn cause(&self) -> Option<&dyn Error> {
6643
match *self {
67-
GraphQLServerError::Canceled(ref e) => Some(e),
6844
GraphQLServerError::ClientError(_) => None,
6945
GraphQLServerError::QueryError(ref e) => Some(e),
7046
GraphQLServerError::InternalError(_) => None,

graph/src/data/query/result.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@ impl QueryResult {
7878
_ => self.errors = self.errors.take().or(other.errors),
7979
}
8080
}
81+
82+
pub fn as_http_response<T: From<String>>(&self) -> http::Response<T> {
83+
let status_code = http::StatusCode::OK;
84+
let json =
85+
serde_json::to_string(&self).expect("Failed to serialize GraphQL response to JSON");
86+
http::Response::builder()
87+
.status(status_code)
88+
.header("Access-Control-Allow-Origin", "*")
89+
.header("Access-Control-Allow-Headers", "Content-Type, User-Agent")
90+
.header("Access-Control-Allow-Methods", "GET, OPTIONS, POST")
91+
.header("Content-Type", "application/json")
92+
.body(T::from(json))
93+
.unwrap()
94+
}
8195
}
8296

8397
impl From<QueryExecutionError> for QueryResult {
@@ -88,6 +102,16 @@ impl From<QueryExecutionError> for QueryResult {
88102
}
89103
}
90104

105+
impl From<QueryError> for QueryResult {
106+
fn from(e: QueryError) -> Self {
107+
QueryResult {
108+
data: None,
109+
errors: Some(vec![e]),
110+
extensions: None,
111+
}
112+
}
113+
}
114+
91115
impl From<Vec<QueryExecutionError>> for QueryResult {
92116
fn from(e: Vec<QueryExecutionError>) -> Self {
93117
QueryResult {

graph/src/lib.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,7 @@ pub mod prelude {
8383
EthereumNetworkIdentifier, EthereumTransactionData, EthereumTrigger, LightEthereumBlock,
8484
LightEthereumBlockExt, ProviderEthRpcMetrics, SubgraphEthRpcMetrics,
8585
};
86-
pub use crate::components::graphql::{
87-
GraphQlRunner, QueryResultFuture, SubscriptionResultFuture,
88-
};
86+
pub use crate::components::graphql::{GraphQlRunner, SubscriptionResultFuture};
8987
pub use crate::components::link_resolver::{JsonStreamValue, JsonValueStream, LinkResolver};
9088
pub use crate::components::metrics::{
9189
aggregate::Aggregate, stopwatch::StopwatchMetrics, Collector, Counter, CounterVec, Gauge,

graphql/src/runner.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ use crate::query::execute_query;
1313
use crate::subscription::execute_prepared_subscription;
1414
use graph::data::graphql::effort::LoadManager;
1515
use graph::prelude::{
16-
o, EthereumBlockPointer, GraphQlRunner as GraphQlRunnerTrait, Logger, Query,
17-
QueryExecutionError, QueryResult, QueryResultFuture, Store, StoreError, SubgraphDeploymentId,
16+
async_trait, o, EthereumBlockPointer, GraphQlRunner as GraphQlRunnerTrait, Logger, Query,
17+
QueryExecutionError, QueryResult, Store, StoreError, SubgraphDeploymentId,
1818
SubgraphDeploymentStore, Subscription, SubscriptionError, SubscriptionResultFuture,
1919
};
2020

@@ -107,7 +107,7 @@ where
107107
Ok(exts)
108108
}
109109

110-
pub fn execute(
110+
fn execute(
111111
&self,
112112
query: Query,
113113
max_complexity: Option<u64>,
@@ -166,30 +166,30 @@ where
166166
}
167167
}
168168

169+
#[async_trait]
169170
impl<S> GraphQlRunnerTrait for GraphQlRunner<S>
170171
where
171172
S: Store + SubgraphDeploymentStore,
172173
{
173-
fn run_query(&self, query: Query) -> QueryResultFuture {
174+
async fn run_query(self: Arc<Self>, query: Query) -> Arc<QueryResult> {
174175
self.run_query_with_complexity(
175176
query,
176177
*GRAPHQL_MAX_COMPLEXITY,
177178
Some(*GRAPHQL_MAX_DEPTH),
178179
Some(*GRAPHQL_MAX_FIRST),
179180
)
181+
.await
180182
}
181183

182-
fn run_query_with_complexity(
184+
async fn run_query_with_complexity(
183185
&self,
184186
query: Query,
185187
max_complexity: Option<u64>,
186188
max_depth: Option<u8>,
187189
max_first: Option<u32>,
188-
) -> QueryResultFuture {
189-
Box::new(future::ok(
190-
self.execute(query, max_complexity, max_depth, max_first)
191-
.unwrap_or_else(|e| Arc::new(e)),
192-
))
190+
) -> Arc<QueryResult> {
191+
self.execute(query, max_complexity, max_depth, max_first)
192+
.unwrap_or_else(|e| Arc::new(e))
193193
}
194194

195195
fn run_subscription(&self, subscription: Subscription) -> SubscriptionResultFuture {

graphql/tests/query.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ use std::time::{Duration, Instant};
1010

1111
use graph::prelude::{
1212
futures03::stream::StreamExt, futures03::FutureExt, futures03::TryFutureExt, o, slog, tokio,
13-
Entity, EntityKey, EntityOperation, EthereumBlockPointer, FutureExtension, Logger, Query,
14-
QueryError, QueryExecutionError, QueryResult, QueryVariables, Schema, Store,
13+
Entity, EntityKey, EntityOperation, EthereumBlockPointer, FutureExtension, GraphQlRunner as _,
14+
Logger, Query, QueryError, QueryExecutionError, QueryResult, QueryVariables, Schema, Store,
1515
SubgraphDeploymentEntity, SubgraphDeploymentId, SubgraphDeploymentStore, SubgraphManifest,
1616
Subscription, SubscriptionError, Value,
1717
};
1818
use graph_graphql::prelude::*;
1919
use test_store::{
20-
execute_subgraph_query_with_complexity, execute_subgraph_query_with_deadline, return_err,
20+
execute_subgraph_query_with_complexity, execute_subgraph_query_with_deadline,
2121
transact_entity_operations, BLOCK_ONE, GENESIS_PTR, LOAD_MANAGER, LOGGER, STORE,
2222
};
2323

@@ -233,9 +233,11 @@ fn execute_query_document_with_variables(
233233
let runner = GraphQlRunner::new(&*LOGGER, STORE.clone(), LOAD_MANAGER.clone());
234234
let query = Query::new(Arc::new(api_test_schema()), query, variables, None);
235235

236-
return_err!(runner.execute(query, None, None, None))
237-
.as_ref()
238-
.clone()
236+
graph::prelude::futures03::executor::block_on(
237+
runner.run_query_with_complexity(query, None, None, None),
238+
)
239+
.as_ref()
240+
.clone()
239241
}
240242

241243
#[test]

server/http/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,10 @@ extern crate hyper;
99
extern crate serde;
1010

1111
mod request;
12-
mod response;
1312
mod server;
1413
mod service;
1514

1615
pub use self::request::GraphQLRequest;
17-
pub use self::response::GraphQLResponse;
1816
pub use self::server::GraphQLServer;
1917
pub use self::service::{GraphQLService, GraphQLServiceResponse};
2018

server/http/src/request.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ impl Future for GraphQLRequest {
4343
// Ensure the JSON data has a "query" field
4444
let query_value = obj.get("query").ok_or_else(|| {
4545
GraphQLServerError::ClientError(String::from(
46-
"The \"query\" field missing in request data",
46+
"The \"query\" field is missing in request data",
4747
))
4848
})?;
4949

5050
// Ensure the "query" field is a string
5151
let query_string = query_value.as_str().ok_or_else(|| {
52-
GraphQLServerError::ClientError(String::from("The\"query\" field is not a string"))
52+
GraphQLServerError::ClientError(String::from("The \"query\" field is not a string"))
5353
})?;
5454

5555
// Parse the "query" field of the JSON body

0 commit comments

Comments
 (0)