mercurius-cache
Advanced tools
Comparing version 0.9.0 to 0.10.0
@@ -6,3 +6,3 @@ 'use strict' | ||
module.exports = fp(async function (app, { all, policy, ttl, cacheSize, skip, storage, onHit, onMiss, onSkip }) { | ||
module.exports = fp(async function (app, { all, policy, ttl, cacheSize, skip, storage, onHit, onMiss, onSkip, ...other }) { | ||
if (typeof policy !== 'object' && !all) { | ||
@@ -9,0 +9,0 @@ throw new Error('policy must be an object') |
{ | ||
"name": "mercurius-cache", | ||
"version": "0.9.0", | ||
"version": "0.10.0", | ||
"description": "Cache the results of your GraphQL resolvers, for Mercurius", | ||
@@ -27,2 +27,4 @@ "main": "index.js", | ||
"@sinonjs/fake-timers": "^8.0.0", | ||
"autocannon": "^7.5.0", | ||
"concurrently": "^6.3.0", | ||
"fastify": "^3.21.3", | ||
@@ -32,6 +34,7 @@ "mercurius": "^8.2.1", | ||
"standard": "^16.0.3", | ||
"tap": "^15.0.9" | ||
"tap": "^15.0.9", | ||
"wait-on": "^6.0.0" | ||
}, | ||
"dependencies": { | ||
"async-cache-dedupe": "^0.4.0", | ||
"async-cache-dedupe": "^0.5.0", | ||
"fastify-plugin": "^3.0.0" | ||
@@ -38,0 +41,0 @@ }, |
102
README.md
@@ -240,4 +240,106 @@ # mercurius-cache | ||
## Benchmarks | ||
We have experienced up to 10x performance improvements in real-world scenarios. | ||
This repository also include a benchmark of a gateway and two federated services that shows | ||
that adding a cache with 10ms TTL can improve the performance by 4x: | ||
``` | ||
$ sh bench.sh | ||
=============================== | ||
= Gateway Mode (not cache) = | ||
=============================== | ||
Running 10s test @ http://localhost:3000/graphql | ||
100 connections | ||
┌─────────┬───────┬───────┬───────┬───────┬──────────┬─────────┬────────┐ | ||
│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │ | ||
├─────────┼───────┼───────┼───────┼───────┼──────────┼─────────┼────────┤ | ||
│ Latency │ 28 ms │ 31 ms │ 57 ms │ 86 ms │ 33.47 ms │ 12.2 ms │ 238 ms │ | ||
└─────────┴───────┴───────┴───────┴───────┴──────────┴─────────┴────────┘ | ||
┌───────────┬────────┬────────┬─────────┬─────────┬─────────┬────────┬────────┐ | ||
│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │ | ||
├───────────┼────────┼────────┼─────────┼─────────┼─────────┼────────┼────────┤ | ||
│ Req/Sec │ 1291 │ 1291 │ 3201 │ 3347 │ 2942.1 │ 559.51 │ 1291 │ | ||
├───────────┼────────┼────────┼─────────┼─────────┼─────────┼────────┼────────┤ | ||
│ Bytes/Sec │ 452 kB │ 452 kB │ 1.12 MB │ 1.17 MB │ 1.03 MB │ 196 kB │ 452 kB │ | ||
└───────────┴────────┴────────┴─────────┴─────────┴─────────┴────────┴────────┘ | ||
Req/Bytes counts sampled once per second. | ||
32k requests in 11.03s, 11.3 MB read | ||
=============================== | ||
= Gateway Mode (0s TTL) = | ||
=============================== | ||
Running 10s test @ http://localhost:3000/graphql | ||
100 connections | ||
┌─────────┬──────┬──────┬───────┬───────┬─────────┬─────────┬────────┐ | ||
│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │ | ||
├─────────┼──────┼──────┼───────┼───────┼─────────┼─────────┼────────┤ | ||
│ Latency │ 6 ms │ 7 ms │ 12 ms │ 17 ms │ 7.29 ms │ 3.32 ms │ 125 ms │ | ||
└─────────┴──────┴──────┴───────┴───────┴─────────┴─────────┴────────┘ | ||
┌───────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐ | ||
│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │ | ||
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤ | ||
│ Req/Sec │ 7403 │ 7403 │ 13359 │ 13751 │ 12759 │ 1831.94 │ 7400 │ | ||
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤ | ||
│ Bytes/Sec │ 2.59 MB │ 2.59 MB │ 4.68 MB │ 4.81 MB │ 4.47 MB │ 642 kB │ 2.59 MB │ | ||
└───────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘ | ||
Req/Bytes counts sampled once per second. | ||
128k requests in 10.03s, 44.7 MB read | ||
=============================== | ||
= Gateway Mode (1s TTL) = | ||
=============================== | ||
Running 10s test @ http://localhost:3000/graphql | ||
100 connections | ||
┌─────────┬──────┬──────┬───────┬───────┬─────────┬─────────┬────────┐ | ||
│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │ | ||
├─────────┼──────┼──────┼───────┼───────┼─────────┼─────────┼────────┤ | ||
│ Latency │ 7 ms │ 7 ms │ 13 ms │ 19 ms │ 7.68 ms │ 4.01 ms │ 149 ms │ | ||
└─────────┴──────┴──────┴───────┴───────┴─────────┴─────────┴────────┘ | ||
┌───────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┬─────────┐ | ||
│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │ | ||
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤ | ||
│ Req/Sec │ 6735 │ 6735 │ 12879 │ 12951 │ 12173 │ 1828.86 │ 6735 │ | ||
├───────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤ | ||
│ Bytes/Sec │ 2.36 MB │ 2.36 MB │ 4.51 MB │ 4.53 MB │ 4.26 MB │ 640 kB │ 2.36 MB │ | ||
└───────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┴─────────┘ | ||
Req/Bytes counts sampled once per second. | ||
122k requests in 10.03s, 42.6 MB read | ||
=============================== | ||
= Gateway Mode (10s TTL) = | ||
=============================== | ||
Running 10s test @ http://localhost:3000/graphql | ||
100 connections | ||
┌─────────┬──────┬──────┬───────┬───────┬─────────┬─────────┬────────┐ | ||
│ Stat │ 2.5% │ 50% │ 97.5% │ 99% │ Avg │ Stdev │ Max │ | ||
├─────────┼──────┼──────┼───────┼───────┼─────────┼─────────┼────────┤ | ||
│ Latency │ 7 ms │ 7 ms │ 13 ms │ 18 ms │ 7.51 ms │ 3.22 ms │ 121 ms │ | ||
└─────────┴──────┴──────┴───────┴───────┴─────────┴─────────┴────────┘ | ||
┌───────────┬────────┬────────┬─────────┬─────────┬─────────┬─────────┬────────┐ | ||
│ Stat │ 1% │ 2.5% │ 50% │ 97.5% │ Avg │ Stdev │ Min │ | ||
├───────────┼────────┼────────┼─────────┼─────────┼─────────┼─────────┼────────┤ | ||
│ Req/Sec │ 7147 │ 7147 │ 13231 │ 13303 │ 12498.2 │ 1807.01 │ 7144 │ | ||
├───────────┼────────┼────────┼─────────┼─────────┼─────────┼─────────┼────────┤ | ||
│ Bytes/Sec │ 2.5 MB │ 2.5 MB │ 4.63 MB │ 4.66 MB │ 4.37 MB │ 633 kB │ 2.5 MB │ | ||
└───────────┴────────┴────────┴─────────┴─────────┴─────────┴─────────┴────────┘ | ||
Req/Bytes counts sampled once per second. | ||
125k requests in 10.03s, 43.7 MB read | ||
``` | ||
## License | ||
MIT |
@@ -8,4 +8,6 @@ 'use strict' | ||
const FakeTimers = require('@sinonjs/fake-timers') | ||
const { promisify } = require('util') | ||
const immediate = promisify(setImmediate) | ||
test('cache a resolver', async ({ equal, same, pass, plan, teardown }) => { | ||
@@ -42,2 +44,3 @@ plan(11) | ||
app.register(cache, { | ||
ttl: 4242, | ||
onHit (type, name) { | ||
@@ -100,2 +103,79 @@ equal(type, 'Query') | ||
test('No TTL', async ({ equal, same, pass, plan, teardown }) => { | ||
plan(13) | ||
const app = fastify() | ||
teardown(app.close.bind(app)) | ||
const schema = ` | ||
type Query { | ||
add(x: Int, y: Int): Int | ||
hello: String | ||
} | ||
` | ||
const resolvers = { | ||
Query: { | ||
async add (_, { x, y }) { | ||
pass('add called only once') | ||
await immediate() | ||
return x + y | ||
} | ||
} | ||
} | ||
app.register(mercurius, { | ||
schema, | ||
resolvers | ||
}) | ||
let hits = 0 | ||
let misses = 0 | ||
app.register(cache, { | ||
onHit (type, name) { | ||
equal(type, 'Query', 'on hit') | ||
equal(name, 'add') | ||
hits++ | ||
}, | ||
onMiss (type, name) { | ||
equal(type, 'Query', 'on miss') | ||
equal(name, 'add') | ||
misses++ | ||
}, | ||
policy: { | ||
Query: { | ||
add: true | ||
} | ||
} | ||
}) | ||
await Promise.all([ | ||
query(), | ||
query() | ||
]) | ||
equal(hits, 1) | ||
equal(misses, 2) | ||
async function query () { | ||
const query = '{ add(x: 2, y: 2) }' | ||
const res = await app.inject({ | ||
method: 'POST', | ||
url: '/graphql', | ||
body: { | ||
query | ||
} | ||
}) | ||
equal(res.statusCode, 200) | ||
same(res.json(), { | ||
data: { | ||
add: 4 | ||
} | ||
}) | ||
} | ||
}) | ||
test('cache a nested resolver with loaders', async ({ same, pass, plan, teardown }) => { | ||
@@ -488,95 +568,2 @@ pass(4) | ||
test('external cache', async ({ equal, same, pass, plan, teardown }) => { | ||
plan(8) | ||
const clock = FakeTimers.install({ | ||
shouldAdvanceTime: true, | ||
advanceTimeDelta: 40 | ||
}) | ||
teardown(() => clock.uninstall()) | ||
const app = fastify() | ||
teardown(app.close.bind(app)) | ||
const schema = ` | ||
type Query { | ||
add(x: Int, y: Int): Int | ||
hello: String | ||
} | ||
` | ||
const resolvers = { | ||
Query: { | ||
async add (_, { x, y }) { | ||
pass('add called once') | ||
return x + y | ||
} | ||
} | ||
} | ||
app.register(mercurius, { | ||
schema, | ||
resolvers | ||
}) | ||
const map = new Map() | ||
app.register(cache, { | ||
ttl: 1, | ||
storage: { | ||
async get (key) { | ||
pass('get called with ' + key) | ||
return map.get(key) | ||
}, | ||
async set (key, value) { | ||
pass('set called') | ||
map.set(key, value) | ||
} | ||
}, | ||
policy: { | ||
Query: { | ||
add: true | ||
} | ||
} | ||
}) | ||
const query = '{ add(x: 2, y: 2) }' | ||
{ | ||
const res = await app.inject({ | ||
method: 'POST', | ||
url: '/graphql', | ||
body: { | ||
query | ||
} | ||
}) | ||
equal(res.statusCode, 200) | ||
same(res.json(), { | ||
data: { | ||
add: 4 | ||
} | ||
}) | ||
} | ||
await clock.tickAsync(2000) | ||
{ | ||
const res = await app.inject({ | ||
method: 'POST', | ||
url: '/graphql', | ||
body: { | ||
query | ||
} | ||
}) | ||
equal(res.statusCode, 200) | ||
same(res.json(), { | ||
data: { | ||
add: 4 | ||
} | ||
}) | ||
} | ||
}) | ||
test('using both policy and all options', async (t) => { | ||
@@ -583,0 +570,0 @@ const app = fastify() |
@@ -7,3 +7,2 @@ 'use strict' | ||
const mercuriusCache = require('..') | ||
async function createTestService (t, schema, resolvers = {}) { | ||
@@ -161,2 +160,3 @@ const service = Fastify({ logger: { level: 'error' } }) | ||
const app = await createTestGatewayServer(t, { | ||
ttl: 4242, | ||
// cache it all | ||
@@ -288,2 +288,3 @@ policy: { | ||
const app = await createTestGatewayServer(t, { | ||
ttl: 4242, | ||
// cache it all | ||
@@ -290,0 +291,0 @@ policy: { |
@@ -76,2 +76,3 @@ 'use strict' | ||
await gateway.register(mercuriusCache, { | ||
ttl: 4242, | ||
policy: { | ||
@@ -208,2 +209,3 @@ Query: { | ||
userService.register(mercuriusCache, { | ||
ttl: 4242, | ||
policy: { | ||
@@ -210,0 +212,0 @@ Query: { |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
66398
24
2198
345
10
+ Addedasync-cache-dedupe@0.5.0(transitive)
+ Addedsafe-stable-stringify@2.5.0(transitive)
- Removedasync-cache-dedupe@0.4.0(transitive)
- Removedsafe-stable-stringify@1.1.1(transitive)
Updatedasync-cache-dedupe@^0.5.0