koatty_store 1.5.4 → 1.5.6
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/.rollup.config.js +63 -0
- package/CHANGELOG.md +9 -0
- package/dist/LICENSE +29 -0
- package/dist/README.md +2 -0
- package/dist/index.d.ts +866 -49
- package/dist/index.js +1913 -51
- package/dist/{store/memory_cache.js → index.mjs} +1885 -1148
- package/dist/package.json +92 -0
- package/package.json +31 -24
- package/.eslintignore +0 -9
- package/.eslintrc.js +0 -43
- package/babel.config.js +0 -21
- package/commitlint.config.js +0 -14
- package/dist/index.js.map +0 -1
- package/dist/store/memory.d.ts +0 -53
- package/dist/store/memory.js +0 -96
- package/dist/store/memory.js.map +0 -1
- package/dist/store/memory_cache.d.ts +0 -553
- package/dist/store/memory_cache.js.map +0 -1
- package/dist/store/redis.d.ts +0 -73
- package/dist/store/redis.js +0 -228
- package/dist/store/redis.js.map +0 -1
- package/dist/store.d.ts +0 -252
- package/dist/store.js +0 -383
- package/dist/store.js.map +0 -1
- package/jest.config.js +0 -36
- package/jest_html_reporters.html +0 -60
- package/tsconfig.json +0 -67
package/dist/index.js
CHANGED
|
@@ -1,54 +1,1916 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Object.defineProperty(exports,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
keyPrefix: 'Koatty',
|
|
35
|
-
timeout: 600,
|
|
36
|
-
poolSize: 10,
|
|
37
|
-
connectTimeout: 500,
|
|
38
|
-
db: 0
|
|
39
|
-
}, ...options
|
|
40
|
-
};
|
|
41
|
-
switch (options.type) {
|
|
42
|
-
case "redis":
|
|
43
|
-
this.instance = new redis_1.RedisStore(options);
|
|
44
|
-
break;
|
|
45
|
-
case "memory":
|
|
46
|
-
default:
|
|
47
|
-
this.instance = new memory_1.MemoryStore(options);
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
return this.instance;
|
|
1
|
+
/*!
|
|
2
|
+
* @Author: richen
|
|
3
|
+
* @Date: 2022-11-03 16:31:15
|
|
4
|
+
* @License: BSD (3-Clause)
|
|
5
|
+
* @Copyright (c) - <richenlin(at)gmail.com>
|
|
6
|
+
* @HomePage: https://koatty.org/
|
|
7
|
+
*/
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
11
|
+
|
|
12
|
+
var lodash = require('lodash');
|
|
13
|
+
var helper = require('koatty_lib');
|
|
14
|
+
var events = require('events');
|
|
15
|
+
var koatty_logger = require('koatty_logger');
|
|
16
|
+
var IORedis = require('ioredis');
|
|
17
|
+
var genericPool = require('generic-pool');
|
|
18
|
+
|
|
19
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
20
|
+
|
|
21
|
+
function _interopNamespace(e) {
|
|
22
|
+
if (e && e.__esModule) return e;
|
|
23
|
+
var n = Object.create(null);
|
|
24
|
+
if (e) {
|
|
25
|
+
Object.keys(e).forEach(function (k) {
|
|
26
|
+
if (k !== 'default') {
|
|
27
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
28
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
get: function () { return e[k]; }
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
});
|
|
51
34
|
}
|
|
35
|
+
n["default"] = e;
|
|
36
|
+
return Object.freeze(n);
|
|
52
37
|
}
|
|
38
|
+
|
|
39
|
+
var helper__namespace = /*#__PURE__*/_interopNamespace(helper);
|
|
40
|
+
var IORedis__default = /*#__PURE__*/_interopDefaultLegacy(IORedis);
|
|
41
|
+
var genericPool__default = /*#__PURE__*/_interopDefaultLegacy(genericPool);
|
|
42
|
+
|
|
43
|
+
/*
|
|
44
|
+
* @Description:
|
|
45
|
+
* @Usage:
|
|
46
|
+
* @Author: richen
|
|
47
|
+
* @Date: 2021-12-02 15:26:55
|
|
48
|
+
* @LastEditTime: 2021-12-02 15:33:22
|
|
49
|
+
*/
|
|
50
|
+
/**
|
|
51
|
+
*
|
|
52
|
+
*
|
|
53
|
+
* @export
|
|
54
|
+
* @class Store
|
|
55
|
+
*/
|
|
56
|
+
class CacheStore {
|
|
57
|
+
/**
|
|
58
|
+
* Creates an instance of CacheStore.
|
|
59
|
+
* @param {StoreOptions} options
|
|
60
|
+
* @memberof CacheStore
|
|
61
|
+
*/
|
|
62
|
+
constructor(options) {
|
|
63
|
+
this.options = options;
|
|
64
|
+
this.pool = null;
|
|
65
|
+
this.client = null;
|
|
66
|
+
}
|
|
67
|
+
getConnection() {
|
|
68
|
+
throw new Error("Method not implemented.");
|
|
69
|
+
}
|
|
70
|
+
close() {
|
|
71
|
+
throw new Error("Method not implemented.");
|
|
72
|
+
}
|
|
73
|
+
release(conn) {
|
|
74
|
+
throw new Error("Method not implemented.");
|
|
75
|
+
}
|
|
76
|
+
defineCommand(name, scripts) {
|
|
77
|
+
throw new Error("Method not implemented.");
|
|
78
|
+
}
|
|
79
|
+
getCompare(name, value) {
|
|
80
|
+
throw new Error("Method not implemented.");
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* handler for native client
|
|
84
|
+
*
|
|
85
|
+
* @param {string} name
|
|
86
|
+
* @param {any[]} data
|
|
87
|
+
* @returns {*}
|
|
88
|
+
* @memberof RedisStore
|
|
89
|
+
*/
|
|
90
|
+
async wrap(name, data) {
|
|
91
|
+
let conn;
|
|
92
|
+
try {
|
|
93
|
+
conn = await this.getConnection();
|
|
94
|
+
const res = await conn[name](...data);
|
|
95
|
+
return res;
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
throw err;
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
this.release(conn);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* 字符串获取
|
|
106
|
+
* @param name
|
|
107
|
+
*/
|
|
108
|
+
get(name) {
|
|
109
|
+
return this.wrap('get', [`${this.options.keyPrefix}${name}`]);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* 字符串写入
|
|
113
|
+
* @param name
|
|
114
|
+
* @param value
|
|
115
|
+
* @param timeout
|
|
116
|
+
* @returns {Promise}
|
|
117
|
+
*/
|
|
118
|
+
set(name, value, timeout) {
|
|
119
|
+
if (typeof timeout !== 'number') {
|
|
120
|
+
timeout = this.options.timeout;
|
|
121
|
+
}
|
|
122
|
+
return this.wrap('set', [`${this.options.keyPrefix}${name}`, value, 'ex', timeout]);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* 以秒为单位,返回给定 key 的剩余生存时间
|
|
126
|
+
* @param name
|
|
127
|
+
* @returns {*}
|
|
128
|
+
*/
|
|
129
|
+
ttl(name) {
|
|
130
|
+
return this.wrap('ttl', [`${this.options.keyPrefix}${name}`]);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* 设置key超时属性
|
|
134
|
+
* @param name
|
|
135
|
+
* @param timeout
|
|
136
|
+
*/
|
|
137
|
+
expire(name, timeout) {
|
|
138
|
+
return this.wrap('expire', [`${this.options.keyPrefix}${name}`, timeout]);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* 删除key
|
|
142
|
+
* @param name
|
|
143
|
+
*/
|
|
144
|
+
rm(name) {
|
|
145
|
+
return this.wrap('del', [`${this.options.keyPrefix}${name}`]);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
*
|
|
149
|
+
*
|
|
150
|
+
* @param {*} name
|
|
151
|
+
* @returns
|
|
152
|
+
*/
|
|
153
|
+
del(name) {
|
|
154
|
+
return this.wrap('del', [`${this.options.keyPrefix}${name}`]);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* 判断key是否存在
|
|
158
|
+
* @param name
|
|
159
|
+
*/
|
|
160
|
+
exists(name) {
|
|
161
|
+
return this.wrap('exists', [`${this.options.keyPrefix}${name}`]);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* 自增
|
|
165
|
+
* @param name
|
|
166
|
+
*/
|
|
167
|
+
incr(name) {
|
|
168
|
+
return this.wrap('incr', [`${this.options.keyPrefix}${name}`]);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* 自减
|
|
172
|
+
* @param name
|
|
173
|
+
* @returns {*}
|
|
174
|
+
*/
|
|
175
|
+
decr(name) {
|
|
176
|
+
return this.wrap('decr', [`${this.options.keyPrefix}${name}`]);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* 将 key 所储存的值增加增量
|
|
180
|
+
* @param name
|
|
181
|
+
* @param incr
|
|
182
|
+
* @returns {*}
|
|
183
|
+
*/
|
|
184
|
+
incrby(name, incr = 1) {
|
|
185
|
+
return this.wrap('incrby', [`${this.options.keyPrefix}${name}`, incr]);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* 将 key 所储存的值减去减量
|
|
189
|
+
*
|
|
190
|
+
* @param {any} name
|
|
191
|
+
* @param {any} decr
|
|
192
|
+
*/
|
|
193
|
+
decrby(name, decr = 1) {
|
|
194
|
+
return this.wrap('decrby', [`${this.options.keyPrefix}${name}`, decr]);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* 哈希写入
|
|
198
|
+
* @param name
|
|
199
|
+
* @param key
|
|
200
|
+
* @param value
|
|
201
|
+
* @param timeout
|
|
202
|
+
*/
|
|
203
|
+
hset(name, key, value, timeout) {
|
|
204
|
+
const setP = [this.wrap('hset', [`${this.options.keyPrefix}${name}`, key, value])];
|
|
205
|
+
if (typeof timeout !== 'number') {
|
|
206
|
+
timeout = this.options.timeout;
|
|
207
|
+
}
|
|
208
|
+
setP.push(this.set(`${name}:${key}_ex`, 1, timeout));
|
|
209
|
+
return Promise.all(setP);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* 哈希获取
|
|
213
|
+
* @param name
|
|
214
|
+
* @param key
|
|
215
|
+
* @returns {*}
|
|
216
|
+
*/
|
|
217
|
+
hget(name, key) {
|
|
218
|
+
const setP = [this.get(`${name}:${key}_ex`)];
|
|
219
|
+
setP.push(this.wrap('hget', [`${this.options.keyPrefix}${name}`, key]));
|
|
220
|
+
return Promise.all(setP).then(dataArr => {
|
|
221
|
+
if (dataArr[0] === null) {
|
|
222
|
+
this.hdel(name, key);
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
return dataArr[1] || null;
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* 查看哈希表 hashKey 中,给定域 key 是否存在
|
|
230
|
+
* @param name
|
|
231
|
+
* @param key
|
|
232
|
+
* @returns {*}
|
|
233
|
+
*/
|
|
234
|
+
hexists(name, key) {
|
|
235
|
+
const setP = [this.get(`${name}:${key}_ex`)];
|
|
236
|
+
setP.push(this.wrap('hexists', [`${this.options.keyPrefix}${name}`, key]));
|
|
237
|
+
return Promise.all(setP).then(dataArr => {
|
|
238
|
+
if (dataArr[0] === null) {
|
|
239
|
+
this.hdel(name, key);
|
|
240
|
+
return 0;
|
|
241
|
+
}
|
|
242
|
+
return dataArr[1] || 0;
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* 哈希删除
|
|
247
|
+
* @param name
|
|
248
|
+
* @param key
|
|
249
|
+
* @returns {*}
|
|
250
|
+
*/
|
|
251
|
+
hdel(name, key) {
|
|
252
|
+
const setP = [this.del(`${name}:${key}_ex`)];
|
|
253
|
+
setP.push(this.wrap('hdel', [`${this.options.keyPrefix}${name}`, key]));
|
|
254
|
+
return Promise.all(setP);
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* 返回哈希表 key 中域的数量
|
|
258
|
+
* @param name
|
|
259
|
+
* @returns {*}
|
|
260
|
+
*/
|
|
261
|
+
hlen(name) {
|
|
262
|
+
return this.wrap('hlen', [`${this.options.keyPrefix}${name}`]);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* 给哈希表指定key,增加increment
|
|
266
|
+
* @param name
|
|
267
|
+
* @param key
|
|
268
|
+
* @param incr
|
|
269
|
+
* @returns {*}
|
|
270
|
+
*/
|
|
271
|
+
hincrby(name, key, incr = 1) {
|
|
272
|
+
return this.wrap('hincrby', [`${this.options.keyPrefix}${name}`, key, incr]);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* 返回哈希表所有key-value
|
|
276
|
+
* @param name
|
|
277
|
+
* @returns {*}
|
|
278
|
+
*/
|
|
279
|
+
hgetall(name) {
|
|
280
|
+
return this.wrap('hgetall', [`${this.options.keyPrefix}${name}`]);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* 返回哈希表所有key
|
|
284
|
+
* @param name
|
|
285
|
+
* @returns {*}
|
|
286
|
+
*/
|
|
287
|
+
hkeys(name) {
|
|
288
|
+
return this.wrap('hkeys', [`${this.options.keyPrefix}${name}`]);
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* 返回哈希表所有value
|
|
292
|
+
* @param name
|
|
293
|
+
* @returns {*}
|
|
294
|
+
*/
|
|
295
|
+
hvals(name) {
|
|
296
|
+
return this.wrap('hvals', [`${this.options.keyPrefix}${name}`]);
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* 判断列表长度,若不存在则表示为空
|
|
300
|
+
* @param name
|
|
301
|
+
* @returns {*}
|
|
302
|
+
*/
|
|
303
|
+
llen(name) {
|
|
304
|
+
return this.wrap('llen', [`${this.options.keyPrefix}${name}`]);
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* 将值插入列表表尾
|
|
308
|
+
* @param name
|
|
309
|
+
* @param value
|
|
310
|
+
* @returns {*}
|
|
311
|
+
*/
|
|
312
|
+
rpush(name, value) {
|
|
313
|
+
return this.wrap('rpush', [`${this.options.keyPrefix}${name}`, value]);
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
*
|
|
317
|
+
*
|
|
318
|
+
* @param {string} name
|
|
319
|
+
* @param {(string | number)} value
|
|
320
|
+
* @returns {*}
|
|
321
|
+
* @memberof RedisStore
|
|
322
|
+
*/
|
|
323
|
+
lpush(name, value) {
|
|
324
|
+
return this.wrap('lpush', [`${this.options.keyPrefix}${name}`, value]);
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* 将列表表头取出,并去除
|
|
328
|
+
* @param name
|
|
329
|
+
* @returns {*}
|
|
330
|
+
*/
|
|
331
|
+
lpop(name) {
|
|
332
|
+
return this.wrap('lpop', [`${this.options.keyPrefix}${name}`]);
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
*
|
|
336
|
+
*
|
|
337
|
+
* @param {string} name
|
|
338
|
+
* @returns {*}
|
|
339
|
+
* @memberof RedisStore
|
|
340
|
+
*/
|
|
341
|
+
rpop(name) {
|
|
342
|
+
return this.wrap('rpop', [`${this.options.keyPrefix}${name}`]);
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* 返回列表 key 中指定区间内的元素,区间以偏移量 start 和 stop 指定
|
|
346
|
+
* @param name
|
|
347
|
+
* @param start
|
|
348
|
+
* @param stop
|
|
349
|
+
* @returns {*}
|
|
350
|
+
*/
|
|
351
|
+
lrange(name, start, stop) {
|
|
352
|
+
return this.wrap('lrange', [`${this.options.keyPrefix}${name}`, start, stop]);
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* 集合新增
|
|
356
|
+
* @param name
|
|
357
|
+
* @param value
|
|
358
|
+
* @param timeout
|
|
359
|
+
* @returns {*}
|
|
360
|
+
*/
|
|
361
|
+
sadd(name, value, timeout) {
|
|
362
|
+
const setP = [this.wrap('sadd', [`${this.options.keyPrefix}${name}`, value])];
|
|
363
|
+
if (typeof timeout !== 'number') {
|
|
364
|
+
setP.push(this.wrap('expire', [`${this.options.keyPrefix}${name}`, timeout]));
|
|
365
|
+
}
|
|
366
|
+
return Promise.all(setP);
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* 返回集合的基数(集合中元素的数量)
|
|
370
|
+
* @param name
|
|
371
|
+
* @returns {*}
|
|
372
|
+
*/
|
|
373
|
+
scard(name) {
|
|
374
|
+
return this.wrap('scard', [`${this.options.keyPrefix}${name}`]);
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* 判断 member 元素是否集合的成员
|
|
378
|
+
* @param name
|
|
379
|
+
* @param key
|
|
380
|
+
* @returns {*}
|
|
381
|
+
*/
|
|
382
|
+
sismember(name, key) {
|
|
383
|
+
return this.wrap('sismember', [`${this.options.keyPrefix}${name}`, key]);
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* 返回集合中的所有成员
|
|
387
|
+
* @param name
|
|
388
|
+
* @returns {*}
|
|
389
|
+
*/
|
|
390
|
+
smembers(name) {
|
|
391
|
+
return this.wrap('smembers', [`${this.options.keyPrefix}${name}`]);
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* 移除并返回集合中的一个随机元素
|
|
395
|
+
* @param name
|
|
396
|
+
* @returns {*}
|
|
397
|
+
*/
|
|
398
|
+
spop(name) {
|
|
399
|
+
return this.wrap('spop', [`${this.options.keyPrefix}${name}`]);
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* 移除集合 key 中的一个 member 元素
|
|
403
|
+
* @param name
|
|
404
|
+
* @param key
|
|
405
|
+
* @returns {*}
|
|
406
|
+
*/
|
|
407
|
+
srem(name, key) {
|
|
408
|
+
return this.wrap('srem', [`${this.options.keyPrefix}${name}`, key]);
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* 将 member 元素从 source 集合移动到 destination 集合
|
|
412
|
+
* @param source
|
|
413
|
+
* @param destination
|
|
414
|
+
* @param member
|
|
415
|
+
* @returns {*}
|
|
416
|
+
*/
|
|
417
|
+
smove(source, destination, member) {
|
|
418
|
+
return this.wrap('smove', [`${this.options.keyPrefix}${source}`, `${this.options.keyPrefix}${destination}`, member]);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/*
|
|
423
|
+
* @Description:
|
|
424
|
+
* @Usage:
|
|
425
|
+
* @Author: richen
|
|
426
|
+
* @Date: 2021-12-02 11:03:20
|
|
427
|
+
* @LastEditTime: 2021-12-02 14:36:11
|
|
428
|
+
*/
|
|
429
|
+
/**
|
|
430
|
+
*
|
|
431
|
+
*
|
|
432
|
+
* @enum {number}
|
|
433
|
+
*/
|
|
434
|
+
var messages;
|
|
435
|
+
(function (messages) {
|
|
436
|
+
messages["ok"] = "OK";
|
|
437
|
+
messages["queued"] = "QUEUED";
|
|
438
|
+
messages["pong"] = "PONG";
|
|
439
|
+
messages["noint"] = "ERR value is not an integer or out of range";
|
|
440
|
+
messages["nofloat"] = "ERR value is not an float or out of range";
|
|
441
|
+
messages["nokey"] = "ERR no such key";
|
|
442
|
+
messages["nomultiinmulti"] = "ERR MULTI calls can not be nested";
|
|
443
|
+
messages["nomultiexec"] = "ERR EXEC without MULTI";
|
|
444
|
+
messages["nomultidiscard"] = "ERR DISCARD without MULTI";
|
|
445
|
+
messages["busykey"] = "ERR target key name is busy";
|
|
446
|
+
messages["syntax"] = "ERR syntax error";
|
|
447
|
+
messages["unsupported"] = "MemoryCache does not support that operation";
|
|
448
|
+
messages["wrongTypeOp"] = "WRONGTYPE Operation against a key holding the wrong kind of value";
|
|
449
|
+
messages["wrongPayload"] = "DUMP payload version or checksum are wrong";
|
|
450
|
+
messages["wrongArgCount"] = "ERR wrong number of arguments for '%0' command";
|
|
451
|
+
messages["bitopnotWrongCount"] = "ERR BITOP NOT must be called with a single source key";
|
|
452
|
+
messages["indexOutOfRange"] = "ERR index out of range";
|
|
453
|
+
messages["invalidLexRange"] = "ERR min or max not valid string range item";
|
|
454
|
+
messages["invalidDBIndex"] = "ERR invalid DB index";
|
|
455
|
+
messages["invalidDBIndexNX"] = "ERR invalid DB index, '%0' does not exist";
|
|
456
|
+
messages["mutuallyExclusiveNXXX"] = "ERR XX and NX options at the same time are not compatible";
|
|
457
|
+
})(messages || (messages = {}));
|
|
458
|
+
class MemoryCache extends events.EventEmitter {
|
|
459
|
+
/**
|
|
460
|
+
* Creates an instance of MemoryCache.
|
|
461
|
+
* @param {*} options
|
|
462
|
+
* @memberof MemoryCache
|
|
463
|
+
*/
|
|
464
|
+
constructor(options) {
|
|
465
|
+
super();
|
|
466
|
+
this.databases = Object.create({});
|
|
467
|
+
this.options = { ...{ database: "0" }, ...options };
|
|
468
|
+
this.currentDBIndex = 0;
|
|
469
|
+
this.connected = false;
|
|
470
|
+
this.lastSave = Date.now();
|
|
471
|
+
this.multiMode = false;
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
*
|
|
475
|
+
*
|
|
476
|
+
* @returns {*}
|
|
477
|
+
* @memberof MemoryCache
|
|
478
|
+
*/
|
|
479
|
+
createClient() {
|
|
480
|
+
this.databases[this.options.database] = Object.create({});
|
|
481
|
+
this.cache = this.databases[this.options.database];
|
|
482
|
+
this.connected = true;
|
|
483
|
+
// exit multi mode if we are in it
|
|
484
|
+
this.discard(null, true);
|
|
485
|
+
this.emit('connect');
|
|
486
|
+
this.emit('ready');
|
|
487
|
+
return this;
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
*
|
|
491
|
+
*
|
|
492
|
+
* @returns {*}
|
|
493
|
+
* @memberof MemoryCache
|
|
494
|
+
*/
|
|
495
|
+
quit() {
|
|
496
|
+
this.connected = false;
|
|
497
|
+
// exit multi mode if we are in it
|
|
498
|
+
this.discard(null, true);
|
|
499
|
+
this.emit('end');
|
|
500
|
+
return this;
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
*
|
|
504
|
+
*
|
|
505
|
+
* @returns {*}
|
|
506
|
+
* @memberof MemoryCache
|
|
507
|
+
*/
|
|
508
|
+
end() {
|
|
509
|
+
return this.quit();
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
*
|
|
513
|
+
*
|
|
514
|
+
* @param {string} message
|
|
515
|
+
* @param {Function} [callback]
|
|
516
|
+
* @returns {*}
|
|
517
|
+
* @memberof MemoryCache
|
|
518
|
+
*/
|
|
519
|
+
echo(message, callback) {
|
|
520
|
+
return this._handleCallback(callback, message);
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
*
|
|
524
|
+
*
|
|
525
|
+
* @param {string} message
|
|
526
|
+
* @param {Function} [callback]
|
|
527
|
+
* @returns {*}
|
|
528
|
+
* @memberof MemoryCache
|
|
529
|
+
*/
|
|
530
|
+
ping(message, callback) {
|
|
531
|
+
message = message || messages.pong;
|
|
532
|
+
return this._handleCallback(callback, message);
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
*
|
|
536
|
+
*
|
|
537
|
+
* @param {string} password
|
|
538
|
+
* @param {Function} [callback]
|
|
539
|
+
* @returns {*}
|
|
540
|
+
* @memberof MemoryCache
|
|
541
|
+
*/
|
|
542
|
+
auth(password, callback) {
|
|
543
|
+
return this._handleCallback(callback, messages.ok);
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
*
|
|
547
|
+
*
|
|
548
|
+
* @param {number} dbIndex
|
|
549
|
+
* @param {Function} [callback]
|
|
550
|
+
* @returns {*}
|
|
551
|
+
* @memberof MemoryCache
|
|
552
|
+
*/
|
|
553
|
+
select(dbIndex, callback) {
|
|
554
|
+
if (!helper__namespace.isNumber(dbIndex)) {
|
|
555
|
+
return this._handleCallback(callback, null, messages.invalidDBIndex);
|
|
556
|
+
}
|
|
557
|
+
if (!this.databases.hasOwnProperty(dbIndex)) {
|
|
558
|
+
this.databases[dbIndex] = Object.create({});
|
|
559
|
+
}
|
|
560
|
+
this.multiMode = false;
|
|
561
|
+
this.currentDBIndex = dbIndex;
|
|
562
|
+
this.cache = this.databases[dbIndex];
|
|
563
|
+
return this._handleCallback(callback, messages.ok);
|
|
564
|
+
}
|
|
565
|
+
// ---------------------------------------
|
|
566
|
+
// Keys
|
|
567
|
+
// ---------------------------------------
|
|
568
|
+
get(key, callback) {
|
|
569
|
+
let retVal = null;
|
|
570
|
+
if (this._hasKey(key)) {
|
|
571
|
+
this._testType(key, 'string', true, callback);
|
|
572
|
+
retVal = this._getKey(key);
|
|
573
|
+
}
|
|
574
|
+
return this._handleCallback(callback, retVal);
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* set(key, value, ttl, pttl, notexist, onlyexist, callback)
|
|
578
|
+
*
|
|
579
|
+
* @param {string} key
|
|
580
|
+
* @param {(string | number)} value
|
|
581
|
+
* @param {...any[]} params
|
|
582
|
+
* @returns {*}
|
|
583
|
+
* @memberof MemoryCache
|
|
584
|
+
*/
|
|
585
|
+
set(key, value, ...params) {
|
|
586
|
+
const retVal = null;
|
|
587
|
+
params = lodash.flatten(params);
|
|
588
|
+
const callback = this._retrieveCallback(params);
|
|
589
|
+
let ttl, pttl, notexist, onlyexist;
|
|
590
|
+
// parse parameters
|
|
591
|
+
while (params.length > 0) {
|
|
592
|
+
const param = params.shift();
|
|
593
|
+
switch (param.toString().toLowerCase()) {
|
|
594
|
+
case 'nx':
|
|
595
|
+
notexist = true;
|
|
596
|
+
break;
|
|
597
|
+
case 'xx':
|
|
598
|
+
onlyexist = true;
|
|
599
|
+
break;
|
|
600
|
+
case 'ex':
|
|
601
|
+
if (params.length === 0) {
|
|
602
|
+
return this._handleCallback(callback, null, messages.syntax);
|
|
603
|
+
}
|
|
604
|
+
ttl = parseInt(params.shift());
|
|
605
|
+
if (isNaN(ttl)) {
|
|
606
|
+
return this._handleCallback(callback, null, messages.noint);
|
|
607
|
+
}
|
|
608
|
+
break;
|
|
609
|
+
case 'px':
|
|
610
|
+
if (params.length === 0) {
|
|
611
|
+
return this._handleCallback(callback, null, messages.syntax);
|
|
612
|
+
}
|
|
613
|
+
pttl = parseInt(params.shift());
|
|
614
|
+
if (isNaN(pttl)) {
|
|
615
|
+
return this._handleCallback(callback, null, messages.noint);
|
|
616
|
+
}
|
|
617
|
+
break;
|
|
618
|
+
default:
|
|
619
|
+
return this._handleCallback(callback, null, messages.syntax);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
if (!lodash.isNil(ttl) && !lodash.isNil(pttl)) {
|
|
623
|
+
return this._handleCallback(callback, null, messages.syntax);
|
|
624
|
+
}
|
|
625
|
+
if (notexist && onlyexist) {
|
|
626
|
+
return this._handleCallback(callback, null, messages.syntax);
|
|
627
|
+
}
|
|
628
|
+
pttl = pttl || ttl * 1000 || null;
|
|
629
|
+
if (!lodash.isNil(pttl)) {
|
|
630
|
+
pttl = Date.now() + pttl;
|
|
631
|
+
}
|
|
632
|
+
if (this._hasKey(key)) {
|
|
633
|
+
this._testType(key, 'string', true, callback);
|
|
634
|
+
if (notexist) {
|
|
635
|
+
return this._handleCallback(callback, retVal);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
else if (onlyexist) {
|
|
639
|
+
return this._handleCallback(callback, retVal);
|
|
640
|
+
}
|
|
641
|
+
this.cache[key] = this._makeKey(value.toString(), 'string', pttl);
|
|
642
|
+
return this._handleCallback(callback, messages.ok);
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
*
|
|
646
|
+
*
|
|
647
|
+
* @param {string} key
|
|
648
|
+
* @param {Function} [callback]
|
|
649
|
+
* @returns {*}
|
|
650
|
+
* @memberof MemoryCache
|
|
651
|
+
*/
|
|
652
|
+
ttl(key, callback) {
|
|
653
|
+
let retVal = this.pttl(key);
|
|
654
|
+
if (retVal >= 0 || retVal <= -3) {
|
|
655
|
+
retVal = Math.floor(retVal / 1000);
|
|
656
|
+
}
|
|
657
|
+
return this._handleCallback(callback, retVal);
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
*
|
|
661
|
+
*
|
|
662
|
+
* @param {string} key
|
|
663
|
+
* @param {number} seconds
|
|
664
|
+
* @param {Function} [callback]
|
|
665
|
+
* @returns {*}
|
|
666
|
+
* @memberof MemoryCache
|
|
667
|
+
*/
|
|
668
|
+
expire(key, seconds, callback) {
|
|
669
|
+
let retVal = 0;
|
|
670
|
+
if (this._hasKey(key)) {
|
|
671
|
+
this.cache[key].timeout = Date.now() + seconds * 1000;
|
|
672
|
+
retVal = 1;
|
|
673
|
+
}
|
|
674
|
+
return this._handleCallback(callback, retVal);
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
*
|
|
678
|
+
*
|
|
679
|
+
* @param {...any[]} keys
|
|
680
|
+
* @returns {*}
|
|
681
|
+
* @memberof MemoryCache
|
|
682
|
+
*/
|
|
683
|
+
del(...keys) {
|
|
684
|
+
let retVal = 0;
|
|
685
|
+
const callback = this._retrieveCallback(keys);
|
|
686
|
+
// Flatten the array in case an array was passed
|
|
687
|
+
keys = lodash.flatten(keys);
|
|
688
|
+
for (let itr = 0; itr < keys.length; itr++) {
|
|
689
|
+
const key = keys[itr];
|
|
690
|
+
if (this._hasKey(key)) {
|
|
691
|
+
delete this.cache[key];
|
|
692
|
+
retVal++;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
return this._handleCallback(callback, retVal);
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
*
|
|
699
|
+
*
|
|
700
|
+
* @param {...any[]} keys
|
|
701
|
+
* @returns {*}
|
|
702
|
+
* @memberof MemoryCache
|
|
703
|
+
*/
|
|
704
|
+
exists(...keys) {
|
|
705
|
+
let retVal = 0;
|
|
706
|
+
const callback = this._retrieveCallback(keys);
|
|
707
|
+
for (let itr = 0; itr < keys.length; itr++) {
|
|
708
|
+
const key = keys[itr];
|
|
709
|
+
if (this._hasKey(key)) {
|
|
710
|
+
retVal++;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
return this._handleCallback(callback, retVal);
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
*
|
|
717
|
+
*
|
|
718
|
+
* @param {string} key
|
|
719
|
+
* @param {Function} [callback]
|
|
720
|
+
* @returns {*}
|
|
721
|
+
* @memberof MemoryCache
|
|
722
|
+
*/
|
|
723
|
+
incr(key, callback) {
|
|
724
|
+
let retVal = null;
|
|
725
|
+
try {
|
|
726
|
+
retVal = this._addToKey(key, 1);
|
|
727
|
+
}
|
|
728
|
+
catch (err) {
|
|
729
|
+
return this._handleCallback(callback, null, err);
|
|
730
|
+
}
|
|
731
|
+
return this._handleCallback(callback, retVal);
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
*
|
|
735
|
+
*
|
|
736
|
+
* @param {string} key
|
|
737
|
+
* @param {number} amount
|
|
738
|
+
* @param {Function} [callback]
|
|
739
|
+
* @returns {*}
|
|
740
|
+
* @memberof MemoryCache
|
|
741
|
+
*/
|
|
742
|
+
incrby(key, amount, callback) {
|
|
743
|
+
let retVal = null;
|
|
744
|
+
try {
|
|
745
|
+
retVal = this._addToKey(key, amount);
|
|
746
|
+
}
|
|
747
|
+
catch (err) {
|
|
748
|
+
return this._handleCallback(callback, null, err);
|
|
749
|
+
}
|
|
750
|
+
return this._handleCallback(callback, retVal);
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
*
|
|
754
|
+
*
|
|
755
|
+
* @param {string} key
|
|
756
|
+
* @param {Function} [callback]
|
|
757
|
+
* @returns {*}
|
|
758
|
+
* @memberof MemoryCache
|
|
759
|
+
*/
|
|
760
|
+
decr(key, callback) {
|
|
761
|
+
let retVal = null;
|
|
762
|
+
try {
|
|
763
|
+
retVal = this._addToKey(key, -1);
|
|
764
|
+
}
|
|
765
|
+
catch (err) {
|
|
766
|
+
return this._handleCallback(callback, null, err);
|
|
767
|
+
}
|
|
768
|
+
return this._handleCallback(callback, retVal);
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
*
|
|
772
|
+
*
|
|
773
|
+
* @param {string} key
|
|
774
|
+
* @param {number} amount
|
|
775
|
+
* @param {Function} [callback]
|
|
776
|
+
* @returns {*}
|
|
777
|
+
* @memberof MemoryCache
|
|
778
|
+
*/
|
|
779
|
+
decrby(key, amount, callback) {
|
|
780
|
+
let retVal = null;
|
|
781
|
+
try {
|
|
782
|
+
retVal = this._addToKey(key, -amount);
|
|
783
|
+
}
|
|
784
|
+
catch (err) {
|
|
785
|
+
return this._handleCallback(callback, null, err);
|
|
786
|
+
}
|
|
787
|
+
return this._handleCallback(callback, retVal);
|
|
788
|
+
}
|
|
789
|
+
// ---------------------------------------
|
|
790
|
+
// ## Hash ##
|
|
791
|
+
// ---------------------------------------
|
|
792
|
+
hset(key, field, value, callback) {
|
|
793
|
+
let retVal = 0;
|
|
794
|
+
if (this._hasKey(key)) {
|
|
795
|
+
this._testType(key, 'hash', true, callback);
|
|
796
|
+
}
|
|
797
|
+
else {
|
|
798
|
+
this.cache[key] = this._makeKey({}, 'hash');
|
|
799
|
+
}
|
|
800
|
+
if (!this._hasField(key, field)) {
|
|
801
|
+
retVal = 1;
|
|
802
|
+
}
|
|
803
|
+
this._setField(key, field, value.toString());
|
|
804
|
+
this.persist(key);
|
|
805
|
+
return this._handleCallback(callback, retVal);
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
*
|
|
809
|
+
*
|
|
810
|
+
* @param {string} key
|
|
811
|
+
* @param {string} field
|
|
812
|
+
* @param {Function} [callback]
|
|
813
|
+
* @returns {*}
|
|
814
|
+
* @memberof MemoryCache
|
|
815
|
+
*/
|
|
816
|
+
hget(key, field, callback) {
|
|
817
|
+
let retVal = null;
|
|
818
|
+
if (this._hasKey(key)) {
|
|
819
|
+
this._testType(key, 'hash', true, callback);
|
|
820
|
+
if (this._hasField(key, field)) {
|
|
821
|
+
retVal = this._getKey(key)[field];
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
return this._handleCallback(callback, retVal);
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
*
|
|
828
|
+
*
|
|
829
|
+
* @param {string} key
|
|
830
|
+
* @param {string} field
|
|
831
|
+
* @param {Function} [callback]
|
|
832
|
+
* @returns {*}
|
|
833
|
+
* @memberof MemoryCache
|
|
834
|
+
*/
|
|
835
|
+
hexists(key, field, callback) {
|
|
836
|
+
let retVal = 0;
|
|
837
|
+
if (this._hasKey(key)) {
|
|
838
|
+
this._testType(key, 'hash', true, callback);
|
|
839
|
+
if (this._hasField(key, field)) {
|
|
840
|
+
retVal = 1;
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
return this._handleCallback(callback, retVal);
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
*
|
|
847
|
+
*
|
|
848
|
+
* @param {string} key
|
|
849
|
+
* @param {...any[]} fields
|
|
850
|
+
* @returns {*}
|
|
851
|
+
* @memberof MemoryCache
|
|
852
|
+
*/
|
|
853
|
+
hdel(key, ...fields) {
|
|
854
|
+
let retVal = 0;
|
|
855
|
+
const callback = this._retrieveCallback(fields);
|
|
856
|
+
if (this._hasKey(key)) {
|
|
857
|
+
this._testType(key, 'hash', true, callback);
|
|
858
|
+
for (let itr = 0; itr < fields.length; itr++) {
|
|
859
|
+
const field = fields[itr];
|
|
860
|
+
if (this._hasField(key, field)) {
|
|
861
|
+
delete this.cache[key].value[field];
|
|
862
|
+
retVal++;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
return this._handleCallback(callback, retVal);
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
*
|
|
870
|
+
*
|
|
871
|
+
* @param {string} key
|
|
872
|
+
* @param {Function} [callback]
|
|
873
|
+
* @returns {*}
|
|
874
|
+
* @memberof MemoryCache
|
|
875
|
+
*/
|
|
876
|
+
hlen(key, callback) {
|
|
877
|
+
const retVal = this.hkeys(key).length;
|
|
878
|
+
return this._handleCallback(callback, retVal);
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
*
|
|
882
|
+
*
|
|
883
|
+
* @param {string} key
|
|
884
|
+
* @param {string} field
|
|
885
|
+
* @param {*} value
|
|
886
|
+
* @param {Function} [callback]
|
|
887
|
+
* @returns {*}
|
|
888
|
+
* @memberof MemoryCache
|
|
889
|
+
*/
|
|
890
|
+
hincrby(key, field, value, callback) {
|
|
891
|
+
let retVal;
|
|
892
|
+
try {
|
|
893
|
+
retVal = this._addToField(key, field, value, false);
|
|
894
|
+
}
|
|
895
|
+
catch (err) {
|
|
896
|
+
return this._handleCallback(callback, null, err);
|
|
897
|
+
}
|
|
898
|
+
return this._handleCallback(callback, retVal);
|
|
899
|
+
}
|
|
900
|
+
/**
|
|
901
|
+
*
|
|
902
|
+
*
|
|
903
|
+
* @param {string} key
|
|
904
|
+
* @param {Function} [callback]
|
|
905
|
+
* @returns {*}
|
|
906
|
+
* @memberof MemoryCache
|
|
907
|
+
*/
|
|
908
|
+
hgetall(key, callback) {
|
|
909
|
+
let retVals = {};
|
|
910
|
+
if (this._hasKey(key)) {
|
|
911
|
+
this._testType(key, 'hash', true, callback);
|
|
912
|
+
retVals = this._getKey(key);
|
|
913
|
+
}
|
|
914
|
+
return this._handleCallback(callback, retVals);
|
|
915
|
+
}
|
|
916
|
+
/**
|
|
917
|
+
*
|
|
918
|
+
*
|
|
919
|
+
* @param {string} key
|
|
920
|
+
* @param {Function} [callback]
|
|
921
|
+
* @returns {*}
|
|
922
|
+
* @memberof MemoryCache
|
|
923
|
+
*/
|
|
924
|
+
hkeys(key, callback) {
|
|
925
|
+
let retVals = [];
|
|
926
|
+
if (this._hasKey(key)) {
|
|
927
|
+
this._testType(key, 'hash', true, callback);
|
|
928
|
+
retVals = Object.keys(this._getKey(key));
|
|
929
|
+
}
|
|
930
|
+
return this._handleCallback(callback, retVals);
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
*
|
|
934
|
+
*
|
|
935
|
+
* @param {string} key
|
|
936
|
+
* @param {Function} [callback]
|
|
937
|
+
* @returns {*}
|
|
938
|
+
* @memberof MemoryCache
|
|
939
|
+
*/
|
|
940
|
+
hvals(key, callback) {
|
|
941
|
+
let retVals = [];
|
|
942
|
+
if (this._hasKey(key)) {
|
|
943
|
+
this._testType(key, 'hash', true, callback);
|
|
944
|
+
retVals = Object.values(this._getKey(key));
|
|
945
|
+
}
|
|
946
|
+
return this._handleCallback(callback, retVals);
|
|
947
|
+
}
|
|
948
|
+
// ---------------------------------------
|
|
949
|
+
// Lists (Array / Queue / Stack)
|
|
950
|
+
// ---------------------------------------
|
|
951
|
+
/**
|
|
952
|
+
*
|
|
953
|
+
*
|
|
954
|
+
* @param {string} key
|
|
955
|
+
* @param {Function} [callback]
|
|
956
|
+
* @returns {*}
|
|
957
|
+
* @memberof MemoryCache
|
|
958
|
+
*/
|
|
959
|
+
llen(key, callback) {
|
|
960
|
+
let retVal = 0;
|
|
961
|
+
if (this._hasKey(key)) {
|
|
962
|
+
this._testType(key, 'list', true, callback);
|
|
963
|
+
retVal = this._getKey(key).length || 0;
|
|
964
|
+
}
|
|
965
|
+
return this._handleCallback(callback, retVal);
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
*
|
|
969
|
+
*
|
|
970
|
+
* @param {string} key
|
|
971
|
+
* @param {(string | number)} value
|
|
972
|
+
* @param {Function} [callback]
|
|
973
|
+
* @returns {*}
|
|
974
|
+
* @memberof MemoryCache
|
|
975
|
+
*/
|
|
976
|
+
rpush(key, value, callback) {
|
|
977
|
+
let retVal = 0;
|
|
978
|
+
if (this._hasKey(key)) {
|
|
979
|
+
this._testType(key, 'list', true, callback);
|
|
980
|
+
}
|
|
981
|
+
else {
|
|
982
|
+
this.cache[key] = this._makeKey([], 'list');
|
|
983
|
+
}
|
|
984
|
+
const val = this._getKey(key);
|
|
985
|
+
val.push(value);
|
|
986
|
+
this._setKey(key, val);
|
|
987
|
+
retVal = val.length;
|
|
988
|
+
return this._handleCallback(callback, retVal);
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
*
|
|
992
|
+
*
|
|
993
|
+
* @param {string} key
|
|
994
|
+
* @param {(string | number)} value
|
|
995
|
+
* @param {Function} [callback]
|
|
996
|
+
* @returns {*}
|
|
997
|
+
* @memberof MemoryCache
|
|
998
|
+
*/
|
|
999
|
+
lpush(key, value, callback) {
|
|
1000
|
+
let retVal = 0;
|
|
1001
|
+
if (this._hasKey(key)) {
|
|
1002
|
+
this._testType(key, 'list', true, callback);
|
|
1003
|
+
}
|
|
1004
|
+
else {
|
|
1005
|
+
this.cache[key] = this._makeKey([], 'list');
|
|
1006
|
+
}
|
|
1007
|
+
const val = this._getKey(key);
|
|
1008
|
+
val.splice(0, 0, value);
|
|
1009
|
+
this._setKey(key, val);
|
|
1010
|
+
retVal = val.length;
|
|
1011
|
+
return this._handleCallback(callback, retVal);
|
|
1012
|
+
}
|
|
1013
|
+
/**
|
|
1014
|
+
*
|
|
1015
|
+
*
|
|
1016
|
+
* @param {string} key
|
|
1017
|
+
* @param {Function} [callback]
|
|
1018
|
+
* @returns {*}
|
|
1019
|
+
* @memberof MemoryCache
|
|
1020
|
+
*/
|
|
1021
|
+
lpop(key, callback) {
|
|
1022
|
+
let retVal = null;
|
|
1023
|
+
if (this._hasKey(key)) {
|
|
1024
|
+
this._testType(key, 'list', true, callback);
|
|
1025
|
+
const val = this._getKey(key);
|
|
1026
|
+
retVal = val.shift();
|
|
1027
|
+
this._setKey(key, val);
|
|
1028
|
+
}
|
|
1029
|
+
return this._handleCallback(callback, retVal);
|
|
1030
|
+
}
|
|
1031
|
+
/**
|
|
1032
|
+
*
|
|
1033
|
+
*
|
|
1034
|
+
* @param {string} key
|
|
1035
|
+
* @param {Function} [callback]
|
|
1036
|
+
* @returns {*}
|
|
1037
|
+
* @memberof MemoryCache
|
|
1038
|
+
*/
|
|
1039
|
+
rpop(key, callback) {
|
|
1040
|
+
let retVal = null;
|
|
1041
|
+
if (this._hasKey(key)) {
|
|
1042
|
+
this._testType(key, 'list', true, callback);
|
|
1043
|
+
const val = this._getKey(key);
|
|
1044
|
+
retVal = val.pop();
|
|
1045
|
+
this._setKey(key, val);
|
|
1046
|
+
}
|
|
1047
|
+
return this._handleCallback(callback, retVal);
|
|
1048
|
+
}
|
|
1049
|
+
/**
|
|
1050
|
+
*
|
|
1051
|
+
*
|
|
1052
|
+
* @param {string} key
|
|
1053
|
+
* @param {number} start
|
|
1054
|
+
* @param {number} stop
|
|
1055
|
+
* @param {Function} [callback]
|
|
1056
|
+
* @returns {*}
|
|
1057
|
+
* @memberof MemoryCache
|
|
1058
|
+
*/
|
|
1059
|
+
lrange(key, start, stop, callback) {
|
|
1060
|
+
const retVal = [];
|
|
1061
|
+
if (this._hasKey(key)) {
|
|
1062
|
+
this._testType(key, 'list', true, callback);
|
|
1063
|
+
const val = this._getKey(key);
|
|
1064
|
+
const length = val.length;
|
|
1065
|
+
if (stop < 0) {
|
|
1066
|
+
stop = length + stop;
|
|
1067
|
+
}
|
|
1068
|
+
if (start < 0) {
|
|
1069
|
+
start = length + start;
|
|
1070
|
+
}
|
|
1071
|
+
if (start < 0) {
|
|
1072
|
+
start = 0;
|
|
1073
|
+
}
|
|
1074
|
+
if (stop >= length) {
|
|
1075
|
+
stop = length - 1;
|
|
1076
|
+
}
|
|
1077
|
+
if (stop >= 0 && stop >= start) {
|
|
1078
|
+
const size = stop - start + 1;
|
|
1079
|
+
for (let itr = start; itr < size; itr++) {
|
|
1080
|
+
retVal.push(val[itr]);
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
return this._handleCallback(callback, retVal);
|
|
1085
|
+
}
|
|
1086
|
+
// ---------------------------------------
|
|
1087
|
+
// ## Sets (Unique Lists)##
|
|
1088
|
+
// ---------------------------------------
|
|
1089
|
+
/**
|
|
1090
|
+
*
|
|
1091
|
+
*
|
|
1092
|
+
* @param {string} key
|
|
1093
|
+
* @param {...any[]} members
|
|
1094
|
+
* @returns {*}
|
|
1095
|
+
* @memberof MemoryCache
|
|
1096
|
+
*/
|
|
1097
|
+
sadd(key, ...members) {
|
|
1098
|
+
let retVal = 0;
|
|
1099
|
+
const callback = this._retrieveCallback(members);
|
|
1100
|
+
if (this._hasKey(key)) {
|
|
1101
|
+
this._testType(key, 'set', true, callback);
|
|
1102
|
+
}
|
|
1103
|
+
else {
|
|
1104
|
+
this.cache[key] = this._makeKey([], 'set');
|
|
1105
|
+
}
|
|
1106
|
+
const val = this._getKey(key);
|
|
1107
|
+
const length = val.length;
|
|
1108
|
+
const nval = lodash.union(val, members);
|
|
1109
|
+
const newlength = nval.length;
|
|
1110
|
+
retVal = newlength - length;
|
|
1111
|
+
this._setKey(key, nval);
|
|
1112
|
+
return this._handleCallback(callback, retVal);
|
|
1113
|
+
}
|
|
1114
|
+
/**
|
|
1115
|
+
*
|
|
1116
|
+
*
|
|
1117
|
+
* @param {string} key
|
|
1118
|
+
* @param {Function} [callback]
|
|
1119
|
+
* @returns {*}
|
|
1120
|
+
* @memberof MemoryCache
|
|
1121
|
+
*/
|
|
1122
|
+
scard(key, callback) {
|
|
1123
|
+
let retVal = 0;
|
|
1124
|
+
if (this._hasKey(key)) {
|
|
1125
|
+
this._testType(key, 'set', true, callback);
|
|
1126
|
+
retVal = this._getKey(key).length;
|
|
1127
|
+
}
|
|
1128
|
+
return this._handleCallback(callback, retVal);
|
|
1129
|
+
}
|
|
1130
|
+
/**
|
|
1131
|
+
*
|
|
1132
|
+
*
|
|
1133
|
+
* @param {string} key
|
|
1134
|
+
* @param {string} member
|
|
1135
|
+
* @param {Function} [callback]
|
|
1136
|
+
* @returns {*}
|
|
1137
|
+
* @memberof MemoryCache
|
|
1138
|
+
*/
|
|
1139
|
+
sismember(key, member, callback) {
|
|
1140
|
+
let retVal = 0;
|
|
1141
|
+
if (this._hasKey(key)) {
|
|
1142
|
+
this._testType(key, 'set', true, callback);
|
|
1143
|
+
const val = this._getKey(key);
|
|
1144
|
+
if (val.includes(member)) {
|
|
1145
|
+
retVal = 1;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
return this._handleCallback(callback, retVal);
|
|
1149
|
+
}
|
|
1150
|
+
/**
|
|
1151
|
+
*
|
|
1152
|
+
*
|
|
1153
|
+
* @param {string} key
|
|
1154
|
+
* @param {Function} [callback]
|
|
1155
|
+
* @returns {*}
|
|
1156
|
+
* @memberof MemoryCache
|
|
1157
|
+
*/
|
|
1158
|
+
smembers(key, callback) {
|
|
1159
|
+
let retVal = [];
|
|
1160
|
+
if (this._hasKey(key)) {
|
|
1161
|
+
this._testType(key, 'set', true, callback);
|
|
1162
|
+
retVal = this._getKey(key);
|
|
1163
|
+
}
|
|
1164
|
+
return this._handleCallback(callback, retVal);
|
|
1165
|
+
}
|
|
1166
|
+
/**
|
|
1167
|
+
*
|
|
1168
|
+
*
|
|
1169
|
+
* @param {string} key
|
|
1170
|
+
* @param {number} [count]
|
|
1171
|
+
* @param {Function} [callback]
|
|
1172
|
+
* @returns {*}
|
|
1173
|
+
* @memberof MemoryCache
|
|
1174
|
+
*/
|
|
1175
|
+
spop(key, count, callback) {
|
|
1176
|
+
let retVal = null;
|
|
1177
|
+
count = count || 1;
|
|
1178
|
+
if (isNaN(count)) {
|
|
1179
|
+
return this._handleCallback(callback, null, messages.noint);
|
|
1180
|
+
}
|
|
1181
|
+
if (this._hasKey(key)) {
|
|
1182
|
+
retVal = [];
|
|
1183
|
+
this._testType(key, 'set', true, callback);
|
|
1184
|
+
const val = this._getKey(key);
|
|
1185
|
+
const length = val.length;
|
|
1186
|
+
count = count > length ? length : count;
|
|
1187
|
+
for (let itr = 0; itr < count; itr++) {
|
|
1188
|
+
retVal.push(val.pop());
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
return this._handleCallback(callback, retVal);
|
|
1192
|
+
}
|
|
1193
|
+
/**
|
|
1194
|
+
*
|
|
1195
|
+
*
|
|
1196
|
+
* @param {string} key
|
|
1197
|
+
* @param {...any[]} members
|
|
1198
|
+
* @returns {*}
|
|
1199
|
+
* @memberof MemoryCache
|
|
1200
|
+
*/
|
|
1201
|
+
srem(key, ...members) {
|
|
1202
|
+
let retVal = 0;
|
|
1203
|
+
const callback = this._retrieveCallback(members);
|
|
1204
|
+
if (this._hasKey(key)) {
|
|
1205
|
+
this._testType(key, 'set', true, callback);
|
|
1206
|
+
const val = this._getKey(key);
|
|
1207
|
+
for (const index in members) {
|
|
1208
|
+
if (members.hasOwnProperty(index)) {
|
|
1209
|
+
const member = members[index];
|
|
1210
|
+
const idx = val.indexOf(member);
|
|
1211
|
+
if (idx !== -1) {
|
|
1212
|
+
val.splice(idx, 1);
|
|
1213
|
+
retVal++;
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
this._setKey(key, val);
|
|
1218
|
+
}
|
|
1219
|
+
return this._handleCallback(callback, retVal);
|
|
1220
|
+
}
|
|
1221
|
+
/**
|
|
1222
|
+
*
|
|
1223
|
+
*
|
|
1224
|
+
* @param {string} sourcekey
|
|
1225
|
+
* @param {string} destkey
|
|
1226
|
+
* @param {string} member
|
|
1227
|
+
* @param {Function} [callback]
|
|
1228
|
+
* @returns {*}
|
|
1229
|
+
* @memberof MemoryCache
|
|
1230
|
+
*/
|
|
1231
|
+
smove(sourcekey, destkey, member, callback) {
|
|
1232
|
+
let retVal = 0;
|
|
1233
|
+
if (this._hasKey(sourcekey)) {
|
|
1234
|
+
this._testType(sourcekey, 'set', true, callback);
|
|
1235
|
+
const val = this._getKey(sourcekey);
|
|
1236
|
+
const idx = val.indexOf(member);
|
|
1237
|
+
if (idx !== -1) {
|
|
1238
|
+
this.sadd(destkey, member);
|
|
1239
|
+
val.splice(idx, 1);
|
|
1240
|
+
retVal = 1;
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
return this._handleCallback(callback, retVal);
|
|
1244
|
+
}
|
|
1245
|
+
// ---------------------------------------
|
|
1246
|
+
// ## Transactions (Atomic) ##
|
|
1247
|
+
// ---------------------------------------
|
|
1248
|
+
// TODO: Transaction Queues watch and unwatch
|
|
1249
|
+
// https://redis.io/topics/transactions
|
|
1250
|
+
// This can be accomplished by temporarily swapping this.cache to a temporary copy of the current statement
|
|
1251
|
+
// holding and then using __.merge on actual this.cache with the temp storage.
|
|
1252
|
+
discard(callback, silent) {
|
|
1253
|
+
// Clear the queue mode, drain the queue, empty the watch list
|
|
1254
|
+
if (this.multiMode) {
|
|
1255
|
+
this.cache = this.databases[this.currentDBIndex];
|
|
1256
|
+
this.tempCache = {};
|
|
1257
|
+
this.multiMode = false;
|
|
1258
|
+
this.responseMessages = [];
|
|
1259
|
+
}
|
|
1260
|
+
else if (!silent) {
|
|
1261
|
+
return this._handleCallback(callback, null, messages.nomultidiscard);
|
|
1262
|
+
}
|
|
1263
|
+
return this._handleCallback(callback, messages.ok);
|
|
1264
|
+
}
|
|
1265
|
+
// ---------------------------------------
|
|
1266
|
+
// ## Internal - Key ##
|
|
1267
|
+
// ---------------------------------------
|
|
1268
|
+
/**
|
|
1269
|
+
*
|
|
1270
|
+
*
|
|
1271
|
+
* @param {string} key
|
|
1272
|
+
* @param {Function} [callback]
|
|
1273
|
+
* @returns {*}
|
|
1274
|
+
* @memberof MemoryCache
|
|
1275
|
+
*/
|
|
1276
|
+
pttl(key, callback) {
|
|
1277
|
+
let retVal = -2;
|
|
1278
|
+
if (this._hasKey(key)) {
|
|
1279
|
+
if (!lodash.isNil(this.cache[key].timeout)) {
|
|
1280
|
+
retVal = this.cache[key].timeout - Date.now();
|
|
1281
|
+
// Prevent unexpected errors if the actual ttl just happens to be -2 or -1
|
|
1282
|
+
if (retVal < 0 && retVal > -3) {
|
|
1283
|
+
retVal = -3;
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
else {
|
|
1287
|
+
retVal = -1;
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
return this._handleCallback(callback, retVal);
|
|
1291
|
+
}
|
|
1292
|
+
/**
|
|
1293
|
+
*
|
|
1294
|
+
*
|
|
1295
|
+
* @private
|
|
1296
|
+
* @param {string} key
|
|
1297
|
+
* @param {Function} [callback]
|
|
1298
|
+
* @returns {*}
|
|
1299
|
+
* @memberof MemoryCache
|
|
1300
|
+
*/
|
|
1301
|
+
persist(key, callback) {
|
|
1302
|
+
let retVal = 0;
|
|
1303
|
+
if (this._hasKey(key)) {
|
|
1304
|
+
if (!lodash.isNil(this._key(key).timeout)) {
|
|
1305
|
+
this._key(key).timeout = null;
|
|
1306
|
+
retVal = 1;
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
return this._handleCallback(callback, retVal);
|
|
1310
|
+
}
|
|
1311
|
+
/**
|
|
1312
|
+
*
|
|
1313
|
+
*
|
|
1314
|
+
* @private
|
|
1315
|
+
* @param {string} key
|
|
1316
|
+
* @returns {*} {boolean}
|
|
1317
|
+
* @memberof MemoryCache
|
|
1318
|
+
*/
|
|
1319
|
+
_hasKey(key) {
|
|
1320
|
+
return this.cache.hasOwnProperty(key);
|
|
1321
|
+
}
|
|
1322
|
+
/**
|
|
1323
|
+
*
|
|
1324
|
+
*
|
|
1325
|
+
* @private
|
|
1326
|
+
* @param {*} value
|
|
1327
|
+
* @param {string} type
|
|
1328
|
+
* @param {number} timeout
|
|
1329
|
+
* @returns {*}
|
|
1330
|
+
* @memberof MemoryCache
|
|
1331
|
+
*/
|
|
1332
|
+
_makeKey(value, type, timeout) {
|
|
1333
|
+
return { value: value, type: type, timeout: timeout || null, lastAccess: Date.now() };
|
|
1334
|
+
}
|
|
1335
|
+
/**
|
|
1336
|
+
*
|
|
1337
|
+
*
|
|
1338
|
+
* @private
|
|
1339
|
+
* @param {string} key
|
|
1340
|
+
* @returns {*}
|
|
1341
|
+
* @memberof MemoryCache
|
|
1342
|
+
*/
|
|
1343
|
+
_key(key) {
|
|
1344
|
+
this.cache[key].lastAccess = Date.now();
|
|
1345
|
+
return this.cache[key];
|
|
1346
|
+
}
|
|
1347
|
+
/**
|
|
1348
|
+
*
|
|
1349
|
+
*
|
|
1350
|
+
* @private
|
|
1351
|
+
* @param {string} key
|
|
1352
|
+
* @param {number} amount
|
|
1353
|
+
* @param {Function} [callback]
|
|
1354
|
+
* @returns {*}
|
|
1355
|
+
* @memberof MemoryCache
|
|
1356
|
+
*/
|
|
1357
|
+
_addToKey(key, amount, callback) {
|
|
1358
|
+
let keyValue = 0;
|
|
1359
|
+
if (isNaN(amount) || lodash.isNil(amount)) {
|
|
1360
|
+
return this._handleCallback(callback, null, messages.noint);
|
|
1361
|
+
}
|
|
1362
|
+
if (this._hasKey(key)) {
|
|
1363
|
+
this._testType(key, 'string', true, callback);
|
|
1364
|
+
keyValue = parseInt(this._getKey(key));
|
|
1365
|
+
if (isNaN(keyValue) || lodash.isNil(keyValue)) {
|
|
1366
|
+
return this._handleCallback(callback, null, messages.noint);
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
else {
|
|
1370
|
+
this.cache[key] = this._makeKey('0', 'string');
|
|
1371
|
+
}
|
|
1372
|
+
const val = keyValue + amount;
|
|
1373
|
+
this._setKey(key, val.toString());
|
|
1374
|
+
return val;
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
*
|
|
1378
|
+
*
|
|
1379
|
+
* @private
|
|
1380
|
+
* @param {string} key
|
|
1381
|
+
* @param {string} type
|
|
1382
|
+
* @param {boolean} [throwError]
|
|
1383
|
+
* @param {Function} [callback]
|
|
1384
|
+
* @returns {*}
|
|
1385
|
+
* @memberof MemoryCache
|
|
1386
|
+
*/
|
|
1387
|
+
_testType(key, type, throwError, callback) {
|
|
1388
|
+
throwError = !!throwError;
|
|
1389
|
+
const keyType = this._key(key).type;
|
|
1390
|
+
if (keyType !== type) {
|
|
1391
|
+
if (throwError) {
|
|
1392
|
+
return this._handleCallback(callback, null, messages.wrongTypeOp);
|
|
1393
|
+
}
|
|
1394
|
+
return false;
|
|
1395
|
+
}
|
|
1396
|
+
return true;
|
|
1397
|
+
}
|
|
1398
|
+
/**
|
|
1399
|
+
*
|
|
1400
|
+
*
|
|
1401
|
+
* @private
|
|
1402
|
+
* @param {string} key
|
|
1403
|
+
* @returns {*}
|
|
1404
|
+
* @memberof MemoryCache
|
|
1405
|
+
*/
|
|
1406
|
+
_getKey(key) {
|
|
1407
|
+
const _key = this._key(key) || {};
|
|
1408
|
+
if (_key.timeout && _key.timeout <= Date.now()) {
|
|
1409
|
+
this.del(key);
|
|
1410
|
+
return null;
|
|
1411
|
+
}
|
|
1412
|
+
return _key.value;
|
|
1413
|
+
}
|
|
1414
|
+
/**
|
|
1415
|
+
*
|
|
1416
|
+
*
|
|
1417
|
+
* @private
|
|
1418
|
+
* @param {string} key
|
|
1419
|
+
* @param {(number | string)} value
|
|
1420
|
+
* @memberof MemoryCache
|
|
1421
|
+
*/
|
|
1422
|
+
_setKey(key, value) {
|
|
1423
|
+
this.cache[key].value = value;
|
|
1424
|
+
this.cache[key].lastAccess = Date.now();
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
*
|
|
1428
|
+
*
|
|
1429
|
+
* @private
|
|
1430
|
+
* @param {string} key
|
|
1431
|
+
* @param {string} field
|
|
1432
|
+
* @param {number} [amount]
|
|
1433
|
+
* @param {boolean} [useFloat]
|
|
1434
|
+
* @param {Function} [callback]
|
|
1435
|
+
* @returns {*}
|
|
1436
|
+
* @memberof MemoryCache
|
|
1437
|
+
*/
|
|
1438
|
+
_addToField(key, field, amount, useFloat, callback) {
|
|
1439
|
+
useFloat = useFloat || false;
|
|
1440
|
+
let fieldValue = useFloat ? 0.0 : 0;
|
|
1441
|
+
let value = 0;
|
|
1442
|
+
if (isNaN(amount) || lodash.isNil(amount)) {
|
|
1443
|
+
return this._handleCallback(callback, null, useFloat ? messages.nofloat : messages.noint);
|
|
1444
|
+
}
|
|
1445
|
+
if (this._hasKey(key)) {
|
|
1446
|
+
this._testType(key, 'hash', true, callback);
|
|
1447
|
+
if (this._hasField(key, field)) {
|
|
1448
|
+
value = this._getField(key, field);
|
|
1449
|
+
}
|
|
1450
|
+
}
|
|
1451
|
+
else {
|
|
1452
|
+
this.cache[key] = this._makeKey({}, 'hash');
|
|
1453
|
+
}
|
|
1454
|
+
fieldValue = useFloat ? parseFloat(`${value}`) : parseInt(`${value}`);
|
|
1455
|
+
amount = useFloat ? parseFloat(`${amount}`) : parseInt(`${amount}`);
|
|
1456
|
+
if (isNaN(fieldValue) || lodash.isNil(fieldValue)) {
|
|
1457
|
+
return this._handleCallback(callback, null, useFloat ? messages.nofloat : messages.noint);
|
|
1458
|
+
}
|
|
1459
|
+
fieldValue += amount;
|
|
1460
|
+
this._setField(key, field, fieldValue.toString());
|
|
1461
|
+
return fieldValue;
|
|
1462
|
+
}
|
|
1463
|
+
/**
|
|
1464
|
+
*
|
|
1465
|
+
*
|
|
1466
|
+
* @private
|
|
1467
|
+
* @param {string} key
|
|
1468
|
+
* @param {string} field
|
|
1469
|
+
* @returns {*}
|
|
1470
|
+
* @memberof MemoryCache
|
|
1471
|
+
*/
|
|
1472
|
+
_getField(key, field) {
|
|
1473
|
+
return this._getKey(key)[field];
|
|
1474
|
+
}
|
|
1475
|
+
/**
|
|
1476
|
+
*
|
|
1477
|
+
*
|
|
1478
|
+
* @private
|
|
1479
|
+
* @param {string} key
|
|
1480
|
+
* @param {string} field
|
|
1481
|
+
* @returns {*} {boolean}
|
|
1482
|
+
* @memberof MemoryCache
|
|
1483
|
+
*/
|
|
1484
|
+
_hasField(key, field) {
|
|
1485
|
+
let retVal = false;
|
|
1486
|
+
if (key && field) {
|
|
1487
|
+
const ky = this._getKey(key);
|
|
1488
|
+
if (ky) {
|
|
1489
|
+
retVal = ky.hasOwnProperty(field);
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
return retVal;
|
|
1493
|
+
}
|
|
1494
|
+
/**
|
|
1495
|
+
*
|
|
1496
|
+
*
|
|
1497
|
+
* @param {string} key
|
|
1498
|
+
* @param {string} field
|
|
1499
|
+
* @param {*} value
|
|
1500
|
+
* @memberof MemoryCache
|
|
1501
|
+
*/
|
|
1502
|
+
_setField(key, field, value) {
|
|
1503
|
+
this._getKey(key)[field] = value;
|
|
1504
|
+
}
|
|
1505
|
+
/**
|
|
1506
|
+
*
|
|
1507
|
+
*
|
|
1508
|
+
* @private
|
|
1509
|
+
* @param {Function} [callback]
|
|
1510
|
+
* @param {(any)} [message]
|
|
1511
|
+
* @param {*} [error]
|
|
1512
|
+
* @param {boolean} [nolog]
|
|
1513
|
+
* @returns {*}
|
|
1514
|
+
* @memberof MemoryCache
|
|
1515
|
+
*/
|
|
1516
|
+
_handleCallback(callback, message, error, nolog) {
|
|
1517
|
+
let err = error;
|
|
1518
|
+
let msg = message;
|
|
1519
|
+
nolog = lodash.isNil(nolog) ? true : nolog;
|
|
1520
|
+
if (nolog) {
|
|
1521
|
+
err = this._logReturn(error);
|
|
1522
|
+
msg = this._logReturn(message);
|
|
1523
|
+
}
|
|
1524
|
+
if (typeof callback === 'function') {
|
|
1525
|
+
callback(err, msg);
|
|
1526
|
+
return;
|
|
1527
|
+
}
|
|
1528
|
+
if (err) {
|
|
1529
|
+
throw new Error(err);
|
|
1530
|
+
}
|
|
1531
|
+
return msg;
|
|
1532
|
+
}
|
|
1533
|
+
_logReturn(message) {
|
|
1534
|
+
if (!lodash.isUndefined(message)) {
|
|
1535
|
+
if (this.multiMode) {
|
|
1536
|
+
if (!lodash.isNil(this.responseMessages)) {
|
|
1537
|
+
this.responseMessages.push(message);
|
|
1538
|
+
if (message === messages.ok) {
|
|
1539
|
+
message = messages.queued;
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
return message;
|
|
1544
|
+
}
|
|
1545
|
+
return;
|
|
1546
|
+
}
|
|
1547
|
+
/**
|
|
1548
|
+
*
|
|
1549
|
+
*
|
|
1550
|
+
* @private
|
|
1551
|
+
* @param {any[]} [params]
|
|
1552
|
+
* @returns {*}
|
|
1553
|
+
* @memberof MemoryCache
|
|
1554
|
+
*/
|
|
1555
|
+
_retrieveCallback(params) {
|
|
1556
|
+
if (Array.isArray(params) && params.length > 0 && typeof params[params.length - 1] === 'function') {
|
|
1557
|
+
return params.pop();
|
|
1558
|
+
}
|
|
1559
|
+
return;
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
// const MemoryCache = require('@outofsync/memory-cache');
|
|
1564
|
+
/*
|
|
1565
|
+
* @Description:
|
|
1566
|
+
* @Usage:
|
|
1567
|
+
* @Author: richen
|
|
1568
|
+
* @Date: 2021-06-29 19:07:57
|
|
1569
|
+
* @LastEditTime: 2021-12-02 15:30:12
|
|
1570
|
+
*/
|
|
1571
|
+
class MemoryStore extends CacheStore {
|
|
1572
|
+
/**
|
|
1573
|
+
* Creates an instance of MemoryStore.
|
|
1574
|
+
* @param {StoreOptions} options
|
|
1575
|
+
* @memberof MemoryStore
|
|
1576
|
+
*/
|
|
1577
|
+
constructor(options) {
|
|
1578
|
+
super(options);
|
|
1579
|
+
this.options = options;
|
|
1580
|
+
this.client = null;
|
|
1581
|
+
}
|
|
1582
|
+
/**
|
|
1583
|
+
* getConnection
|
|
1584
|
+
*
|
|
1585
|
+
* @returns {*}
|
|
1586
|
+
* @memberof MemoryStore
|
|
1587
|
+
*/
|
|
1588
|
+
getConnection() {
|
|
1589
|
+
if (!this.pool) {
|
|
1590
|
+
this.pool = new MemoryCache({
|
|
1591
|
+
database: this.options.db
|
|
1592
|
+
});
|
|
1593
|
+
}
|
|
1594
|
+
if (!this.client) {
|
|
1595
|
+
this.client = this.pool.createClient();
|
|
1596
|
+
this.client.status = "ready";
|
|
1597
|
+
}
|
|
1598
|
+
return this.client;
|
|
1599
|
+
}
|
|
1600
|
+
/**
|
|
1601
|
+
* close
|
|
1602
|
+
*
|
|
1603
|
+
* @returns {*} {Promise<void>}
|
|
1604
|
+
* @memberof MemoryStore
|
|
1605
|
+
*/
|
|
1606
|
+
async close() {
|
|
1607
|
+
this.client.end();
|
|
1608
|
+
this.client = null;
|
|
1609
|
+
}
|
|
1610
|
+
/**
|
|
1611
|
+
* release
|
|
1612
|
+
*
|
|
1613
|
+
* @param {*} conn
|
|
1614
|
+
* @returns {*} {Promise<void>}
|
|
1615
|
+
* @memberof MemoryStore
|
|
1616
|
+
*/
|
|
1617
|
+
async release(conn) {
|
|
1618
|
+
return;
|
|
1619
|
+
}
|
|
1620
|
+
/**
|
|
1621
|
+
* defineCommand
|
|
1622
|
+
*
|
|
1623
|
+
* @param {string} name
|
|
1624
|
+
* @param {*} scripts
|
|
1625
|
+
* @memberof MemoryStore
|
|
1626
|
+
*/
|
|
1627
|
+
async defineCommand(name, scripts) {
|
|
1628
|
+
throw new Error(messages.unsupported);
|
|
1629
|
+
}
|
|
1630
|
+
/**
|
|
1631
|
+
* get and compare value
|
|
1632
|
+
*
|
|
1633
|
+
* @param {string} name
|
|
1634
|
+
* @param {(string | number)} value
|
|
1635
|
+
* @returns {*} {Promise<any>}
|
|
1636
|
+
* @memberof MemoryStore
|
|
1637
|
+
*/
|
|
1638
|
+
async getCompare(name, value) {
|
|
1639
|
+
const client = this.getConnection();
|
|
1640
|
+
const val = client.get(`${this.options.keyPrefix}${name}`);
|
|
1641
|
+
if (!val) {
|
|
1642
|
+
return 0;
|
|
1643
|
+
}
|
|
1644
|
+
else if (val == value) {
|
|
1645
|
+
return client.del(`${this.options.keyPrefix}${name}`);
|
|
1646
|
+
}
|
|
1647
|
+
else {
|
|
1648
|
+
return -1;
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
/*
|
|
1654
|
+
* @Author: richen
|
|
1655
|
+
* @Date: 2020-11-30 15:56:08
|
|
1656
|
+
* @LastEditors: Please set LastEditors
|
|
1657
|
+
* @LastEditTime: 2021-12-02 15:30:11
|
|
1658
|
+
* @License: BSD (3-Clause)
|
|
1659
|
+
* @Copyright (c) - <richenlin(at)gmail.com>
|
|
1660
|
+
*/
|
|
1661
|
+
/**
|
|
1662
|
+
*
|
|
1663
|
+
*
|
|
1664
|
+
* @export
|
|
1665
|
+
* @class RedisStore
|
|
1666
|
+
*/
|
|
1667
|
+
class RedisStore extends CacheStore {
|
|
1668
|
+
/**
|
|
1669
|
+
* Creates an instance of RedisStore.
|
|
1670
|
+
* @param {StoreOptions} options
|
|
1671
|
+
* @memberof RedisStore
|
|
1672
|
+
*/
|
|
1673
|
+
constructor(options) {
|
|
1674
|
+
super(options);
|
|
1675
|
+
this.options = this.parseOpt(options);
|
|
1676
|
+
this.pool = null;
|
|
1677
|
+
this.client = null;
|
|
1678
|
+
}
|
|
1679
|
+
// parseOpt
|
|
1680
|
+
parseOpt(options) {
|
|
1681
|
+
const opt = {
|
|
1682
|
+
host: options.host || '127.0.0.1',
|
|
1683
|
+
port: options.port || 3306,
|
|
1684
|
+
username: options.username || "",
|
|
1685
|
+
password: options.password || "",
|
|
1686
|
+
db: options.db || 0,
|
|
1687
|
+
timeout: options.timeout,
|
|
1688
|
+
keyPrefix: options.keyPrefix || '',
|
|
1689
|
+
poolSize: options.poolSize || 10,
|
|
1690
|
+
connectTimeout: options.connectTimeout || 500,
|
|
1691
|
+
};
|
|
1692
|
+
if (helper__namespace.isArray(options.host)) {
|
|
1693
|
+
const hosts = [];
|
|
1694
|
+
for (let i = 0; i < options.host.length; i++) {
|
|
1695
|
+
const h = options.host[i];
|
|
1696
|
+
if (!helper__namespace.isEmpty(options.host[i])) {
|
|
1697
|
+
let p;
|
|
1698
|
+
if (helper__namespace.isArray(options.port)) {
|
|
1699
|
+
p = options.port[i];
|
|
1700
|
+
}
|
|
1701
|
+
else {
|
|
1702
|
+
p = options.port || 6379;
|
|
1703
|
+
}
|
|
1704
|
+
hosts.push({
|
|
1705
|
+
host: h,
|
|
1706
|
+
port: helper__namespace.toNumber(p),
|
|
1707
|
+
});
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
// sentinel
|
|
1711
|
+
if (!helper__namespace.isEmpty(options.name)) {
|
|
1712
|
+
opt.host = "";
|
|
1713
|
+
opt.port = null;
|
|
1714
|
+
opt.sentinels = [...hosts];
|
|
1715
|
+
opt.sentinelUsername = options.username;
|
|
1716
|
+
opt.sentinelPassword = options.password;
|
|
1717
|
+
}
|
|
1718
|
+
else {
|
|
1719
|
+
// cluster
|
|
1720
|
+
opt.host = "";
|
|
1721
|
+
opt.port = null;
|
|
1722
|
+
opt.clusters = [...hosts];
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
return opt;
|
|
1726
|
+
}
|
|
1727
|
+
/**
|
|
1728
|
+
* create connection by native
|
|
1729
|
+
*
|
|
1730
|
+
* @param {number} [connNum=0]
|
|
1731
|
+
* @returns {*} {Promise<IORedis.Redis | IORedis.Cluster>}
|
|
1732
|
+
* @memberof RedisStore
|
|
1733
|
+
*/
|
|
1734
|
+
async connect(connNum = 0) {
|
|
1735
|
+
if (this.client && this.client.status === 'ready') {
|
|
1736
|
+
return this.client;
|
|
1737
|
+
}
|
|
1738
|
+
const defer = helper__namespace.getDefer();
|
|
1739
|
+
let connection;
|
|
1740
|
+
if (!helper__namespace.isEmpty(this.options.clusters)) {
|
|
1741
|
+
connection = new IORedis__default["default"].Cluster([...this.options.clusters], { redisOptions: this.options });
|
|
1742
|
+
}
|
|
1743
|
+
else {
|
|
1744
|
+
connection = new IORedis__default["default"](this.options);
|
|
1745
|
+
}
|
|
1746
|
+
connection.on('end', () => {
|
|
1747
|
+
if (connNum < 3) {
|
|
1748
|
+
connNum++;
|
|
1749
|
+
defer.resolve(this.connect(connNum));
|
|
1750
|
+
}
|
|
1751
|
+
else {
|
|
1752
|
+
this.close();
|
|
1753
|
+
defer.reject('redis connection end');
|
|
1754
|
+
}
|
|
1755
|
+
});
|
|
1756
|
+
connection.on('ready', () => {
|
|
1757
|
+
this.client = connection;
|
|
1758
|
+
defer.resolve(connection);
|
|
1759
|
+
});
|
|
1760
|
+
return defer.promise;
|
|
1761
|
+
}
|
|
1762
|
+
/**
|
|
1763
|
+
* get connection from pool
|
|
1764
|
+
*
|
|
1765
|
+
* @returns {*}
|
|
1766
|
+
* @memberof RedisStore
|
|
1767
|
+
*/
|
|
1768
|
+
getConnection() {
|
|
1769
|
+
if (!this.pool || !this.pool.acquire) {
|
|
1770
|
+
const factory = {
|
|
1771
|
+
create: () => {
|
|
1772
|
+
return this.connect();
|
|
1773
|
+
},
|
|
1774
|
+
destroy: () => {
|
|
1775
|
+
return this.close();
|
|
1776
|
+
},
|
|
1777
|
+
validate: (resource) => {
|
|
1778
|
+
return Promise.resolve(resource.status === 'ready');
|
|
1779
|
+
}
|
|
1780
|
+
};
|
|
1781
|
+
this.pool = genericPool__default["default"].createPool(factory, {
|
|
1782
|
+
max: this.options.poolSize || 10,
|
|
1783
|
+
min: 2 // minimum size of the pool
|
|
1784
|
+
});
|
|
1785
|
+
this.pool.on('factoryCreateError', function (err) {
|
|
1786
|
+
koatty_logger.DefaultLogger.Error(err);
|
|
1787
|
+
});
|
|
1788
|
+
this.pool.on('factoryDestroyError', function (err) {
|
|
1789
|
+
koatty_logger.DefaultLogger.Error(err);
|
|
1790
|
+
});
|
|
1791
|
+
}
|
|
1792
|
+
return this.pool.acquire();
|
|
1793
|
+
}
|
|
1794
|
+
/**
|
|
1795
|
+
* close connection
|
|
1796
|
+
*
|
|
1797
|
+
* @returns {*}
|
|
1798
|
+
* @memberof RedisStore
|
|
1799
|
+
*/
|
|
1800
|
+
async close() {
|
|
1801
|
+
this.client.disconnect();
|
|
1802
|
+
this.client = null;
|
|
1803
|
+
this.pool.destroy(this.client);
|
|
1804
|
+
this.pool = null;
|
|
1805
|
+
return;
|
|
1806
|
+
}
|
|
1807
|
+
/**
|
|
1808
|
+
*
|
|
1809
|
+
*
|
|
1810
|
+
* @param {*} conn
|
|
1811
|
+
* @returns {*}
|
|
1812
|
+
* @memberof RedisStore
|
|
1813
|
+
*/
|
|
1814
|
+
async release(conn) {
|
|
1815
|
+
if (this.pool.isBorrowedResource(conn)) {
|
|
1816
|
+
return this.pool.release(conn);
|
|
1817
|
+
}
|
|
1818
|
+
return Promise.resolve();
|
|
1819
|
+
}
|
|
1820
|
+
/**
|
|
1821
|
+
* defineCommand
|
|
1822
|
+
*
|
|
1823
|
+
* @param {string} name
|
|
1824
|
+
* @param {{ numberOfKeys?: number; lua?: string; }} scripts
|
|
1825
|
+
* @returns {*}
|
|
1826
|
+
* @memberof RedisStore
|
|
1827
|
+
*/
|
|
1828
|
+
async defineCommand(name, scripts) {
|
|
1829
|
+
const conn = await this.getConnection();
|
|
1830
|
+
if (!conn[name]) {
|
|
1831
|
+
conn.defineCommand(name, scripts);
|
|
1832
|
+
}
|
|
1833
|
+
return conn;
|
|
1834
|
+
}
|
|
1835
|
+
/**
|
|
1836
|
+
* get and compare value
|
|
1837
|
+
*
|
|
1838
|
+
* @param {string} name
|
|
1839
|
+
* @param {(string | number)} value
|
|
1840
|
+
* @returns {*} {Promise<any>}
|
|
1841
|
+
* @memberof RedisStore
|
|
1842
|
+
*/
|
|
1843
|
+
async getCompare(name, value) {
|
|
1844
|
+
let conn;
|
|
1845
|
+
try {
|
|
1846
|
+
conn = await this.defineCommand("getCompare", {
|
|
1847
|
+
numberOfKeys: 1,
|
|
1848
|
+
lua: `
|
|
1849
|
+
local remote_value = redis.call("get",KEYS[1])
|
|
1850
|
+
|
|
1851
|
+
if (not remote_value) then
|
|
1852
|
+
return 0
|
|
1853
|
+
elseif (remote_value == ARGV[1]) then
|
|
1854
|
+
return redis.call("del",KEYS[1])
|
|
1855
|
+
else
|
|
1856
|
+
return -1
|
|
1857
|
+
end
|
|
1858
|
+
`
|
|
1859
|
+
});
|
|
1860
|
+
return conn.getCompare(name, value);
|
|
1861
|
+
}
|
|
1862
|
+
catch (error) {
|
|
1863
|
+
throw error;
|
|
1864
|
+
}
|
|
1865
|
+
finally {
|
|
1866
|
+
this.release(conn);
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
/**
|
|
1872
|
+
*
|
|
1873
|
+
*
|
|
1874
|
+
* @export
|
|
1875
|
+
* @class Store
|
|
1876
|
+
*/
|
|
1877
|
+
class Store {
|
|
1878
|
+
/**
|
|
1879
|
+
*
|
|
1880
|
+
*
|
|
1881
|
+
* @static
|
|
1882
|
+
* @returns
|
|
1883
|
+
* @memberof ValidateUtil
|
|
1884
|
+
*/
|
|
1885
|
+
static getInstance(options) {
|
|
1886
|
+
if (this.instance) {
|
|
1887
|
+
return this.instance;
|
|
1888
|
+
}
|
|
1889
|
+
options = {
|
|
1890
|
+
...{
|
|
1891
|
+
type: 'memory',
|
|
1892
|
+
host: '',
|
|
1893
|
+
port: 0,
|
|
1894
|
+
keyPrefix: 'Koatty',
|
|
1895
|
+
timeout: 600,
|
|
1896
|
+
poolSize: 10,
|
|
1897
|
+
connectTimeout: 500,
|
|
1898
|
+
db: 0
|
|
1899
|
+
}, ...options
|
|
1900
|
+
};
|
|
1901
|
+
switch (options.type) {
|
|
1902
|
+
case "redis":
|
|
1903
|
+
this.instance = new RedisStore(options);
|
|
1904
|
+
break;
|
|
1905
|
+
case "memory":
|
|
1906
|
+
default:
|
|
1907
|
+
this.instance = new MemoryStore(options);
|
|
1908
|
+
break;
|
|
1909
|
+
}
|
|
1910
|
+
return this.instance;
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
exports.CacheStore = CacheStore;
|
|
1915
|
+
exports.MemoryStore = MemoryStore;
|
|
53
1916
|
exports.Store = Store;
|
|
54
|
-
//# sourceMappingURL=index.js.map
|