Skip to content

Commit 2c375f1

Browse files
committed
docs and such
1 parent 37e32c6 commit 2c375f1

File tree

12 files changed

+291
-83
lines changed

12 files changed

+291
-83
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ The version headers in this history reflect the versions of Apollo Server itself
99

1010
## vNEXT
1111

12+
- `apollo-server-core`: Previously, only the batteries-included `apollo-server` package supported a graceful shutdown. Now the integrations support it as well, if you tell your `ApolloServer` which HTTP server to drain with the new `ApolloServerPluginDrainHttpServer` plugin. This plugin implements a new `drainServer` plugin hook. For `apollo-server-hapi` you can use `ApolloServerPluginStopHapiServer` instead. [PR #5635](https://github.com/apollographql/apollo-server/pull/5635)
1213
- `apollo-server-core`: Fix `experimental_approximateDocumentStoreMiB` option, which seems to have never worked before. [PR #5629](https://github.com/apollographql/apollo-server/pull/5629)
1314
- `apollo-server-core`: Only register `SIGINT` and `SIGTERM` handlers once the server successfully starts up; trying to call `stop` on a server that hasn't successfully started had undefined behavior. By default, don't register the handlers in serverless integrations, which don't have the same lifecycle as non-serverless integrations (eg, there's no explicit `start` call); you can still explicitly set `stopOnTerminationSignals` to override this default. [PR #5639](https://github.com/apollographql/apollo-server/pull/5639)
1415

docs/gatsby-config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ module.exports = {
7777
'api/plugin/usage-reporting',
7878
'api/plugin/schema-reporting',
7979
'api/plugin/inline-trace',
80+
'api/plugin/drain-http-server',
8081
'api/plugin/cache-control',
8182
'api/plugin/landing-pages',
8283
],

docs/source/api/apollo-server.md

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -517,22 +517,22 @@ The `start` method triggers the following actions:
517517

518518
## `stop`
519519

520-
`ApolloServer.stop()` is an async method that tells all of Apollo Server's background tasks to complete. It calls and awaits all [`serverWillStop` plugin handlers](../integrations/plugins-event-reference/#serverwillstop) (including the [usage reporting plugin](./plugin/usage-reporting/)'s handler, which sends a final usage report to Apollo Studio). This method takes no arguments. You should only call it after [`start()`](#start) returns successfully (or [`listen()`](#listen) if you're using the batteries-included `apollo-server` package).
520+
`ApolloServer.stop()` is an async method that tells all of Apollo Server's background tasks to complete. Specifically, it:
521521

522-
If your server is a [federated gateway](https://www.apollographql.com/docs/federation/gateway/), `stop` also stops gateway-specific background activities, such as polling for updated service configuration.
522+
- Calls and awaits all [`drainServer` plugin handlers](../integrations/plugins-event-reference/#drainserver). These should generally:
523+
* Stop listening for new connections
524+
* Closes idle connections (i.e., connections with no current HTTP request)
525+
* Closes active connections whenever they become idle
526+
* Waits for all connections to be closed
527+
* After a grace period, if any connections remain active, forcefully close them.
528+
If you're using the batteries-included `apollo-server` package, it does this by default. (You can configure the grace period with the [`stopGracePeriodMillis` constructor option](#stopgraceperiodmillis).) Otherwise, you can use the [drain HTTP server plugin](./plugin/drain-http-server/) to drain your HTTP server.
529+
- Transitions the server to a state where it will not start executing more GraphQL operations.
530+
- Calls and awaits all [`serverWillStop` plugin handlers](../integrations/plugins-event-reference/#serverwillstop) (including the [usage reporting plugin](./plugin/usage-reporting/)'s handler, which sends a final usage report to Apollo Studio).
531+
- If your server is a [federated gateway](https://www.apollographql.com/docs/federation/gateway/), `stop` also stops gateway-specific background activities, such as polling for updated service configuration.
523532

524-
In some circumstances, Apollo Server calls `stop` automatically when the process receives a `SIGINT` or `SIGTERM` signal. See the [`stopOnTerminationSignals` constructor option](#stoponterminationsignals) for details.
525-
526-
If you're using the `apollo-server` package (which handles setting up an HTTP server for you), this method first stops the HTTP server. Specifically, it:
527-
528-
* Stops listening for new connections
529-
* Closes idle connections (i.e., connections with no current HTTP request)
530-
* Closes active connections whenever they become idle
531-
* Waits for all connections to be closed
532-
533-
If any connections remain active after a grace period (10 seconds by default), Apollo Server forcefully closes those connections. You can configure this grace period with the [`stopGracePeriodMillis` constructor option](#stopgraceperiodmillis).
533+
This method takes no arguments. You should only call it after [`start()`](#start) returns successfully (or [`listen()`](#listen) if you're using the batteries-included `apollo-server` package).
534534

535-
If you're using a [middleware package](../integrations/middleware/) instead of `apollo-server`, you should stop your HTTP server before calling `ApolloServer.stop()`.
535+
In some circumstances, Apollo Server calls `stop` automatically when the process receives a `SIGINT` or `SIGTERM` signal. See the [`stopOnTerminationSignals` constructor option](#stoponterminationsignals) for details.
536536

537537
## Framework-specific middleware function
538538

@@ -547,23 +547,25 @@ These functions take an `options` object as a parameter. Some supported fields o
547547
```js
548548
const express = require('express');
549549
const { ApolloServer } = require('apollo-server-express');
550+
const { ApolloServerPluginDrainHttpServer } = require('apollo-server-core');
550551
const { typeDefs, resolvers } = require('./schema');
551552

552553
async function startApolloServer() {
554+
const app = express();
555+
const httpServer = http.createServer(app);
553556
const server = new ApolloServer({
554557
typeDefs,
555558
resolvers,
559+
plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
556560
});
557561
await server.start();
558562

559-
const app = express();
560-
561563
// Additional middleware can be mounted at this point to run before Apollo.
562564
app.use('*', jwtCheck, requireAuth, checkScope);
563565

564566
// Mount Apollo middleware here.
565567
server.applyMiddleware({ app, path: '/specialUrl' });
566-
await new Promise(resolve => app.listen({ port: 4000 }, resolve));
568+
await new Promise(resolve => httpServer.listen({ port: 4000 }, resolve));
567569
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
568570
return { server, app };
569571
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
---
2+
title: "API Reference: Drain HTTP server plugin"
3+
sidebar_title: Drain HTTP server
4+
api_reference: true
5+
---
6+
7+
## Using the plugin
8+
9+
This API reference documents the `ApolloServerPluginDrainHttpServer` plugin.
10+
11+
This plugin is designed for use with [`apollo-server-express` and other framework-specific packages](../../integrations/middleware/#all-supported-packages) which are built on top of [Node `http.Server`s](https://nodejs.org/api/http.html#http_class_http_server). It is highly recommended that you use this plugin with packages like `apollo-server-express` if you want your server to shut down gracefully.
12+
13+
You do not need to explicitly use this plugin with the batteries-included `apollo-server` package: that package automatically uses this plugin internally.
14+
15+
When you use this plugin, Apollo Server will drain your HTTP server when you call the `stop()` method (which is also called for you when the `SIGTERM` and `SIGINT` signals are received, unless disabled with the [`stopOnTerminationSignals` constructor option](./apollo-server/#stoponterminationsignals)). Specifically, it will:
16+
17+
* Stop listening for new connections
18+
* Close idle connections (i.e., connections with no current HTTP request)
19+
* Close active connections whenever they become idle
20+
* Wait for all connections to be closed
21+
* After a grace period, if any connections remain active, forcefully close them.
22+
23+
This plugin is exported from the `apollo-server-core` package. It is tested with `apollo-server-express`, `apollo-server-koa`, and `apollo-server-fastify`. (If you're using Hapi, you should instead use the `ApolloServerPluginStopHapiServer` plugin exported from the `apollo-server-hapi` package.)
24+
25+
```js
26+
const express = require('express');
27+
const { ApolloServer } = require('apollo-server-express');
28+
const { ApolloServerPluginDrainHttpServer } = require('apollo-server-core');
29+
const { typeDefs, resolvers } = require('./schema');
30+
31+
async function startApolloServer() {
32+
const app = express();
33+
const httpServer = http.createServer(app);
34+
const server = new ApolloServer({
35+
typeDefs,
36+
resolvers,
37+
plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
38+
});
39+
await server.start();
40+
41+
// Mount Apollo middleware here.
42+
server.applyMiddleware({ app });
43+
await new Promise(resolve => httpServer.listen({ port: 4000 }, resolve));
44+
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
45+
return { server, app };
46+
}
47+
```
48+
49+
## Options
50+
51+
<table class="field-table">
52+
<thead>
53+
<tr>
54+
<th>Name /<br/>Type</th>
55+
<th>Description</th>
56+
</tr>
57+
</thead>
58+
59+
<tbody>
60+
61+
<tr>
62+
<td>
63+
64+
###### `httpServer`
65+
66+
[`http.Server`](https://nodejs.org/api/http.html#http_class_http_server)
67+
</td>
68+
<td>
69+
70+
The server to drain; required.
71+
</td>
72+
</tr>
73+
74+
<tr>
75+
<td>
76+
77+
###### `stopGracePeriodMillis`
78+
79+
`number`
80+
</td>
81+
<td>
82+
83+
How long to wait before forcefully closing non-idle connections. Defaults to `10_000` (ten seconds).
84+
</td>
85+
</tr>
86+
87+
</tbody>
88+
</table>

docs/source/data/subscriptions.mdx

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -99,16 +99,26 @@ To run both an Express app _and_ a separate subscription server, we'll create an
9999
// This `server` is the instance returned from `new ApolloServer`.
100100
path: server.graphqlPath,
101101
});
102+
```
102103

103-
// Shut down in the case of interrupt and termination signals
104-
// We expect to handle this more cleanly in the future. See (#5074)[https://github.com/apollographql/apollo-server/issues/5074] for reference.
105-
['SIGINT', 'SIGTERM'].forEach(signal => {
106-
process.on(signal, () => subscriptionServer.close());
107-
});
104+
6. Add a plugin to your `ApolloServer` constructor to close the `SubscriptionServer`.
108105

106+
```javascript:title=index.js-10
107+
const server = new ApolloServer({
108+
schema,
109+
plugins: [{
110+
async serverWillStart() {
111+
return {
112+
async drainServer() {
113+
subscriptionServer.close();
114+
}
115+
};
116+
}
117+
}],
118+
});
109119
```
110120

111-
6. Finally, we need to adjust our existing `listen` call.
121+
7. Finally, we need to adjust our existing `listen` call.
112122

113123
Most Express applications call `app.listen(...)`. **Change this to `httpServer.listen(...)`** with the same arguments. This way, the server starts listening on the HTTP and WebSocket transports simultaneously.
114124

@@ -136,17 +146,26 @@ import typeDefs from "./typeDefs";
136146
resolvers,
137147
});
138148

149+
const subscriptionServer = SubscriptionServer.create(
150+
{ schema, execute, subscribe },
151+
{ server: httpServer, path: server.graphqlPath }
152+
);
153+
139154
const server = new ApolloServer({
140155
schema,
156+
plugins: [{
157+
async serverWillStart() {
158+
return {
159+
async drainServer() {
160+
subscriptionServer.close();
161+
}
162+
};
163+
}
164+
}],
141165
});
142166
await server.start();
143167
server.applyMiddleware({ app });
144168

145-
SubscriptionServer.create(
146-
{ schema, execute, subscribe },
147-
{ server: httpServer, path: server.graphqlPath }
148-
);
149-
150169
const PORT = 4000;
151170
httpServer.listen(PORT, () =>
152171
console.log(`Server is now running on http://localhost:${PORT}/graphql`)

0 commit comments

Comments
 (0)