Merge branch 'master' into rework-core-traits
This commit is contained in:
commit
0b6544db48
6 changed files with 107 additions and 96 deletions
15
.github/workflows/ci.yml
vendored
15
.github/workflows/ci.yml
vendored
|
@ -23,6 +23,7 @@ jobs:
|
|||
pr:
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
needs:
|
||||
- bench
|
||||
- clippy
|
||||
- example
|
||||
- feature
|
||||
|
@ -73,6 +74,19 @@ jobs:
|
|||
# Testing #
|
||||
###########
|
||||
|
||||
bench:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
|
||||
- run: cargo clippy -p juniper_benchmarks --benches -- -D warnings
|
||||
- run: cargo bench -p juniper_benchmarks
|
||||
|
||||
example:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
@ -295,6 +309,7 @@ jobs:
|
|||
release-github:
|
||||
name: Release on GitHub
|
||||
needs:
|
||||
- bench
|
||||
- clippy
|
||||
- example
|
||||
- feature
|
||||
|
|
|
@ -10,7 +10,7 @@ futures = "0.3"
|
|||
juniper = { path = "../juniper" }
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.3"
|
||||
criterion = "0.4"
|
||||
tokio = { version = "1.0", features = ["rt-multi-thread"] }
|
||||
|
||||
[[bench]]
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use criterion::{criterion_group, criterion_main, Criterion, ParameterizedBenchmark};
|
||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||
|
||||
use juniper::InputValue;
|
||||
use juniper_benchmarks as j;
|
||||
|
||||
fn bench_sync_vs_async_users_flat_instant(c: &mut Criterion) {
|
||||
const ASYNC_QUERY: &'static str = r#"
|
||||
// language=GraphQL
|
||||
const ASYNC_QUERY: &str = r#"
|
||||
query Query($id: Int) {
|
||||
users_async_instant(ids: [$id]!) {
|
||||
id
|
||||
|
@ -15,74 +16,70 @@ fn bench_sync_vs_async_users_flat_instant(c: &mut Criterion) {
|
|||
}
|
||||
"#;
|
||||
|
||||
const SYNC_QUERY: &'static str = r#"
|
||||
query Query($id: Int) {
|
||||
users_sync_instant(ids: [$id]!) {
|
||||
id
|
||||
kind
|
||||
username
|
||||
email
|
||||
// language=GraphQL
|
||||
const SYNC_QUERY: &str = r#"
|
||||
query Query($id: Int) {
|
||||
users_sync_instant(ids: [$id]!) {
|
||||
id
|
||||
kind
|
||||
username
|
||||
email
|
||||
}
|
||||
}
|
||||
"#;
|
||||
|
||||
let mut group = c.benchmark_group("Sync vs Async - Users Flat - Instant");
|
||||
for count in [1, 10] {
|
||||
group.bench_function(BenchmarkId::new("Sync", count), |b| {
|
||||
let ids = (0..count)
|
||||
.map(|x| InputValue::scalar(x as i32))
|
||||
.collect::<Vec<_>>();
|
||||
let ids = InputValue::list(ids);
|
||||
b.iter(|| {
|
||||
j::execute_sync(
|
||||
SYNC_QUERY,
|
||||
vec![("ids".to_owned(), ids.clone())].into_iter().collect(),
|
||||
)
|
||||
})
|
||||
});
|
||||
|
||||
group.bench_function(BenchmarkId::new("Async - Single Thread", count), |b| {
|
||||
let rt = tokio::runtime::Builder::new_current_thread()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let ids = (0..count)
|
||||
.map(|x| InputValue::scalar(x as i32))
|
||||
.collect::<Vec<_>>();
|
||||
let ids = InputValue::list(ids);
|
||||
|
||||
b.iter(|| {
|
||||
let f = j::execute(
|
||||
ASYNC_QUERY,
|
||||
vec![("ids".to_owned(), ids.clone())].into_iter().collect(),
|
||||
);
|
||||
rt.block_on(f)
|
||||
})
|
||||
});
|
||||
|
||||
group.bench_function(BenchmarkId::new("Async - Threadpool", count), |b| {
|
||||
let rt = tokio::runtime::Builder::new_multi_thread().build().unwrap();
|
||||
|
||||
let ids = (0..count)
|
||||
.map(|x| InputValue::scalar(x as i32))
|
||||
.collect::<Vec<_>>();
|
||||
let ids = InputValue::list(ids);
|
||||
|
||||
b.iter(|| {
|
||||
let f = j::execute(
|
||||
ASYNC_QUERY,
|
||||
vec![("ids".to_owned(), ids.clone())].into_iter().collect(),
|
||||
);
|
||||
rt.block_on(f)
|
||||
})
|
||||
});
|
||||
}
|
||||
"#;
|
||||
|
||||
c.bench(
|
||||
"Sync vs Async - Users Flat - Instant",
|
||||
ParameterizedBenchmark::new(
|
||||
"Sync",
|
||||
|b, count| {
|
||||
let ids = (0..*count)
|
||||
.map(|x| InputValue::scalar(x as i32))
|
||||
.collect::<Vec<_>>();
|
||||
let ids = InputValue::list(ids);
|
||||
b.iter(|| {
|
||||
j::execute_sync(
|
||||
SYNC_QUERY,
|
||||
vec![("ids".to_owned(), ids.clone())].into_iter().collect(),
|
||||
)
|
||||
})
|
||||
},
|
||||
vec![1, 10],
|
||||
)
|
||||
.with_function("Async - Single Thread", |b, count| {
|
||||
let mut rt = tokio::runtime::Builder::new()
|
||||
.basic_scheduler()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let ids = (0..*count)
|
||||
.map(|x| InputValue::scalar(x as i32))
|
||||
.collect::<Vec<_>>();
|
||||
let ids = InputValue::list(ids);
|
||||
|
||||
b.iter(|| {
|
||||
let f = j::execute(
|
||||
ASYNC_QUERY,
|
||||
vec![("ids".to_owned(), ids.clone())].into_iter().collect(),
|
||||
);
|
||||
rt.block_on(f)
|
||||
})
|
||||
})
|
||||
.with_function("Async - Threadpool", |b, count| {
|
||||
let mut rt = tokio::runtime::Builder::new()
|
||||
.threaded_scheduler()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let ids = (0..*count)
|
||||
.map(|x| InputValue::scalar(x as i32))
|
||||
.collect::<Vec<_>>();
|
||||
let ids = InputValue::list(ids);
|
||||
|
||||
b.iter(|| {
|
||||
let f = j::execute(
|
||||
ASYNC_QUERY,
|
||||
vec![("ids".to_owned(), ids.clone())].into_iter().collect(),
|
||||
);
|
||||
rt.block_on(f)
|
||||
})
|
||||
}),
|
||||
);
|
||||
group.finish();
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_sync_vs_async_users_flat_instant);
|
||||
|
|
|
@ -11,6 +11,10 @@ All user visible changes to `juniper_hyper` crate will be documented in this fil
|
|||
### BC Breaks
|
||||
|
||||
- Switched to 0.16 version of [`juniper` crate].
|
||||
- Changed return type of all functions from `Response<Body>` to `Response<String>`. ([#1101], [#1096])
|
||||
|
||||
[#1096]: /../../issues/1096
|
||||
[#1101]: /../../pull/1101
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::{convert::Infallible, sync::Arc};
|
|||
use hyper::{
|
||||
server::Server,
|
||||
service::{make_service_fn, service_fn},
|
||||
Body, Method, Response, StatusCode,
|
||||
Method, Response, StatusCode,
|
||||
};
|
||||
use juniper::{
|
||||
tests::fixtures::starwars::schema::{Database, Query},
|
||||
|
@ -38,7 +38,7 @@ async fn main() {
|
|||
juniper_hyper::graphql(root_node, ctx, req).await
|
||||
}
|
||||
_ => {
|
||||
let mut response = Response::new(Body::empty());
|
||||
let mut response = Response::new(String::new());
|
||||
*response.status_mut() = StatusCode::NOT_FOUND;
|
||||
response
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ pub async fn graphql_sync<CtxT, QueryT, MutationT, SubscriptionT, S>(
|
|||
root_node: Arc<RootNode<'static, QueryT, MutationT, SubscriptionT, S>>,
|
||||
context: Arc<CtxT>,
|
||||
req: Request<Body>,
|
||||
) -> Response<Body>
|
||||
) -> Response<String>
|
||||
where
|
||||
QueryT: GraphQLType<S, Context = CtxT>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
|
@ -38,7 +38,7 @@ pub async fn graphql<CtxT, QueryT, MutationT, SubscriptionT, S>(
|
|||
root_node: Arc<RootNode<'static, QueryT, MutationT, SubscriptionT, S>>,
|
||||
context: Arc<CtxT>,
|
||||
req: Request<Body>,
|
||||
) -> Response<Body>
|
||||
) -> Response<String>
|
||||
where
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
|
@ -57,7 +57,7 @@ where
|
|||
|
||||
async fn parse_req<S: ScalarValue>(
|
||||
req: Request<Body>,
|
||||
) -> Result<GraphQLBatchRequest<S>, Response<Body>> {
|
||||
) -> Result<GraphQLBatchRequest<S>, Response<String>> {
|
||||
match *req.method() {
|
||||
Method::GET => parse_get_req(req),
|
||||
Method::POST => {
|
||||
|
@ -121,32 +121,27 @@ async fn parse_post_graphql_req<S: ScalarValue>(
|
|||
pub async fn graphiql(
|
||||
graphql_endpoint: &str,
|
||||
subscriptions_endpoint: Option<&str>,
|
||||
) -> Response<Body> {
|
||||
) -> Response<String> {
|
||||
let mut resp = new_html_response(StatusCode::OK);
|
||||
// XXX: is the call to graphiql_source blocking?
|
||||
*resp.body_mut() = Body::from(juniper::http::graphiql::graphiql_source(
|
||||
graphql_endpoint,
|
||||
subscriptions_endpoint,
|
||||
));
|
||||
*resp.body_mut() =
|
||||
juniper::http::graphiql::graphiql_source(graphql_endpoint, subscriptions_endpoint);
|
||||
resp
|
||||
}
|
||||
|
||||
pub async fn playground(
|
||||
graphql_endpoint: &str,
|
||||
subscriptions_endpoint: Option<&str>,
|
||||
) -> Response<Body> {
|
||||
) -> Response<String> {
|
||||
let mut resp = new_html_response(StatusCode::OK);
|
||||
*resp.body_mut() = Body::from(juniper::http::playground::playground_source(
|
||||
graphql_endpoint,
|
||||
subscriptions_endpoint,
|
||||
));
|
||||
*resp.body_mut() =
|
||||
juniper::http::playground::playground_source(graphql_endpoint, subscriptions_endpoint);
|
||||
resp
|
||||
}
|
||||
|
||||
fn render_error(err: GraphQLRequestError) -> Response<Body> {
|
||||
let message = err.to_string();
|
||||
fn render_error(err: GraphQLRequestError) -> Response<String> {
|
||||
let mut resp = new_response(StatusCode::BAD_REQUEST);
|
||||
*resp.body_mut() = Body::from(message);
|
||||
*resp.body_mut() = err.to_string();
|
||||
resp
|
||||
}
|
||||
|
||||
|
@ -154,7 +149,7 @@ async fn execute_request_sync<CtxT, QueryT, MutationT, SubscriptionT, S>(
|
|||
root_node: Arc<RootNode<'static, QueryT, MutationT, SubscriptionT, S>>,
|
||||
context: Arc<CtxT>,
|
||||
request: GraphQLBatchRequest<S>,
|
||||
) -> Response<Body>
|
||||
) -> Response<String>
|
||||
where
|
||||
QueryT: GraphQLType<S, Context = CtxT>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
|
@ -166,7 +161,7 @@ where
|
|||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
let res = request.execute_sync(&*root_node, &context);
|
||||
let body = Body::from(serde_json::to_string_pretty(&res).unwrap());
|
||||
let body = serde_json::to_string_pretty(&res).unwrap();
|
||||
let code = if res.is_ok() {
|
||||
StatusCode::OK
|
||||
} else {
|
||||
|
@ -185,7 +180,7 @@ async fn execute_request<CtxT, QueryT, MutationT, SubscriptionT, S>(
|
|||
root_node: Arc<RootNode<'static, QueryT, MutationT, SubscriptionT, S>>,
|
||||
context: Arc<CtxT>,
|
||||
request: GraphQLBatchRequest<S>,
|
||||
) -> Response<Body>
|
||||
) -> Response<String>
|
||||
where
|
||||
QueryT: GraphQLTypeAsync<S, Context = CtxT>,
|
||||
QueryT::TypeInfo: Sync,
|
||||
|
@ -197,7 +192,7 @@ where
|
|||
S: ScalarValue + Send + Sync,
|
||||
{
|
||||
let res = request.execute(&*root_node, &context).await;
|
||||
let body = Body::from(serde_json::to_string_pretty(&res).unwrap());
|
||||
let body = serde_json::to_string_pretty(&res).unwrap();
|
||||
let code = if res.is_ok() {
|
||||
StatusCode::OK
|
||||
} else {
|
||||
|
@ -260,13 +255,13 @@ fn invalid_err(parameter_name: &str) -> GraphQLRequestError {
|
|||
))
|
||||
}
|
||||
|
||||
fn new_response(code: StatusCode) -> Response<Body> {
|
||||
let mut r = Response::new(Body::empty());
|
||||
fn new_response(code: StatusCode) -> Response<String> {
|
||||
let mut r = Response::new(String::new());
|
||||
*r.status_mut() = code;
|
||||
r
|
||||
}
|
||||
|
||||
fn new_html_response(code: StatusCode) -> Response<Body> {
|
||||
fn new_html_response(code: StatusCode) -> Response<String> {
|
||||
let mut resp = new_response(code);
|
||||
resp.headers_mut().insert(
|
||||
header::CONTENT_TYPE,
|
||||
|
@ -313,7 +308,7 @@ mod tests {
|
|||
use hyper::{
|
||||
server::Server,
|
||||
service::{make_service_fn, service_fn},
|
||||
Body, Method, Response, StatusCode,
|
||||
Method, Response, StatusCode,
|
||||
};
|
||||
use juniper::{
|
||||
http::tests as http_tests,
|
||||
|
@ -409,7 +404,7 @@ mod tests {
|
|||
super::graphql(root_node, ctx, req).await
|
||||
}
|
||||
} else {
|
||||
let mut resp = Response::new(Body::empty());
|
||||
let mut resp = Response::new(String::new());
|
||||
*resp.status_mut() = StatusCode::NOT_FOUND;
|
||||
resp
|
||||
})
|
||||
|
|
Loading…
Add table
Reference in a new issue