Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

apollo-server-core: Update schema reporting plugin to support gateways #5187

Merged
merged 27 commits into from Jul 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4e10622
Add optional onSchemaLoadOrUpdate method to GraphQLService, to be use…
sachindshinde Jun 25, 2021
c89a9b9
Add schemaDidLoadOrUpdate hook TS typings
sachindshinde Jun 25, 2021
31a3380
Consolidate schema tracking logic (updates and notifications) into a …
sachindshinde Jun 25, 2021
3bc2da0
Update ApolloServerPluginSchemaReporting to use the new schemaDidLoad…
sachindshinde Jun 25, 2021
f0bdb18
Remove "invoking serverWillStart" state, as it's no longer used.
sachindshinde Jun 26, 2021
4c714ae
Disable test that checks for gateway schema update unsubscribe for se…
sachindshinde Jun 26, 2021
fe150cf
Use JS arrow function instead of JS bind()
sachindshinde Jul 7, 2021
530bb61
Change TODO about gateway version message update into FIXME, and fix …
sachindshinde Jul 7, 2021
f958c6b
Throw a specific error subclass when the gateway is too old in Schema…
sachindshinde Jul 7, 2021
64e1467
Accept overrideReportedSchema for schema reporting in gateways as the…
sachindshinde Jul 7, 2021
b7e4345
Change schemaDidLoadOrUpdate() hook to early return after executing o…
sachindshinde Jul 7, 2021
d3ca2af
Remove loadedSchema from server state, as it's no longer used
sachindshinde Jul 7, 2021
4921428
Update GatewayInterface.onSchemaChange to be optional, in preparation…
sachindshinde Jul 7, 2021
2e57079
Re-enable test on serverless that checks whether gateway unsubscribe …
sachindshinde Jul 7, 2021
8e4e86a
Throw when SchemaManager.onSchemaLoadOrUpdate() is called before Sche…
sachindshinde Jul 20, 2021
5c3a1f0
Add FIXME to update error message in SchemaManager.onSchemaLoadOrUpda…
sachindshinde Jul 20, 2021
1ff88b8
Keep stacktrace info when logging errors in SchemaManager.processSche…
sachindshinde Jul 20, 2021
0e3249b
Change SchemaManager.onSchemaLoadOrUpdate() to log and throw if a cal…
sachindshinde Jul 20, 2021
2535449
Update docs for plugins and migration
sachindshinde Jul 21, 2021
95deff6
Update CHANGELOG.md
sachindshinde Jul 21, 2021
0ac2944
Clarify docs for `schemaDidLoadOrUpdate` to note that not providing a…
sachindshinde Jul 22, 2021
bb8b6d2
Refactor some if/elses around the APOLLO_SCHEMA_REPORTING env var
sachindshinde Jul 22, 2021
4681a98
Add warning to ApolloServerBase.stop() to indicate that it may not be…
sachindshinde Jul 22, 2021
341af1f
Remove logging around callback errors in SchemaManager.onSchemaLoadOr…
sachindshinde Jul 22, 2021
a498b4a
Update CHANGELOG.md to state that schema reporting shouldn't be enabl…
sachindshinde Jul 22, 2021
f5241eb
CHANGELOG: tweak wording, move up to vNEXT
glasser Jul 22, 2021
19ce0f8
Update version numbers from FIXMEs
glasser Jul 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Expand Up @@ -10,7 +10,8 @@ The version headers in this history reflect the versions of Apollo Server itself
## vNEXT

- `apollo-server-core`: If a client does not provide a value or provides null for a variable declared to be non-null, this is now reported as an error with an `extensions.code` of `BAD_USER_INPUT` rather than `INTERNAL_SERVER_ERROR`. (This is similar to a change we made in v2.23.0 for variables that are sent as the wrong type.) [PR #5508](https://github.com/apollographql/apollo-server/pull/5508) [Issue #5353](https://github.com/apollographql/apollo-server/issues/5353)

- `apollo-server-core`/`apollo-server-plugin-base`: Add support for `schemaDidLoadOrUpdate` event hooks, to be specified by the `serverWillStart` event hook. Plugins listening for this event will receive the API schema (and core schema for gateways) when the server's schema is initially loaded and when the server's schema is updated. For more information about this plugin event, see [the plugin event reference documentation](https://www.apollographql.com/docs/apollo-server/integrations/plugins-event-reference/). [PR #5187](https://github.com/apollographql/apollo-server/pull/5187)
- `apollo-server-core`: Add support for schema reporting when using Apollo Gateway. At the time of this package's release, Apollo Studio does not yet support schema reporting from gateways, so you should not use this feature yet for gateways (unless instructed otherwise by Apollo staff or by the Studio docs). If you do enable schema reporting for a gateway, the version of `@apollo/gateway` must be at least `0.35.0` , or else `start()` will error. [PR #5187](https://github.com/apollographql/apollo-server/pull/5187)

## v3.0.2

Expand Down
35 changes: 32 additions & 3 deletions docs/source/integrations/plugins-event-reference.md
Expand Up @@ -3,7 +3,7 @@ title: Apollo Server plugin event reference
sidebar_title: Event reference
---

> **New in Apollo Server 3:** All plugin lifecycle methods are `async`, _except for [`willResolveField`](#willresolvefield)_.
> **New in Apollo Server 3:** All plugin lifecycle methods are `async`, _except for [`willResolveField`](#willresolvefield) and [`schemaDidLoadOrUpdate`](#schemadidloadorupdate)_.

This reference describes the lifecycle events that your [custom Apollo Server plugin](./plugins/) can respond to.

Expand All @@ -14,7 +14,7 @@ events** and **request lifecycle events**.
* Request lifecycle events are associated with the lifecycle of a specific request.
* You define responses to these events _within_ the response to a `requestDidStart` event, as described in [Responding to request lifecycle events](./plugins#responding-to-request-lifecycle-events).

> With one exception, all plugin methods in Apollo Server 3 are `async`. The exception is `willResolveField`, which is called much more frequently than other plugin methods.
> With two exceptions, all plugin methods in Apollo Server 3 are `async`. The first exception is `willResolveField`, which is called much more frequently than other plugin methods. The second exception is `schemaDidLoadOrUpdate`, where making the method `async` would introduce unclear ordering semantics around method executions.

## Server lifecycle events

Expand Down Expand Up @@ -171,6 +171,35 @@ const server = new ApolloServer({
If your plugin doesn't need to respond to any request lifecycle events, `requestDidStart`
should not return a value.

### `schemaDidLoadOrUpdate`

The `schemaDidLoadOrUpdate` event fires whenever Apollo Server initially loads the schema or updates the schema. A `schemaDidLoadOrUpdate` handler is given the new API schema and optionally the new core schema (if using a gateway). If you provide a gateway and it is older than `@apollo/gateway@0.35.0`, attempting to register a `schemaDidLoadOrUpdate` handler will fail.

`schemaDidLoadOrUpdate` is a synchronous plugin API (i.e., it does not return a `Promise`).

#### Example

```js
const server = new ApolloServer({
/* ... other necessary configuration ... */

plugins: [
{
async serverWillStart() {
return {
schemaDidLoadOrUpdate({ apiSchema, coreSupergraphSdl }) {
console.log(`The API schema is ${printSchema(apiSchema)}`);
if (coreSupergraphSdl) {
console.log(`The core schema is ${coreSupergraphSdl}`);
}
},
};
},
},
],
});
```

## Request lifecycle events

> If you're using TypeScript to create your plugin, implement the [ `GraphQLRequestListener` interface](https://github.com/apollographql/apollo-server/blob/main/packages/apollo-server-plugin-base/src/index.ts) from the `apollo-server-plugin-base` module to define functions for request lifecycle events.
Expand Down Expand Up @@ -294,7 +323,7 @@ You provide your `willResolveField` handler in the object returned by your [`exe

Your `willResolveField` handler can optionally return an ["end hook"](./plugins/#end-hooks) function that's invoked with the resolver's result (or the error that it throws). The end hook is called when your resolver has _fully_ resolved (e.g., if the resolver returns a Promise, the hook is called with the Promise's eventual resolved result).

`willResolveField` and its end hook are the only synchronous plugin APIs (ie, they do not return `Promise`s).
`willResolveField` and its end hook are synchronous plugin APIs (i.e., they do not return `Promise`s).

#### Example

Expand Down
6 changes: 3 additions & 3 deletions docs/source/integrations/plugins.md
Expand Up @@ -4,7 +4,7 @@ sidebar_title: Creating plugins
description: Extend Apollo Server with custom functionality
---

> **New in Apollo Server 3:** All plugin lifecycle methods are `async`, _except for [`willResolveField`](./plugins-event-reference/#willresolvefield)_.
> **New in Apollo Server 3:** All plugin lifecycle methods are `async`, _except for [`willResolveField`](./plugins-event-reference/#willresolvefield) and [`schemaDidLoadOrUpdate`](./plugins-event-reference/#schemadidloadorupdate)_.

You can create your own Apollo Server plugins to perform custom operations in response to certain events. For example, a basic logging plugin might log the GraphQL query string associated with each request that's sent to Apollo Server.

Expand Down Expand Up @@ -49,8 +49,8 @@ module.exports = (options) => {

## Responding to events

A plugin specifies exactly which events it responds to by implementing functions that correspond to those events. The plugin in the examples above responds to the `serverWillStart` event, which fires when Apollo Server is preparing to start up. Almost all plugin events are `async` functions (i.e., functions that return `Promise`s). The only exception
is [`willResolveField`](./plugins-event-reference/#willresolvefield).
A plugin specifies exactly which events it responds to by implementing functions that correspond to those events. The plugin in the examples above responds to the `serverWillStart` event, which fires when Apollo Server is preparing to start up. Almost all plugin events are `async` functions (i.e., functions that return `Promise`s). The only exceptions
are [`willResolveField`](./plugins-event-reference/#willresolvefield) and [`schemaDidLoadOrUpdate`](./plugins-event-reference/#schemadidloadorupdate).

A plugin can respond to any combination of [supported events](./plugins-event-reference/).

Expand Down
2 changes: 1 addition & 1 deletion docs/source/migration.mdx
Expand Up @@ -658,7 +658,7 @@ We don't expect this to affect many users and we have not publicly suggested usi

In Apollo Server 2, some [plugin events](./integrations/plugins-event-reference/) are synchronous (their return value is not a `Promise`), and some are "maybe-asynchronous" (they could return a `Promise` if they wanted, but didn't have to). This means that you can't do asynchronous work in the former events, and the typings for the latter events are somewhat complex.

In Apollo Server 3, _almost_ all plugin methods are always asynchronous: they always return a `Promise` type. This includes [end hooks](../integrations/plugins/#end-hooks) as well. The exception is `willResolveField` and its end hook, which are always synchronous.
In Apollo Server 3, _almost_ all plugin methods are always asynchronous: they always return a `Promise` type. This includes [end hooks](../integrations/plugins/#end-hooks) as well. The exceptions are `willResolveField` and its end hook and `schemaDidLoadOrUpdate`, which are always synchronous.

In practice, this means that all of your plugin events should use `async` functions or methods. If you are using TypeScript, you need to do this for your code to compile.

Expand Down