Skip to content

Commit 4302bb1

Browse files
committed
add ioredis store, use scan instead of keys
1 parent 8b7e2cf commit 4302bb1

File tree

5 files changed

+144
-5
lines changed

5 files changed

+144
-5
lines changed

package-lock.json

Lines changed: 83 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/utils/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"@types/debug": "^4.1.12",
1818
"@types/mocha": "^10.0.6",
1919
"@types/node": "^20.11.5",
20+
"ioredis": "^5.4.1",
2021
"mocha": "^10.4.0",
2122
"should": "^13.2.3",
2223
"ts-node": "^10.9.2"
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
2+
import type {Redis as IoRedis} from "ioredis"
3+
import type {KvStore} from './Types'
4+
import type {Upload} from '../models'
5+
6+
export class IoRedisKvStore<T = Upload> implements KvStore<T> {
7+
constructor(
8+
private redis: IoRedis,
9+
private prefix = ''
10+
) {
11+
this.redis = redis
12+
this.prefix = prefix
13+
}
14+
15+
private prefixed(key: string): string {
16+
return `${this.prefix}${key}`
17+
}
18+
19+
async get(key: string): Promise<T | undefined> {
20+
return this.deserializeValue(await this.redis.get(this.prefixed(key)))
21+
}
22+
23+
async set(key: string, value: T): Promise<void> {
24+
await this.redis.set(this.prefixed(key), this.serializeValue(value))
25+
}
26+
27+
async delete(key: string): Promise<void> {
28+
await this.redis.del(this.prefixed(key))
29+
}
30+
31+
async list(): Promise<Array<string>> {
32+
const keys = new Set<string>()
33+
let cursor = "0"
34+
do {
35+
const [next, batch] = await this.redis.scan(cursor, "MATCH", this.prefixed("*"), "COUNT", "20")
36+
cursor = next
37+
for (const key of batch) keys.add(key)
38+
} while (cursor !== "0")
39+
return Array.from(keys)
40+
}
41+
42+
private serializeValue(value: T): string {
43+
return JSON.stringify(value)
44+
}
45+
46+
private deserializeValue(buffer: string | null): T | undefined {
47+
return buffer ? JSON.parse(buffer) : undefined
48+
}
49+
}
50+
51+

packages/utils/src/kvstores/RedisKvStore.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,14 @@ export class RedisKvStore<T = Upload> implements KvStore<T> {
2929
}
3030

3131
async list(): Promise<Array<string>> {
32-
return this.redis.keys(`${this.prefix}*`)
32+
const keys = new Set<string>()
33+
let cursor = 0
34+
do {
35+
const result = await this.redis.scan(cursor, { MATCH: `${this.prefix}*`, COUNT: 20 })
36+
cursor = result.cursor
37+
for (const key of result.keys) keys.add(key)
38+
} while (cursor !== 0)
39+
return Array.from(keys)
3340
}
3441

3542
private serializeValue(value: T): string {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export {FileKvStore} from './FileKvStore'
22
export {MemoryKvStore} from './MemoryKvStore'
33
export {RedisKvStore} from './RedisKvStore'
4+
export {IoRedisKvStore} from './IoRedisKvStore'
45
export {KvStore} from './Types'

0 commit comments

Comments
 (0)