Skip to content

Commit

Permalink
Merge pull request apollographql#273 from DxCx/batching#176
Browse files Browse the repository at this point in the history
Run batching queries in parallel (apollographql#176)
  • Loading branch information
DxCx authored Jan 24, 2017
2 parents c05c176 + f0127a4 commit fd77345
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Changelog

### VNEXT
* run batched requests in parallel ([@DxCx](https://github.com/DxCx)) on [#273](https://github.com/apollostack/graphql-server/pull/273)
* Fix GraphiQL options variables. Issue #193. ([@alanchristensen](https://github.com/alanchristensen)) on
[PR #255](https://github.com/apollostack/apollo-server/pull/255)

Expand Down
12 changes: 6 additions & 6 deletions packages/graphql-server-core/src/runHttpQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ export async function runHttpQuery(handlerArguments: Array<any>, request: HttpQu
requestPayload = [requestPayload];
}

let responses: Array<ExecutionResult> = [];
for (let requestParams of requestPayload) {
const requests: Array<ExecutionResult> = requestPayload.map(requestParams => {
try {
let query = requestParams.query;
if ( isGetRequest ) {
Expand Down Expand Up @@ -128,17 +127,18 @@ export async function runHttpQuery(handlerArguments: Array<any>, request: HttpQu
params = optionsObject.formatParams(params);
}

responses.push(await runQuery(params));
return runQuery(params);
} catch (e) {
// Populate any HttpQueryError to our handler which should
// convert it to Http Error.
if ( e.name === 'HttpQueryError' ) {
throw e;
return Promise.reject(e);
}

responses.push({ errors: [formatErrorFn(e)] });
return Promise.resolve({ errors: [formatErrorFn(e)] });
}
}
});
const responses = await Promise.all(requests);

if (!isBatch) {
const gqlResponse = responses[0];
Expand Down
8 changes: 6 additions & 2 deletions packages/graphql-server-express/src/apolloServerHttp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ const version = 'modern';
describe(`GraphQL-HTTP (apolloServer) tests for ${version} express`, () => {
describe('POST functionality', () => {

it('allows gzipped POST bodies', async () => {
it('allows gzipped POST bodies', async function () {
// Increase timeout for slow node 4
this.timeout(3000);
const app = express();

app.use(urlString(), bodyParser.json());
Expand All @@ -181,7 +183,9 @@ describe(`GraphQL-HTTP (apolloServer) tests for ${version} express`, () => {
});
});

it('allows deflated POST bodies', async () => {
it('allows deflated POST bodies', async function () {
// Increase timeout for slow node 4
this.timeout(3000);
const app = express();

app.use(urlString(), bodyParser.json());
Expand Down
35 changes: 35 additions & 0 deletions packages/graphql-server-integration-testsuite/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLInt,
GraphQLError,
GraphQLNonNull,
introspectionQuery,
Expand All @@ -29,6 +30,17 @@ const queryType = new GraphQLObjectType({
return 'it works';
},
},
testStringWithDelay: {
type: GraphQLString,
args: {
delay: { type: new GraphQLNonNull(GraphQLInt) },
},
resolve(root, args) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('it works'), args['delay']);
});
},
},
testContext: {
type: GraphQLString,
resolve(_, args, context) {
Expand Down Expand Up @@ -457,6 +469,29 @@ export default (createApp: CreateAppFunc, destroyApp?: DestroyAppFunc) => {
});
});

it('can handle batch requests in parallel', function() {
// this test will fail due to timeout if running serially.
const parallels = 100;
const delayPerReq = 40;
this.timeout(3000);

app = createApp();
const expected = Array(parallels).fill({
data: { testStringWithDelay: 'it works' },
});
const req = request(app)
.post('/graphql')
.send(Array(parallels).fill({
query: `query test($delay: Int!) { testStringWithDelay(delay: $delay) }`,
operationName: 'test',
variables: { delay: delayPerReq },
}));
return req.then((res) => {
expect(res.status).to.equal(200);
return expect(res.body).to.deep.equal(expected);
});
});

it('clones batch context', () => {
app = createApp({graphqlOptions: {
schema,
Expand Down

0 comments on commit fd77345

Please sign in to comment.