Skip to content

Commit

Permalink
apollo-server-core: Remove inconsistent @cacheControl auto-definiti…
Browse files Browse the repository at this point in the history
…on (#5182)

In Apollo Server 2, ApolloServer *sometimes* adds the definition of
`@cacheControl` to your schema.

Specifically, it adds it whenever you rely on the implicit call to
`graphql-tools`' `makeExecutableSchema` (ie, you pass `typeDefs` and
`resolvers`). It doesn't add it when you pass your own `schema`, and
oddly it doesn't add it when you use `modules`.

On the other hand, it doesn't care if you actually have cache control
enabled in your app.

What this means is that switching between the implicit call to the
built-in version of `makeExecutableSchema` and using your own copy of
`graphql-tools` has a surprising impact on your schema. We'd like to
make the implicit call just a shorthand and encourage folks who want to
use all of the different options of `makeExecutableSchema` to call it
directly in their app (rather than having tons of pass-through
arguments), so we don't want the semantics to differ in a surprising and
undocumented way.

Plus, other tools that look at your schema will work better if you
define the `@cacheControl` directive explicitly.

AS2 did allow you to define the directive yourself (it only adds it if
it isn't there).

So this PR changes `apollo-server-core` to no longer auto-include the
definitions, and documents how to write them yourself.

(In the future, we may want to change `@cacheControl` to be a Core
Schema feature, but we're not doing that today.)

(AS2 had a similar issue with the types related to `graphql-upload` but
that integration is removed.)

Fixes #5181.
  • Loading branch information
glasser authored May 6, 2021
1 parent 6cce70c commit 5a55a8b
Show file tree
Hide file tree
Showing 11 changed files with 68 additions and 91 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ The version headers in this history reflect the versions of Apollo Server itself
- Removed deprecated `ApolloServer.schema` field, which never worked with gateways. If you'd like to extract your schema from your server, make a plugin with `serverWillStart`, or register `onSchemaChange` on your gateway.
- `apollo-server-caching`: The test suite helper works differently, and the `TestableKeyValueCache` interface is removed.
- `apollo-datasource-rest`: We no longer officially support overriding the `baseURL` property with a getter, because TypeScript 4 does not allow you to do that.
- Previously, Apollo Server would automatically add the definition of the `@cacheControl` directive to your schema in some circumstances but not in others; this depended on how precisely you set up your schema, but not on whether you had disabled the cache control feature. In Apollo Server 3, Apollo Server is now consistent: it never automatically adds the directive definition to your schema. If you use `@cacheControl`, just [define it yourself as shown in the docs](https://www.apollographql.com/docs/apollo-server/performance/caching/#in-your-schema-static).
- Top-level exports have changed. E.g.,

- We no longer re-export the entirety of `graphql-tools` (including `makeExecutableSchema`) from all Apollo Server packages.
Expand Down
2 changes: 1 addition & 1 deletion docs/source/performance/apq.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ type Author @cacheControl(maxAge: 60) {
}
```
See [the cache control documentation](https://github.com/apollographql/apollo-server/tree/main/packages/apollo-cache-control#add-cache-hints-to-your-schema) for more details, including how to specify hints dynamically inside resolvers, how to set a default `maxAge` for all fields, and how to specify that a field should be cached for specific users only (in which case CDNs should ignore it). For example, to set a default max age other than `0` modify the Apollo Server constructor to include `cacheControl`:
See [the cache control documentation](./caching) for more details, including how to define the `@cacheControl` directive, how to specify hints dynamically inside resolvers, how to set a default `maxAge` for all fields, and how to specify that a field should be cached for specific users only (in which case CDNs should ignore it). For example, to set a default max age other than `0` modify the Apollo Server constructor to include `cacheControl`:
```js
const server = new ApolloServer({
Expand Down
16 changes: 15 additions & 1 deletion docs/source/performance/caching.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,21 @@ These details can vary significantly, even among the fields of a single object t

### In your schema (static)

Apollo Server defines the `@cacheControl` directive, which you can use in your schema to define caching behavior either for a [single field](#field-level-definitions), or for _all_ fields that return a particular [type](#type-level-definitions).
Apollo Server recognizes the `@cacheControl` directive, which you can use in your schema to define caching behavior either for a [single field](#field-level-definitions), or for _all_ fields that return a particular [type](#type-level-definitions).

In order to use the directive in your schema, you need to define it, as well as the enum that is used for one of its arguments; otherwise you will get an error like `Unknown directive "@cacheControl"`. (Older versions of Apollo Server used to automatically insert the definitions in some inconsistent situations; Apollo Server 3 consistently expects you to define them yourself.) Just include the following in your schema file:

```graphql
enum CacheControlScope {
PUBLIC
PRIVATE
}

directive @cacheControl(
maxAge: Int
scope: CacheControlScope
) on FIELD_DEFINITION | OBJECT | INTERFACE
```

The `@cacheControl` directive accepts the following arguments:

Expand Down
12 changes: 11 additions & 1 deletion packages/apollo-cache-control/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ app.use('/graphql', bodyParser.json(), graphqlExpress({
### Add cache hints to your schema

Cache hints can be added to your schema using directives on your types and fields. When executing your query, these hints will be used to compute an overall cache policy for the response. Hints on fields override hints specified on the target type.
Cache hints can be added to your schema using directives on your types and fields. When executing your query, these hints will be used to compute an overall cache policy for the response. Hints on fields override hints specified on the target type. With Apollo Server 3, you need to include the definition for the `@cacheControl` directive in your schema.

```graphql
type Post @cacheControl(maxAge: 240) {
Expand All @@ -41,6 +41,16 @@ type Post @cacheControl(maxAge: 240) {
votes: Int @cacheControl(maxAge: 30)
readByCurrentUser: Boolean! @cacheControl(scope: PRIVATE)
}

enum CacheControlScope {
PUBLIC
PRIVATE
}

directive @cacheControl(
maxAge: Int
scope: CacheControlScope
) on FIELD_DEFINITION | OBJECT | INTERFACE
```

If you need to add cache hints dynamically, you can use a programmatic API from within your resolvers.
Expand Down
22 changes: 0 additions & 22 deletions packages/apollo-server-core/src/ApolloServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,12 @@ import {
GraphQLService,
} from './types';

import { gql } from './index';

import {
createPlaygroundOptions,
PlaygroundRenderPageOptions,
} from './playground';

import { generateSchemaHash } from './utils/schemaHash';
import { isDirectiveDefined } from './utils/isDirectiveDefined';
import {
processGraphQLRequest,
GraphQLRequestContext,
Expand Down Expand Up @@ -629,25 +626,6 @@ export class ApolloServerBase {

const augmentedTypeDefs = Array.isArray(typeDefs) ? typeDefs : [typeDefs];

// We augment the typeDefs with the @cacheControl directive and associated
// scope enum, so makeExecutableSchema won't fail SDL validation

if (!isDirectiveDefined(augmentedTypeDefs, 'cacheControl')) {
augmentedTypeDefs.push(
gql`
enum CacheControlScope {
PUBLIC
PRIVATE
}
directive @cacheControl(
maxAge: Int
scope: CacheControlScope
) on FIELD_DEFINITION | OBJECT | INTERFACE
`,
);
}

return makeExecutableSchema({
typeDefs: augmentedTypeDefs,
schemaDirectives,
Expand Down

This file was deleted.

19 changes: 0 additions & 19 deletions packages/apollo-server-core/src/utils/isDirectiveDefined.ts

This file was deleted.

10 changes: 10 additions & 0 deletions packages/apollo-server-express/src/__tests__/ApolloServer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,16 @@ describe('apollo-server-express', () => {
cooks: [Cook]
pooks: [Pook]
}
enum CacheControlScope {
PUBLIC
PRIVATE
}
directive @cacheControl(
maxAge: Int
scope: CacheControlScope
) on FIELD_DEFINITION | OBJECT | INTERFACE
`;

const resolvers = {
Expand Down
10 changes: 10 additions & 0 deletions packages/apollo-server-fastify/src/__tests__/ApolloServer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,16 @@ describe('apollo-server-fastify', () => {
cooks: [Cook]
pooks: [Pook]
}
enum CacheControlScope {
PUBLIC
PRIVATE
}
directive @cacheControl(
maxAge: Int
scope: CacheControlScope
) on FIELD_DEFINITION | OBJECT | INTERFACE
`;

const resolvers = {
Expand Down
10 changes: 10 additions & 0 deletions packages/apollo-server-integration-testsuite/src/ApolloServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2231,6 +2231,16 @@ export function testApolloServer<AS extends ApolloServerBase>(
uncached: String
private: String @cacheControl(maxAge: 9, scope: PRIVATE)
}
enum CacheControlScope {
PUBLIC
PRIVATE
}
directive @cacheControl(
maxAge: Int
scope: CacheControlScope
) on FIELD_DEFINITION | OBJECT | INTERFACE
`;

type FieldName =
Expand Down
10 changes: 10 additions & 0 deletions packages/apollo-server-koa/src/__tests__/ApolloServer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,16 @@ describe('apollo-server-koa', () => {
cooks: [Cook]
pooks: [Pook]
}
enum CacheControlScope {
PUBLIC
PRIVATE
}
directive @cacheControl(
maxAge: Int
scope: CacheControlScope
) on FIELD_DEFINITION | OBJECT | INTERFACE
`;

const resolvers = {
Expand Down

0 comments on commit 5a55a8b

Please sign in to comment.