-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcache-redis.js
112 lines (97 loc) · 3.02 KB
/
cache-redis.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
import { compress, decompress } from '@tadashi/jsonb'
import { connect } from '@tadashi/connect-redis'
/**
* Class representing a cache using Redis with compression capabilities.
*/
class Cache {
/**
* Create a cache instance.
*
* @param {Object} [opts={}] - Options for configuring the cache.
* @param {string} [opts.address] - The address of the Redis server.
* @param {string} [opts.namespace='app'] - A namespace for the cache keys, defaulting to 'app'.
* @param {Object} [opts.redisOptions={}] - Additional options for Redis connection.
*/
constructor(opts = {}) {
const {
address,
namespace = 'app',
redisOptions = {},
} = opts
redisOptions.keyPrefix = redisOptions?.keyPrefix ?? 'tadashi_cache_redis'
redisOptions.keyPrefix = `${redisOptions.keyPrefix}_${namespace}:`
this.namespace = '@ns'
this.redis = connect({ ...redisOptions, address })
}
/**
* Retrieve a value from the cache.
*
* @param {string} key - The key of the item to retrieve.
* @returns {Promise<*>} A promise that resolves with the decompressed value retrieved from the cache, or undefined if not found.
*/
async get(key) {
let value = await this.redis.getBuffer(key)
if (value === undefined || value === null) {
return
}
value = await decompress(value)
return value
}
/**
* Set a value in the cache.
*
* @param {string} key - The key under which the value will be stored.
* @param {*} value - The value to store in the cache.
* @param {string} [expire] - Optional expiration mode ('EX', 'PX', 'EXAT', 'PXAT').
* @param {number} [ttl=0] - Optional time-to-live for the cache entry.
* @returns {Promise<Object>} An object indicating the success of the set and sadd operations.
*/
async set(key, value, expire, ttl = 0) {
if (value === undefined) {
return
}
let _ttl = typeof ttl === 'number' ? ttl : Number(ttl)
_ttl = Number.isInteger(_ttl) ? _ttl : 0
const _value = await compress(value, { base64: false })
let args = [key, _value]
if (expire === 'EX' || expire === 'PX') {
args = [...args, expire, _ttl]
}
if (expire === 'EXAT' || expire === 'PXAT') {
const _time = _ttl + Math.floor(Date.now() / (expire === 'EXAT' ? 1000 : 1))
args = [...args, expire, _time]
}
const [[, set], [, sadd]] = await this.redis
.multi()
// @ts-ignore: pure js
.set(...args)
.sadd(this.namespace, key)
.exec()
return { set, sadd }
}
/**
* Delete a value from the cache.
*
* @param {string} key - The key of the item to delete.
* @returns {Promise<Object>} An object indicating the success of the del and srem operations.
*/
async delete(key) {
const [[, del], [, srem]] = await this.redis
.multi()
.del(key)
.srem(this.namespace, key)
.exec()
return { del, srem }
}
/**
* Clear the entire cache.
*
* @returns {Promise<void>} A promise that resolves when the cache is cleared.
*/
async clear() {
const keys = await this.redis.smembers(this.namespace)
const args = [...keys, this.namespace]
await this.redis.del(...args)
}
}
export default Cache