Skip to content

Commit

Permalink
bring back willStart
Browse files Browse the repository at this point in the history
  • Loading branch information
glasser committed Mar 22, 2021
1 parent b39fe89 commit 15426d9
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 5 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Expand Up @@ -11,7 +11,7 @@ The version headers in this history reflect the versions of Apollo Server itself

> The changes noted within this `vNEXT` section have not been released yet. New PRs and commits which introduce changes should include an entry in this `vNEXT` section as part of their development. With few exceptions, the format of the entry should follow convention (i.e., prefix with package name, use markdown `backtick formatting` for package names and code, suffix with a link to the change-set 脿 la `[PR #YYY](https://link/pull/YYY)`, etc.). When a release is being prepared, a new header will be (manually) created below and the appropriate changes within that release will be moved into the new section.
- Improve startup error handling by ensuring that your server has loaded its schema and executed its `serverWillStart` handlers successfully before starting an HTTP server. If you're using the `apollo-server` package, no code changes are necessary. If you're using an integration such as `apollo-server-express` that is not a "serverless framework", you can insert [`await server.start()`](https://www.apollographql.com/docs/apollo-server/api/apollo-server/#start) between `server = new ApolloServer()` and `server.applyMiddleware`. (If you don't call `server.start()` yourself, your server will still work, but the previous behavior of starting a web server that may fail to load its schema still applies.) The serverless framework integrations (Lambda, Azure Functions, and Cloud Functions) do not support this functionality. The protected method `willStart` has been removed; `start` or the new protected method `ensureStarting` should fulfill the same purpose if you were using it. [PR #4981](https://github.com/apollographql/apollo-server/pull/4981)
- Improve startup error handling by ensuring that your server has loaded its schema and executed its `serverWillStart` handlers successfully before starting an HTTP server. If you're using the `apollo-server` package, no code changes are necessary. If you're using an integration such as `apollo-server-express` that is not a "serverless framework", you can insert [`await server.start()`](https://www.apollographql.com/docs/apollo-server/api/apollo-server/#start) between `server = new ApolloServer()` and `server.applyMiddleware`. (If you don't call `server.start()` yourself, your server will still work, but the previous behavior of starting a web server that may fail to load its schema still applies.) The serverless framework integrations (Lambda, Azure Functions, and Cloud Functions) do not support this functionality. While the protected method `willStart` still exists for backwards compatibility, you should replace calls to it with `start` or the new protected method `ensureStarting`. [PR #4981](https://github.com/apollographql/apollo-server/pull/4981)

## v2.21.2

Expand Down
37 changes: 33 additions & 4 deletions packages/apollo-server-core/src/ApolloServer.ts
Expand Up @@ -129,7 +129,7 @@ type ServerState =
barrier: Resolvable<void>;
schemaDerivedData: SchemaDerivedData;
}
| { phase: 'failed to start'; error: Error }
| { phase: 'failed to start'; error: Error; loadedSchema: boolean }
| {
phase: 'started';
schemaDerivedData: SchemaDerivedData;
Expand Down Expand Up @@ -499,6 +499,8 @@ export class ApolloServerBase {
return await this._start();
}

// This is protected so that it can be called from `apollo-server`. It is
// otherwise an internal implementation detail.
protected async _start(): Promise<void> {
const initialState = this.state;
if (
Expand All @@ -511,14 +513,15 @@ export class ApolloServerBase {
}
const barrier = resolvable();
this.state = { phase: 'starting', barrier };
let loadedSchema = false;
try {
const schemaDerivedData =
initialState.phase === 'initialized with schema'
? initialState.schemaDerivedData
: this.generateSchemaDerivedData(
await this.startGatewayAndLoadSchema(initialState.gateway),
);

loadedSchema = true;
this.state = {
phase: 'invoking serverWillStart',
barrier,
Expand Down Expand Up @@ -571,13 +574,39 @@ export class ApolloServerBase {

this.state = { phase: 'started', schemaDerivedData };
} catch (error) {
this.state = { phase: 'failed to start', error };
this.state = { phase: 'failed to start', error, loadedSchema };
throw error;
} finally {
barrier.resolve();
}
}

/**
* @deprecated This deprecated method is provided for backwards compatibility
* with the pre-v2.22 API. It could be used for purposes similar to `start` or
* `ensureStarting`, and was used by integrations. It had odd error handling
* semantics, in that it would ignore any error that came from loading the
* schema, but would throw errors that came from `serverWillStart`. Anyone
* calling it should call `start` or `ensureStarting` instead.
*/
protected async willStart() {
try {
this._start();
} catch (e) {
if (
this.state.phase === 'failed to start' &&
this.state.error === e &&
!this.state.loadedSchema
) {
// For backwards compatibility with the odd semantics of the old
// willStart method, don't throw if the error occurred in loading the
// schema.
return;
}
throw e;
}
}

// Part of the backwards-compatibility behavior described above `start` to
// make ApolloServer work if you don't explicitly call `start`, as well as for
// serverless frameworks where there is no `start`. This is called at the
Expand All @@ -594,7 +623,7 @@ export class ApolloServerBase {
switch (this.state.phase) {
case 'initialized with gateway':
case 'initialized with schema':
await this.start();
await this._start();
// continue the while loop
break;
case 'starting':
Expand Down

0 comments on commit 15426d9

Please sign in to comment.