Skip to content

Commit 41308f1

Browse files
committed
feat: upgrade cache-manager to v6
1 parent e7bed58 commit 41308f1

File tree

10 files changed

+4434
-5078
lines changed

10 files changed

+4434
-5078
lines changed

packages/reku/src/event/crosschecker/cache/manager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export class CrossCheckerCacheManager extends SimpleStoreManager {
8989
await this.set(`${this.storeKeyPrefix}checkpoint`, checkpoint, this.ttl)
9090
}
9191

92-
async getCheckpoint(): Promise<number | undefined> {
92+
async getCheckpoint(): Promise<number | undefined | null> {
9393
return await this.get(`${this.storeKeyPrefix}checkpoint`)
9494
}
9595
}

packages/utils/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,14 @@
4343
"ethers": ">=6.13.0"
4444
},
4545
"dependencies": {
46+
"@keyv/redis": "^4.2.0",
4647
"@murongg/utils": "^0.1.28",
47-
"cache-manager": "^5.7.6",
48+
"cache-manager": "^6.3.2",
4849
"cache-manager-ioredis-yet": "^2.1.1",
50+
"cacheable": "^1.8.7",
4951
"debug": "^4.3.7",
5052
"ioredis": "^5.4.1",
53+
"keyv": "^5.2.3",
5154
"lodash.clonedeep": "^4.5.0",
5255
"lru-cache": "^11.0.1",
5356
"picocolors": "^1.0.1",

packages/utils/src/store/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
export type { Store, StoreConfig, Stores } from 'cache-manager'
1+
export type { CacheManagerStore } from 'cache-manager'
2+
export type { Store } from './types'
23
export { redisStore } from './redis'
34
export * from './manager'
45
export { memoryStore } from './memory'
5-
export type { MemoryStore, MemoryCache, MemoryConfig } from './memory'
6+
export type { MemoryConfig } from './memory'

packages/utils/src/store/manager.ts

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,42 @@
1-
import type { Cache, Milliseconds, Store } from 'cache-manager'
2-
import { createCache, memoryStore } from 'cache-manager'
1+
import type { Cache, CreateCacheOptions } from 'cache-manager'
2+
import { createCache } from 'cache-manager'
33
import type { RedisStore } from 'cache-manager-ioredis-yet'
4+
import { Keyv } from 'keyv'
5+
import { KeyvCacheableMemory } from 'cacheable'
46

57
export class SimpleStoreManager {
68
private cache: Cache
9+
private store: Keyv
710

811
constructor(
9-
store?: Store,
12+
options?: (Omit<CreateCacheOptions, 'stores'>) & { store: Keyv },
1013
) {
11-
if (store) {
12-
this.cache = createCache(store)
14+
if (options) {
15+
this.cache = createCache({
16+
...options,
17+
stores: [
18+
options.store,
19+
],
20+
})
21+
this.store = options.store
1322
}
1423
else {
15-
this.cache = createCache(memoryStore({
16-
max: 100,
17-
ttl: 10 * 1000 /* milliseconds */,
18-
}))
24+
const store = new KeyvCacheableMemory({ ttl: 10 * 1000, lruSize: 100 })
25+
const keyv = new Keyv({ store })
26+
this.store = keyv
27+
this.cache = createCache({ stores: [keyv] })
1928
}
2029
}
2130

2231
get redisStore(): RedisStore {
23-
return <RedisStore> this.cache.store
32+
return <RedisStore> this.store.store
2433
}
2534

2635
async get<T>(key: string) {
2736
return await this.cache.get<T>(key)
2837
}
2938

30-
async set(key: string, value: unknown, ttl?: Milliseconds) {
39+
async set(key: string, value: unknown, ttl?: number) {
3140
await this.cache.set(key, value, ttl)
3241
}
3342

@@ -36,16 +45,28 @@ export class SimpleStoreManager {
3645
}
3746

3847
async keys(pattern?: string): Promise<string[]> {
39-
return await this.cache.store.keys(pattern)
48+
const keys = []
49+
for await (const [key] of this.store.store.entries()) {
50+
if (pattern) {
51+
const regex = new RegExp(`(?<!.)${pattern}`)
52+
if (regex.test(key))
53+
keys.push(key)
54+
}
55+
else {
56+
keys.push(key)
57+
}
58+
}
59+
return keys
4060
}
4161

4262
async has(key: string): Promise<boolean> {
43-
return !!await this.cache.store.get(key)
63+
return !!await this.cache.get(key)
4464
}
4565

4666
async getAll<T>(): Promise<T[]> {
47-
const keys = await this.keys()
48-
const values = await Promise.all(keys.map(async key => await this.get<T>(key)))
49-
return values.filter(value => value !== undefined)
67+
const values = []
68+
for await (const [, value] of this.store.store.entries())
69+
values.push(value)
70+
return values
5071
}
5172
}

packages/utils/src/store/memory.ts

Lines changed: 9 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,113 +1,13 @@
1-
import { LRUCache } from 'lru-cache'
2-
import cloneDeep from 'lodash.clonedeep'
3-
import type { Cache, Config, Store } from 'cache-manager'
1+
import { Keyv } from 'keyv'
2+
import type { CacheableMemoryOptions } from 'cacheable'
3+
import { KeyvCacheableMemory } from 'cacheable'
44

5-
function clone<T>(object: T): T {
6-
if (typeof object === 'object' && object !== null)
7-
return cloneDeep(object)
8-
9-
return object
5+
export type MemoryConfig = CacheableMemoryOptions & {
6+
namespace?: string
107
}
118

12-
type LRU = LRUCache<string, any>
13-
14-
type Pre = LRUCache.OptionsTTLLimit<string, any, unknown>
15-
type Options = Omit<Pre, 'ttlAutopurge'> & Partial<Pick<Pre, 'ttlAutopurge'>>
16-
export type MemoryConfig = {
17-
max?: number
18-
sizeCalculation?: (value: unknown, key: string) => number
19-
shouldCloneBeforeSet?: boolean
20-
} & Options &
21-
Config
22-
23-
export type MemoryStore = Store & {
24-
dump: LRU['dump']
25-
load: LRU['load']
26-
calculatedSize: LRU['calculatedSize']
27-
get size(): number
28-
}
29-
export type MemoryCache = Cache<MemoryStore>
30-
31-
/**
32-
* Wrapper for lru-cache.
33-
*/
34-
export function memoryStore(arguments_?: MemoryConfig): MemoryStore {
35-
const shouldCloneBeforeSet = arguments_?.shouldCloneBeforeSet !== false // Clone by default
36-
const isCacheable = arguments_?.isCacheable ?? (value => value !== undefined)
37-
38-
const lruOptions = {
39-
ttlAutopurge: true,
40-
...arguments_,
41-
max: arguments_?.max ?? 500,
42-
ttl: arguments_?.ttl === undefined ? 0 : arguments_.ttl,
43-
}
44-
45-
const lruCache = new LRUCache(lruOptions)
46-
47-
return {
48-
async del(key) {
49-
lruCache.delete(key)
50-
},
51-
get: async <T>(key: string) => lruCache.get(key) as T,
52-
keys: async (pattern?: string) => {
53-
const keys = [...lruCache.keys()]
54-
if (!pattern)
55-
return keys
56-
57-
const regex = new RegExp(`(?<!.)${pattern}`)
58-
return keys.filter(key => regex.test(key))
59-
},
60-
61-
mget: async (...arguments_) => arguments_.map(x => lruCache.get(x)),
62-
async mset(arguments_, ttl?) {
63-
const opt = { ttl: ttl ?? lruOptions.ttl } as const
64-
for (const [key, value] of arguments_) {
65-
if (!isCacheable(value))
66-
throw new Error(`no cacheable value ${JSON.stringify(value)}`)
67-
68-
if (shouldCloneBeforeSet)
69-
lruCache.set(key, clone(value), opt)
70-
else
71-
lruCache.set(key, value, opt)
72-
}
73-
},
74-
async mdel(...arguments_) {
75-
for (const key of arguments_)
76-
lruCache.delete(key)
77-
},
78-
async reset() {
79-
lruCache.clear()
80-
},
81-
ttl: async key => lruCache.getRemainingTTL(key),
82-
async set(key, value, opt) {
83-
if (!isCacheable(value))
84-
throw new Error(`no cacheable value ${JSON.stringify(value)}`)
85-
86-
if (shouldCloneBeforeSet)
87-
value = clone(value)
88-
89-
const ttl = opt ?? lruOptions.ttl
90-
91-
lruCache.set(key, value, { ttl })
92-
},
93-
get calculatedSize() {
94-
return lruCache.calculatedSize
95-
},
96-
/**
97-
* This method is not available in the caching modules.
98-
*/
99-
get size() {
100-
return lruCache.size
101-
},
102-
/**
103-
* This method is not available in the caching modules.
104-
*/
105-
dump: () => lruCache.dump(),
106-
/**
107-
* This method is not available in the caching modules.
108-
*/
109-
load(...arguments_: Parameters<LRU['load']>) {
110-
lruCache.load(...arguments_)
111-
},
112-
}
9+
export function memoryStore(options?: MemoryConfig) {
10+
const store = new KeyvCacheableMemory(options)
11+
const keyv = new Keyv({ store }, { namespace: '' })
12+
return keyv
11313
}

packages/utils/src/store/redis.ts

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,33 @@
1-
import type { RedisOptions } from 'ioredis'
2-
import { Redis } from 'ioredis'
3-
import type { Config } from 'cache-manager'
4-
import { RedisClusterConfig, redisInsStore } from 'cache-manager-ioredis-yet'
1+
import type { KeyvRedisOptions, RedisClientConnectionType, RedisClientOptions, RedisClusterOptions } from '@keyv/redis'
2+
import KeyvRedis, { Keyv } from '@keyv/redis'
3+
4+
export interface RedisConnect {
5+
host?: string
6+
port?: number
7+
username?: string
8+
password?: string
9+
db?: number
10+
}
511

612
export function redisStore(
7-
options?: (RedisOptions | { clusterConfig: RedisClusterConfig }) & Config,
13+
connect?: string | RedisClientOptions | RedisClusterOptions | RedisClientConnectionType | RedisConnect,
14+
options?: KeyvRedisOptions,
815
) {
9-
options ||= {}
10-
const redisCache
11-
= 'clusterConfig' in options
12-
? new Redis.Cluster(
13-
options.clusterConfig.nodes,
14-
options.clusterConfig.options,
15-
)
16-
: new Redis(options)
17-
18-
return redisInsStore(redisCache, options)
19-
}
16+
if (typeof connect === 'object' && connect) {
17+
if (Reflect.get(connect, 'host')) {
18+
const c = connect as RedisConnect
19+
let connectStr = 'redis://'
20+
if (c.username)
21+
connectStr += `${c.username}:${c.password}@`
22+
connectStr += `${c.host}:${c.port}`
23+
if (c.db)
24+
connectStr += `/${c.db}`
25+
connect = connectStr
26+
}
27+
}
2028

21-
export {
22-
RedisClusterConfig,
23-
redisInsStore,
29+
const keyv = new Keyv(new KeyvRedis(connect, options), {
30+
namespace: '',
31+
})
32+
return keyv
2433
}

0 commit comments

Comments
 (0)