Skip to content

Commit

Permalink
add docs
Browse files Browse the repository at this point in the history
  • Loading branch information
n1ru4l committed Jul 28, 2022
1 parent 6478015 commit cd6403c
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 0 deletions.
3 changes: 3 additions & 0 deletions packages/plugins/response-cache/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# @graphql-yoga/plugin-response-cache

For the documentation check `http://graphql-yoga.com/docs/response-cache`
1 change: 1 addition & 0 deletions website/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export function getDocsV3Routes(): IRoutes {
['testing', 'Testing'],
['persisted-operations', 'Persisted Operations'],
['automatic-persisted-queries', 'Automatic Persisted Queries'],
['response-caching', 'Response Caching'],
],
},
integrations: {
Expand Down
201 changes: 201 additions & 0 deletions website/v3/docs/features/response-caching.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
---
id: response-caching
title: Response Caching
sidebar_label: Resposne Caching
---

Response caching is a technique for reducing server load by caching GraphQL query operation results.

## Installation

<PackageInstall packages={['@graphql-yoga/plugin-response-cache']} />

## Quick Start

```ts
import { createYoga } from 'graphql-yoga'
import { createServer } from 'node:http'
import { useResponseCache } from '@graphql-yoga/plugin-response-cache'

const yoga = createYoga({
schema: {
typeDefs: `type Query { slow: String}`,
resolvers: {
Query: {
slow: async () => {
await new Promise((resolve) => setTimeout(resolve, 5000))
return 'I am slow.'
},
},
},
},
plugins: [
useResponseCache({
// global cache
session: () => null,
}),
],
})

const server = createServer(yoga)
server.listen(4000)
```

```
curl -X POST -H 'Content-Type: application/json' http://localhost:4000/graphql \
-d '{"query":"{__typename}"}' -w '\nTotal time : %{time_total}'
```

This will output something like the following:

```
{"data":{"slow":"I am slow."}}
Total time:5.026632
```

After executing the same curl statement a second time, the duration is significantly lower.

```
{"data":{"slow":"I am slow."}}
Total time:0.007571%
```

## Session based caching

If your GraphQL API returns specific data depending on the viewer's session, you can use the `session` option to cache the response per session.

```ts
useResponseCache({
// cache based on the authentication header
session: (request) => request.headers.get('authentication'),
})
```

## TTL

It is possible to give cached operations a time to live. Either globally, based on [schema coordinates](https://github.com/graphql/graphql-wg/blob/main/rfcs/SchemaCoordinates.md) or object types.
If a query operation result contains multiple objects of the same type, the lowest TTL is picked.

```ts
useResponseCache({
session: () => null,
// by default cache all operations for 2 seconds
ttl: 2_000,
ttlPerType: {
// only cache query operations containing User for 500ms
User: 500,
},
ttlPerSchemaCoordinate: {
// cache operations selecting Query.lazy for 10 seconds
'Query.lazy': 10_000,
},
})
```

## Invalidatios via Mutation

When executing a mutation operation the cached query results that contain type entities within the Mutation result will be automatically be invalidated.

```graphql
mutation {
updateUser(id: 1, newName: "John") {
__typename
id
name
}
}
```

```json
{
"data": {
"updateLaunch": {
"__typename": "User",
"id": "1",
"name": "John"
}
}
}
```

All cached query results that contain the type `User` with the id `1` will be invalidated.

This behavior can be disabled by setting the `invalidateViaMutation` option to `false`.

```ts
useResponseCache({
session: (request) => null,
invalidateViaMutation: false,
})
```

## Manual Invalidation

You can invalidate a type or specific instances of a type using the cache invalidation API.

In order to use the API, you need to manually instantiate the cache an pass it to the `useResponseCache` plugin.

```ts
import {
useResponseCache,
createInMemoryCache,
} from '@graphql-yoga/plugin-response-cache'

const cache = createInMemoryCache()

useResponseCache({
session: () => null,
cache,
})
```

Then in your business logic you can call the `invalidate` method on the cache instance.

Invalidate all GraphQL query results that referance a specific type:

```ts
cache.invalidate([{ type: 'User' }])
```

Invalidate all GraphQL query results that reference a specific entity of a type:

```ts
cache.invalidate([{ type: 'User', id: '1' }])
```

Invalidate all GraphQL query results multiple entities in a single call.

```ts
cache.invalidate([
{ type: 'Post', id: '1' },
{ type: 'User', id: '2' },
])
```

## External Cache

By default the response cache stores all the cached query results in memory.

If you want a cache that is shared between multiple server instances you can use the Redis cache implementation.

<PackageInstall packages={['@envelop/response-cache-redis']} />

```ts
import { useResponseCache } from '@graphql-yoga/plugin-response-cache'
import Redis from 'ioredis'

const redis = new Redis({
host: 'my-redis-db.example.com',
port: '30652',
password: '1234567890',
})

const redis = new Redis('rediss://:1234567890@my-redis-db.example.com:30652')

const cache = createRedisCache({ redis })

useResponseCache({
session: () => null,
cache,
})
```

0 comments on commit cd6403c

Please sign in to comment.