koatty_store 1.5.8 → 1.6.1

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