Skip to content

Commit 3184ce5

Browse files
committed
Simplify code.
1 parent 42c6f16 commit 3184ce5

2 files changed

Lines changed: 40 additions & 60 deletions

File tree

packages/cache/src/plugin.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { definePlugin } from '@zenstackhq/orm'
2-
import stableStringify from 'stable-hash'
2+
import { stableHash } from 'stable-hash'
33
import murmurhash from 'murmurhash'
44
import { cacheEnvelopeSchema } from './schemas'
55
import type {
@@ -58,7 +58,7 @@ export function defineCachePlugin(pluginOptions: CachePluginOptions) {
5858

5959
onQuery: async ({ args, model, operation, proceed }) => {
6060
if (args && 'cache' in args) {
61-
const json = stableStringify({
61+
const json = stableHash({
6262
args,
6363
model,
6464
operation,

packages/cache/src/providers/redis.ts

Lines changed: 38 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,61 +2,11 @@ import type { CacheInvalidationOptions, CacheProvider, CacheEntry } from '../typ
22
import { Redis } from 'ioredis'
33
import { getTotalTtl } from '../utils'
44

5-
interface ZenStackRedisCommands {
6-
invalidate: (options: string) => Promise<void>
7-
invalidateAll: () => Promise<void>
8-
}
9-
10-
declare module 'ioredis' {
11-
interface Redis extends ZenStackRedisCommands {}
12-
}
13-
145
export class RedisCacheProvider implements CacheProvider {
156
private readonly redis: Redis
167

178
constructor(options: RedisCacheProviderOptions) {
18-
this.redis = new Redis(options.url, {
19-
scripts: {
20-
invalidate: {
21-
numberOfKeys: 0,
22-
lua: `
23-
local options = cjson.decode(ARGV[1])
24-
local keysToDelete = {}
25-
26-
if (options.tags) then
27-
for _, tag in ipairs(options.tags) do
28-
local formattedTag = 'zenstack:tag:' .. tag
29-
local keys = redis.call('SMEMBERS', formattedTag)
30-
31-
for _, key in ipairs(keys) do
32-
keysToDelete[#keysToDelete + 1] = key
33-
end
34-
35-
redis.call('DEL', formattedTag)
36-
end
37-
end
38-
39-
if (#keysToDelete > 0) then
40-
redis.call('DEL', unpack(keysToDelete))
41-
end
42-
`,
43-
},
44-
45-
invalidateAll: {
46-
numberOfKeys: 0,
47-
lua: `
48-
local keys = redis.call('SMEMBERS', 'zenstack:key')
49-
50-
for i = 1, #keys do
51-
local key = keys[i]
52-
redis.call('DEL', key)
53-
end
54-
55-
redis.call('DEL', 'zenstack:key')
56-
`,
57-
},
58-
},
59-
})
9+
this.redis = new Redis(options.url)
6010
}
6111

6212
async get(key: string) {
@@ -74,7 +24,6 @@ export class RedisCacheProvider implements CacheProvider {
7424
const formattedKey = formatQueryKey(key)
7525

7626
multi.set(formattedKey, JSON.stringify(entry))
77-
multi.sadd('zenstack:key', formattedKey)
7827

7928
const totalTtl = getTotalTtl(entry)
8029

@@ -87,19 +36,50 @@ export class RedisCacheProvider implements CacheProvider {
8736
const formattedTagKey = formatTagKey(tag)
8837

8938
multi.sadd(formattedTagKey, formattedKey)
90-
multi.sadd('zenstack:key', formattedTagKey)
39+
40+
if (totalTtl > 0) {
41+
multi.expire(formattedTagKey, totalTtl, 'GT')
42+
multi.expire(formattedTagKey, totalTtl, 'NX')
43+
}
9144
}
9245
}
9346

9447
await multi.exec()
9548
}
9649

9750
async invalidate(options: CacheInvalidationOptions) {
98-
await this.redis.invalidate(JSON.stringify(options))
51+
if (options.tags && options.tags.length > 0) {
52+
await Promise.all(options.tags.map(tag => {
53+
return new Promise((resolve, reject) => {
54+
const stream = this.redis.sscanStream(formatTagKey(tag), {
55+
count: 100,
56+
})
57+
58+
stream.on('data', async (keys: string[]) => {
59+
await this.redis.del(...keys)
60+
})
61+
62+
stream.on('error', reject)
63+
stream.on('end', resolve)
64+
})
65+
}))
66+
}
9967
}
10068

10169
async invalidateAll() {
102-
await this.redis.invalidateAll()
70+
await new Promise((resolve, reject) => {
71+
const stream = this.redis.scanStream({
72+
count: 100,
73+
match: 'zenstack:cache:*',
74+
})
75+
76+
stream.on('data', async keys => {
77+
await this.redis.del(...keys)
78+
})
79+
80+
stream.on('error', reject)
81+
stream.on('end', resolve)
82+
})
10383
}
10484
}
10585

@@ -108,9 +88,9 @@ export type RedisCacheProviderOptions = {
10888
}
10989

11090
function formatQueryKey(key: string) {
111-
return `zenstack:query:${key}`
91+
return `zenstack:cache:query:${key}`
11292
}
11393

11494
function formatTagKey(key: string) {
115-
return `zenstack:tag:${key}`
116-
}
95+
return `zenstack:cache:tag:${key}`
96+
}

0 commit comments

Comments
 (0)