-
Notifications
You must be signed in to change notification settings - Fork 19
/
invalidation.js
125 lines (107 loc) · 2.94 KB
/
invalidation.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
'use strict'
const fastify = require('fastify')
const mercurius = require('mercurius')
const redis = require('fastify-redis')
const fp = require('fastify-plugin')
const cache = require('mercurius-cache')
async function main () {
const app = fastify({ logger: true })
const schema = `
type Country {
name: String
}
type User {
id: ID!
name: String!
}
type Query {
user(id: ID!): User
countries: [Country]
}
input UserInput {
name: String!
}
type Mutation {
updateUser (id: ID!, user: UserInput!): User!
}
`
const resolvers = {
Query: {
user (_, { id }, { app }) {
app.log.info(`requesting user with an id ${id}`)
return { id, name: `User ${id}` }
},
countries (_, __, { app }) {
app.log.info('requesting countries')
return [{ name: 'Ireland' }, { name: 'Italy' }]
}
},
Mutation: {
updateUser (_, { id, user }, { app }) {
app.log.info(`updating a user with an id ${id}`)
return { id, name: user.name }
}
}
}
app.register(mercurius, {
schema,
resolvers
})
app.register(redis)
app.register(fp(async app => {
app.register(cache, {
ttl: 10,
// default storage is redis
storage: {
type: 'redis',
options: { client: app.redis, invalidation: true }
},
onHit (type, fieldName) {
console.log(`hit ${type} ${fieldName}`)
},
onMiss (type, fieldName) {
console.log(`miss ${type} ${fieldName}`)
},
policy: {
Query: {
user: {
// references: the user by id
references: (_request, _key, result) => {
if (!result) {
return
}
return [`user:${result.id}`]
}
},
// since countries rarely change, we can cache them for a very long time
// and since their size is small, it's convenient to cache them in memory
countries: {
ttl: 86400, // 1 day
// don't really need invalidation, just as example
storage: { type: 'memory', options: { invalidation: true } },
references: () => ['countries']
}
},
Mutation: {
updateUser: {
// invalidate the user
invalidate: (self, arg, _ctx, _info, _result) => [`user:${arg.id}`]
}
}
}
}, { dependencies: ['fastify-redis'] })
}))
await app.listen(3000)
// manual invalidation
// wildcard
app.graphql.cache.invalidate('user:*')
// with a reference
app.graphql.cache.invalidate('user:1')
// with an array of references
app.graphql.cache.invalidate(['user:1', 'user:2'])
// using a specific storage
// note "countries" uses a different storage from the default one
// so need to specify it, otherwise it will invalidate on the default storage
app.graphql.cache.invalidate('countries', 'Query.countries')
}
main()