@cacheable/node-cache 0.5.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +43 -2
- package/dist/index.cjs +398 -0
- package/dist/index.d.cts +89 -0
- package/dist/index.d.ts +39 -12
- package/dist/index.js +335 -317
- package/package.json +19 -9
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,344 +1,362 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
useClones: true,
|
|
24
|
-
deleteOnExpire: true,
|
|
25
|
-
maxKeys: -1,
|
|
26
|
-
};
|
|
27
|
-
this.store = new Map();
|
|
28
|
-
this._stats = {
|
|
29
|
-
keys: 0,
|
|
30
|
-
hits: 0,
|
|
31
|
-
misses: 0,
|
|
32
|
-
ksize: 0,
|
|
33
|
-
vsize: 0,
|
|
34
|
-
};
|
|
35
|
-
this.intervalId = 0;
|
|
36
|
-
if (options) {
|
|
37
|
-
this.options = Object.assign(Object.assign({}, this.options), options);
|
|
38
|
-
}
|
|
39
|
-
this.startInterval();
|
|
40
|
-
}
|
|
41
|
-
// Sets a key value pair. It is possible to define a ttl (in seconds). Returns true on success.
|
|
42
|
-
set(key, value, ttl) {
|
|
43
|
-
// Check on key type
|
|
44
|
-
/* c8 ignore next 3 */
|
|
45
|
-
if (typeof key !== 'string' && typeof key !== 'number') {
|
|
46
|
-
throw this.createError(NodeCacheErrors.EKEYTYPE, key);
|
|
47
|
-
}
|
|
48
|
-
// Check on ttl type
|
|
49
|
-
/* c8 ignore next 3 */
|
|
50
|
-
if (ttl && typeof ttl !== 'number') {
|
|
51
|
-
throw this.createError(NodeCacheErrors.ETTLTYPE, this.formatKey(key));
|
|
52
|
-
}
|
|
53
|
-
const keyValue = this.formatKey(key);
|
|
54
|
-
const ttlValue = ttl !== null && ttl !== void 0 ? ttl : this.options.stdTTL;
|
|
55
|
-
let expirationTimestamp = 0; // Never delete
|
|
56
|
-
if (ttlValue && ttlValue > 0) {
|
|
57
|
-
expirationTimestamp = this.getExpirationTimestamp(ttlValue);
|
|
58
|
-
}
|
|
59
|
-
// Check on max key size
|
|
60
|
-
if (this.options.maxKeys) {
|
|
61
|
-
const maxKeys = this.options.maxKeys;
|
|
62
|
-
if (maxKeys > -1 && this.store.size >= maxKeys) {
|
|
63
|
-
throw this.createError(NodeCacheErrors.ECACHEFULL, this.formatKey(key));
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
this.store.set(keyValue, { key: keyValue, value, ttl: expirationTimestamp });
|
|
67
|
-
// Event
|
|
68
|
-
this.emit('set', keyValue, value, ttlValue);
|
|
69
|
-
// Add the bytes to the stats
|
|
70
|
-
this._stats.ksize += this.roughSizeOfKey(keyValue);
|
|
71
|
-
this._stats.vsize += this.roughSizeOfObject(value);
|
|
72
|
-
this._stats.keys = this.store.size;
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
// Sets multiple key val pairs. It is possible to define a ttl (seconds). Returns true on success.
|
|
76
|
-
mset(data) {
|
|
77
|
-
// Check on keys type
|
|
78
|
-
/* c8 ignore next 3 */
|
|
79
|
-
if (!Array.isArray(data)) {
|
|
80
|
-
throw this.createError(NodeCacheErrors.EKEYSTYPE);
|
|
81
|
-
}
|
|
82
|
-
for (const item of data) {
|
|
83
|
-
this.set(item.key, item.value, item.ttl);
|
|
84
|
-
}
|
|
85
|
-
return true;
|
|
86
|
-
}
|
|
87
|
-
// Gets a saved value from the cache. Returns a undefined if not found or expired. If the value was found it returns the value.
|
|
88
|
-
get(key) {
|
|
89
|
-
const result = this.store.get(this.formatKey(key));
|
|
90
|
-
if (result) {
|
|
91
|
-
if (result.ttl > 0) {
|
|
92
|
-
if (result.ttl < Date.now()) {
|
|
93
|
-
if (this.options.deleteOnExpire) {
|
|
94
|
-
this.del(key);
|
|
95
|
-
}
|
|
96
|
-
this.addMiss();
|
|
97
|
-
// Event
|
|
98
|
-
this.emit('expired', this.formatKey(key), result.value);
|
|
99
|
-
return undefined;
|
|
100
|
-
}
|
|
101
|
-
this.addHit();
|
|
102
|
-
if (this.options.useClones) {
|
|
103
|
-
return this.clone(result.value);
|
|
104
|
-
}
|
|
105
|
-
return result.value;
|
|
106
|
-
}
|
|
107
|
-
this.addHit();
|
|
108
|
-
if (this.options.useClones) {
|
|
109
|
-
return this.clone(result.value);
|
|
110
|
-
}
|
|
111
|
-
return result.value;
|
|
112
|
-
}
|
|
113
|
-
this.addMiss();
|
|
114
|
-
return undefined;
|
|
115
|
-
}
|
|
116
|
-
/*
|
|
117
|
-
Gets multiple saved values from the cache. Returns an empty object {} if not found or expired.
|
|
118
|
-
If the value was found it returns an object with the key value pair.
|
|
119
|
-
*/
|
|
120
|
-
mget(keys) {
|
|
121
|
-
const result = {};
|
|
122
|
-
for (const key of keys) {
|
|
123
|
-
const value = this.get(key);
|
|
124
|
-
if (value) {
|
|
125
|
-
result[this.formatKey(key)] = value;
|
|
126
|
-
}
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import eventemitter from "eventemitter3";
|
|
3
|
+
import { CacheableMemory as CacheableMemory2, CacheableStats } from "cacheable";
|
|
4
|
+
|
|
5
|
+
// src/store.ts
|
|
6
|
+
import { Cacheable, CacheableMemory } from "cacheable";
|
|
7
|
+
import { Keyv } from "keyv";
|
|
8
|
+
var NodeCacheStore = class {
|
|
9
|
+
_maxKeys = 0;
|
|
10
|
+
_cache = new Cacheable({ primary: new Keyv({ store: new CacheableMemory() }) });
|
|
11
|
+
constructor(options) {
|
|
12
|
+
if (options) {
|
|
13
|
+
const cacheOptions = {
|
|
14
|
+
ttl: options.ttl,
|
|
15
|
+
primary: options.primary,
|
|
16
|
+
secondary: options.secondary
|
|
17
|
+
};
|
|
18
|
+
this._cache = new Cacheable(cacheOptions);
|
|
19
|
+
if (options.maxKeys) {
|
|
20
|
+
this._maxKeys = options.maxKeys;
|
|
21
|
+
if (this._maxKeys > 0) {
|
|
22
|
+
this._cache.stats.enabled = true;
|
|
127
23
|
}
|
|
128
|
-
|
|
24
|
+
}
|
|
129
25
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
26
|
+
}
|
|
27
|
+
get cache() {
|
|
28
|
+
return this._cache;
|
|
29
|
+
}
|
|
30
|
+
get ttl() {
|
|
31
|
+
return this._cache.ttl;
|
|
32
|
+
}
|
|
33
|
+
set ttl(ttl) {
|
|
34
|
+
this._cache.ttl = ttl;
|
|
35
|
+
}
|
|
36
|
+
get primary() {
|
|
37
|
+
return this._cache.primary;
|
|
38
|
+
}
|
|
39
|
+
set primary(primary) {
|
|
40
|
+
this._cache.primary = primary;
|
|
41
|
+
}
|
|
42
|
+
get secondary() {
|
|
43
|
+
return this._cache.secondary;
|
|
44
|
+
}
|
|
45
|
+
set secondary(secondary) {
|
|
46
|
+
this._cache.secondary = secondary;
|
|
47
|
+
}
|
|
48
|
+
get maxKeys() {
|
|
49
|
+
return this._maxKeys;
|
|
50
|
+
}
|
|
51
|
+
set maxKeys(maxKeys) {
|
|
52
|
+
this._maxKeys = maxKeys;
|
|
53
|
+
if (this._maxKeys > 0) {
|
|
54
|
+
this._cache.stats.enabled = true;
|
|
145
55
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const keyValue = this.formatKey(key);
|
|
154
|
-
this.store.delete(keyValue);
|
|
155
|
-
// Event
|
|
156
|
-
this.emit('del', keyValue, result.value);
|
|
157
|
-
// Remove the bytes from the stats
|
|
158
|
-
this._stats.ksize -= this.roughSizeOfKey(keyValue);
|
|
159
|
-
this._stats.vsize -= this.roughSizeOfObject(result.value);
|
|
160
|
-
this._stats.keys = this.store.size;
|
|
161
|
-
return 1;
|
|
162
|
-
}
|
|
163
|
-
return 0;
|
|
56
|
+
}
|
|
57
|
+
async set(key, value, ttl) {
|
|
58
|
+
if (this._maxKeys > 0) {
|
|
59
|
+
console.log(this._cache.stats.count, this._maxKeys);
|
|
60
|
+
if (this._cache.stats.count >= this._maxKeys) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
164
63
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
64
|
+
const finalTtl = ttl ?? this._cache.ttl;
|
|
65
|
+
await this._cache.set(key.toString(), value, finalTtl);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
async mset(list) {
|
|
69
|
+
const items = new Array();
|
|
70
|
+
for (const item of list) {
|
|
71
|
+
items.push({ key: item.key.toString(), value: item.value, ttl: item.ttl });
|
|
172
72
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
return false;
|
|
73
|
+
await this._cache.setMany(items);
|
|
74
|
+
}
|
|
75
|
+
async get(key) {
|
|
76
|
+
return this._cache.get(key.toString());
|
|
77
|
+
}
|
|
78
|
+
async mget(keys) {
|
|
79
|
+
const result = {};
|
|
80
|
+
for (const key of keys) {
|
|
81
|
+
result[key.toString()] = await this._cache.get(key.toString());
|
|
184
82
|
}
|
|
185
|
-
|
|
186
|
-
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
async del(key) {
|
|
86
|
+
return this._cache.delete(key.toString());
|
|
87
|
+
}
|
|
88
|
+
async mdel(keys) {
|
|
89
|
+
return this._cache.deleteMany(keys.map((key) => key.toString()));
|
|
90
|
+
}
|
|
91
|
+
async clear() {
|
|
92
|
+
return this._cache.clear();
|
|
93
|
+
}
|
|
94
|
+
};
|
|
187
95
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
96
|
+
// src/index.ts
|
|
97
|
+
var NodeCacheErrors = /* @__PURE__ */ ((NodeCacheErrors2) => {
|
|
98
|
+
NodeCacheErrors2["ECACHEFULL"] = "Cache max keys amount exceeded";
|
|
99
|
+
NodeCacheErrors2["EKEYTYPE"] = "The key argument has to be of type `string` or `number`. Found: `__key`";
|
|
100
|
+
NodeCacheErrors2["EKEYSTYPE"] = "The keys argument has to be an array.";
|
|
101
|
+
NodeCacheErrors2["ETTLTYPE"] = "The ttl argument has to be a number.";
|
|
102
|
+
return NodeCacheErrors2;
|
|
103
|
+
})(NodeCacheErrors || {});
|
|
104
|
+
var NodeCache = class extends eventemitter {
|
|
105
|
+
options = {
|
|
106
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
107
|
+
stdTTL: 0,
|
|
108
|
+
checkperiod: 600,
|
|
109
|
+
useClones: true,
|
|
110
|
+
deleteOnExpire: true,
|
|
111
|
+
maxKeys: -1
|
|
112
|
+
};
|
|
113
|
+
store = /* @__PURE__ */ new Map();
|
|
114
|
+
_stats = new CacheableStats({ enabled: true });
|
|
115
|
+
_cacheable = new CacheableMemory2();
|
|
116
|
+
intervalId = 0;
|
|
117
|
+
constructor(options) {
|
|
118
|
+
super();
|
|
119
|
+
if (options) {
|
|
120
|
+
this.options = { ...this.options, ...options };
|
|
201
121
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
for (const key of this.store.keys()) {
|
|
209
|
-
result.push(key);
|
|
210
|
-
}
|
|
211
|
-
return result;
|
|
122
|
+
this.startInterval();
|
|
123
|
+
}
|
|
124
|
+
// Sets a key value pair. It is possible to define a ttl (in seconds). Returns true on success.
|
|
125
|
+
set(key, value, ttl) {
|
|
126
|
+
if (typeof key !== "string" && typeof key !== "number") {
|
|
127
|
+
throw this.createError("The key argument has to be of type `string` or `number`. Found: `__key`" /* EKEYTYPE */, key);
|
|
212
128
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
return this.store.has(this.formatKey(key));
|
|
129
|
+
if (ttl && typeof ttl !== "number") {
|
|
130
|
+
throw this.createError("The ttl argument has to be a number." /* ETTLTYPE */, this.formatKey(key));
|
|
216
131
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
132
|
+
const keyValue = this.formatKey(key);
|
|
133
|
+
const ttlValue = ttl ?? this.options.stdTTL;
|
|
134
|
+
let expirationTimestamp = 0;
|
|
135
|
+
if (ttlValue && ttlValue > 0) {
|
|
136
|
+
expirationTimestamp = this.getExpirationTimestamp(ttlValue);
|
|
220
137
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
this.
|
|
225
|
-
|
|
226
|
-
this.emit('flush');
|
|
138
|
+
if (this.options.maxKeys) {
|
|
139
|
+
const maxKeys = this.options.maxKeys;
|
|
140
|
+
if (maxKeys > -1 && this.store.size >= maxKeys) {
|
|
141
|
+
throw this.createError("Cache max keys amount exceeded" /* ECACHEFULL */, this.formatKey(key));
|
|
142
|
+
}
|
|
227
143
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
144
|
+
this.store.set(keyValue, { key: keyValue, value, ttl: expirationTimestamp });
|
|
145
|
+
this.emit("set", keyValue, value, ttlValue);
|
|
146
|
+
this._stats.incrementKSize(keyValue);
|
|
147
|
+
this._stats.incrementVSize(value);
|
|
148
|
+
this._stats.setCount(this.store.size);
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
// Sets multiple key val pairs. It is possible to define a ttl (seconds). Returns true on success.
|
|
152
|
+
mset(data) {
|
|
153
|
+
if (!Array.isArray(data)) {
|
|
154
|
+
throw this.createError("The keys argument has to be an array." /* EKEYSTYPE */);
|
|
239
155
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
this.stopInterval();
|
|
156
|
+
for (const item of data) {
|
|
157
|
+
this.set(item.key, item.value, item.ttl);
|
|
243
158
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
// Gets a saved value from the cache. Returns a undefined if not found or expired. If the value was found it returns the value.
|
|
162
|
+
get(key) {
|
|
163
|
+
const result = this.store.get(this.formatKey(key));
|
|
164
|
+
if (result) {
|
|
165
|
+
if (result.ttl > 0) {
|
|
166
|
+
if (result.ttl < Date.now()) {
|
|
167
|
+
if (this.options.deleteOnExpire) {
|
|
168
|
+
this.del(key);
|
|
169
|
+
}
|
|
170
|
+
this._stats.incrementMisses();
|
|
171
|
+
this.emit("expired", this.formatKey(key), result.value);
|
|
172
|
+
return void 0;
|
|
173
|
+
}
|
|
174
|
+
this._stats.incrementHits();
|
|
175
|
+
if (this.options.useClones) {
|
|
176
|
+
return this._cacheable.clone(result.value);
|
|
177
|
+
}
|
|
178
|
+
return result.value;
|
|
179
|
+
}
|
|
180
|
+
this._stats.incrementHits();
|
|
181
|
+
if (this.options.useClones) {
|
|
182
|
+
return this._cacheable.clone(result.value);
|
|
183
|
+
}
|
|
184
|
+
return result.value;
|
|
247
185
|
}
|
|
248
|
-
|
|
249
|
-
|
|
186
|
+
this._stats.incrementMisses();
|
|
187
|
+
return void 0;
|
|
188
|
+
}
|
|
189
|
+
/*
|
|
190
|
+
Gets multiple saved values from the cache. Returns an empty object {} if not found or expired.
|
|
191
|
+
If the value was found it returns an object with the key value pair.
|
|
192
|
+
*/
|
|
193
|
+
mget(keys) {
|
|
194
|
+
const result = {};
|
|
195
|
+
for (const key of keys) {
|
|
196
|
+
const value = this.get(key);
|
|
197
|
+
if (value) {
|
|
198
|
+
result[this.formatKey(key)] = value;
|
|
199
|
+
}
|
|
250
200
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
/*
|
|
204
|
+
Get the cached value and remove the key from the cache.
|
|
205
|
+
Equivalent to calling get(key) + del(key).
|
|
206
|
+
Useful for implementing single use mechanism such as OTP, where once a value is read it will become obsolete.
|
|
207
|
+
*/
|
|
208
|
+
take(key) {
|
|
209
|
+
const result = this.get(key);
|
|
210
|
+
if (result) {
|
|
211
|
+
this.del(key);
|
|
212
|
+
if (this.options.useClones) {
|
|
213
|
+
return this._cacheable.clone(result);
|
|
214
|
+
}
|
|
215
|
+
return result;
|
|
256
216
|
}
|
|
257
|
-
|
|
258
|
-
|
|
217
|
+
return void 0;
|
|
218
|
+
}
|
|
219
|
+
// Delete a key. Returns the number of deleted entries. A delete will never fail.
|
|
220
|
+
del(key) {
|
|
221
|
+
if (Array.isArray(key)) {
|
|
222
|
+
return this.mdel(key);
|
|
259
223
|
}
|
|
260
|
-
|
|
261
|
-
|
|
224
|
+
const result = this.store.get(this.formatKey(key));
|
|
225
|
+
if (result) {
|
|
226
|
+
const keyValue = this.formatKey(key);
|
|
227
|
+
this.store.delete(keyValue);
|
|
228
|
+
this.emit("del", keyValue, result.value);
|
|
229
|
+
this._stats.decreaseKSize(keyValue);
|
|
230
|
+
this._stats.decreaseVSize(result.value);
|
|
231
|
+
this._stats.setCount(this.store.size);
|
|
232
|
+
return 1;
|
|
262
233
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
234
|
+
return 0;
|
|
235
|
+
}
|
|
236
|
+
// Delete all keys in Array that exist. Returns the number of deleted entries.
|
|
237
|
+
mdel(keys) {
|
|
238
|
+
let result = 0;
|
|
239
|
+
for (const key of keys) {
|
|
240
|
+
result += this.del(key);
|
|
266
241
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
else if (typeof value === 'number') {
|
|
280
|
-
bytes += 8; // Numbers are 8 bytes (IEEE 754 format)
|
|
281
|
-
}
|
|
282
|
-
else if (typeof value === 'object' && value !== null && !objectList.includes(value)) {
|
|
283
|
-
objectList.push(value);
|
|
284
|
-
// Estimate object overhead, and then recursively estimate the size of properties
|
|
285
|
-
// eslint-disable-next-line guard-for-in
|
|
286
|
-
for (const key in value) {
|
|
287
|
-
bytes += key.length * 2; // Keys are strings (UTF-16)
|
|
288
|
-
stack.push(value[key]); // Add values to the stack to compute their size
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
return bytes;
|
|
242
|
+
return result;
|
|
243
|
+
}
|
|
244
|
+
// Redefine the ttl of a key. Returns true if the key has been found and changed.
|
|
245
|
+
// Otherwise returns false. If the ttl-argument isn't passed the default-TTL will be used.
|
|
246
|
+
ttl(key, ttl) {
|
|
247
|
+
const result = this.store.get(this.formatKey(key));
|
|
248
|
+
if (result) {
|
|
249
|
+
const ttlValue = ttl ?? this.options.stdTTL;
|
|
250
|
+
result.ttl = this.getExpirationTimestamp(ttlValue);
|
|
251
|
+
this.store.set(this.formatKey(key), result);
|
|
252
|
+
return true;
|
|
293
253
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
/*
|
|
257
|
+
Receive the ttl of a key. You will get:
|
|
258
|
+
|
|
259
|
+
undefined if the key does not exist
|
|
260
|
+
0 if this key has no ttl
|
|
261
|
+
a timestamp in ms representing the time at which the key will expire
|
|
262
|
+
*/
|
|
263
|
+
getTtl(key) {
|
|
264
|
+
const result = this.store.get(this.formatKey(key));
|
|
265
|
+
if (result) {
|
|
266
|
+
if (result.ttl === 0) {
|
|
267
|
+
return 0;
|
|
268
|
+
}
|
|
269
|
+
return result.ttl;
|
|
303
270
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
271
|
+
return void 0;
|
|
272
|
+
}
|
|
273
|
+
/*
|
|
274
|
+
Returns an array of all existing keys.
|
|
275
|
+
[ "all", "my", "keys", "foo", "bar" ]
|
|
276
|
+
*/
|
|
277
|
+
keys() {
|
|
278
|
+
const result = [];
|
|
279
|
+
for (const key of this.store.keys()) {
|
|
280
|
+
result.push(key);
|
|
310
281
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
282
|
+
return result;
|
|
283
|
+
}
|
|
284
|
+
// Returns boolean indicating if the key is cached.
|
|
285
|
+
has(key) {
|
|
286
|
+
return this.store.has(this.formatKey(key));
|
|
287
|
+
}
|
|
288
|
+
// Gets the stats of the cache.
|
|
289
|
+
getStats() {
|
|
290
|
+
const stats = {
|
|
291
|
+
keys: this._stats.count,
|
|
292
|
+
hits: this._stats.hits,
|
|
293
|
+
misses: this._stats.misses,
|
|
294
|
+
ksize: this._stats.ksize,
|
|
295
|
+
vsize: this._stats.vsize
|
|
296
|
+
};
|
|
297
|
+
return stats;
|
|
298
|
+
}
|
|
299
|
+
// Flush the whole data.
|
|
300
|
+
flushAll() {
|
|
301
|
+
this.store.clear();
|
|
302
|
+
this.flushStats();
|
|
303
|
+
this.emit("flush");
|
|
304
|
+
}
|
|
305
|
+
// Flush the stats
|
|
306
|
+
flushStats() {
|
|
307
|
+
this._stats = new CacheableStats({ enabled: true });
|
|
308
|
+
this.emit("flush_stats");
|
|
309
|
+
}
|
|
310
|
+
// Close the cache. This will clear the interval timeout which is set on check period option.
|
|
311
|
+
close() {
|
|
312
|
+
this.stopInterval();
|
|
313
|
+
}
|
|
314
|
+
// Get the interval id
|
|
315
|
+
getIntervalId() {
|
|
316
|
+
return this.intervalId;
|
|
317
|
+
}
|
|
318
|
+
formatKey(key) {
|
|
319
|
+
return key.toString();
|
|
320
|
+
}
|
|
321
|
+
getExpirationTimestamp(ttlInSeconds) {
|
|
322
|
+
const currentTimestamp = Date.now();
|
|
323
|
+
const ttlInMilliseconds = ttlInSeconds * 1e3;
|
|
324
|
+
const expirationTimestamp = currentTimestamp + ttlInMilliseconds;
|
|
325
|
+
return expirationTimestamp;
|
|
326
|
+
}
|
|
327
|
+
startInterval() {
|
|
328
|
+
if (this.options.checkperiod && this.options.checkperiod > 0) {
|
|
329
|
+
const checkPeriodinSeconds = this.options.checkperiod * 1e3;
|
|
330
|
+
this.intervalId = setInterval(() => {
|
|
331
|
+
this.checkData();
|
|
332
|
+
}, checkPeriodinSeconds);
|
|
333
|
+
return;
|
|
316
334
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
335
|
+
this.intervalId = 0;
|
|
336
|
+
}
|
|
337
|
+
checkData() {
|
|
338
|
+
for (const [key, value] of this.store.entries()) {
|
|
339
|
+
if (value.ttl > 0 && value.ttl < Date.now()) {
|
|
340
|
+
this.del(key);
|
|
341
|
+
}
|
|
324
342
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
}
|
|
331
|
-
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
332
|
-
return true;
|
|
333
|
-
}
|
|
334
|
-
return result;
|
|
343
|
+
}
|
|
344
|
+
stopInterval() {
|
|
345
|
+
if (this.intervalId !== 0) {
|
|
346
|
+
clearInterval(this.intervalId);
|
|
347
|
+
this.intervalId = 0;
|
|
335
348
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
349
|
+
}
|
|
350
|
+
createError(errorCode, key) {
|
|
351
|
+
let error = errorCode;
|
|
352
|
+
if (key) {
|
|
353
|
+
error = error.replace("__key", key);
|
|
341
354
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
355
|
+
return new Error(error);
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
export {
|
|
359
|
+
NodeCacheErrors,
|
|
360
|
+
NodeCacheStore,
|
|
361
|
+
NodeCache as default
|
|
362
|
+
};
|