Merge branch 'master' into rework-core-traits

This commit is contained in:
tyranron 2022-09-20 15:45:32 +03:00
commit 0b6544db48
No known key found for this signature in database
GPG key ID: 762E144FB230A4F0
6 changed files with 107 additions and 96 deletions

View file

@ -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

View file

@ -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]]

View file

@ -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);

View file

@ -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

View file

@ -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
}

View file

@ -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
})