koatty_store 1.5.8 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.rollup.config.js +51 -51
- package/CHANGELOG.md +2 -0
- package/dist/index.d.ts +100 -35
- package/dist/index.js +1300 -1316
- package/dist/index.mjs +1301 -1315
- package/dist/package.json +5 -3
- package/package.json +5 -3
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* @Author: richen
|
|
3
|
-
* @Date: 2023-
|
|
3
|
+
* @Date: 2023-02-19 01:08:09
|
|
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
|
|
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
|
|
41
|
-
* @LastEditTime: 2023-
|
|
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
|
-
* @
|
|
47
|
-
* @class Store
|
|
46
|
+
* @enum {number}
|
|
48
47
|
*/
|
|
49
|
-
|
|
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
|
|
52
|
-
* @param {
|
|
53
|
-
* @memberof
|
|
74
|
+
* Creates an instance of MemoryCache.
|
|
75
|
+
* @param {*} options
|
|
76
|
+
* @memberof MemoryCache
|
|
54
77
|
*/
|
|
55
78
|
constructor(options) {
|
|
56
|
-
|
|
57
|
-
this.
|
|
58
|
-
this.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
*
|
|
79
|
-
* @param {any[]} data
|
|
89
|
+
*
|
|
80
90
|
* @returns {*}
|
|
81
|
-
* @memberof
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
*
|
|
119
|
-
*
|
|
104
|
+
*
|
|
105
|
+
*
|
|
120
106
|
* @returns {*}
|
|
107
|
+
* @memberof MemoryCache
|
|
121
108
|
*/
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
|
|
169
|
-
return this.
|
|
122
|
+
end() {
|
|
123
|
+
return this.quit();
|
|
170
124
|
}
|
|
171
125
|
/**
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
* @param
|
|
126
|
+
*
|
|
127
|
+
*
|
|
128
|
+
* @param {string} message
|
|
129
|
+
* @param {Function} [callback]
|
|
175
130
|
* @returns {*}
|
|
131
|
+
* @memberof MemoryCache
|
|
176
132
|
*/
|
|
177
|
-
|
|
178
|
-
return this.
|
|
133
|
+
echo(message, callback) {
|
|
134
|
+
return this._handleCallback(callback, message);
|
|
179
135
|
}
|
|
180
136
|
/**
|
|
181
|
-
* 将 key 所储存的值减去减量
|
|
182
137
|
*
|
|
183
|
-
*
|
|
184
|
-
* @param {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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
|
-
*
|
|
207
|
-
* @param
|
|
149
|
+
*
|
|
150
|
+
*
|
|
151
|
+
* @param {string} password
|
|
152
|
+
* @param {Function} [callback]
|
|
208
153
|
* @returns {*}
|
|
154
|
+
* @memberof MemoryCache
|
|
209
155
|
*/
|
|
210
|
-
|
|
211
|
-
|
|
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
|
-
*
|
|
223
|
-
*
|
|
224
|
-
* @param
|
|
160
|
+
*
|
|
161
|
+
*
|
|
162
|
+
* @param {number} dbIndex
|
|
163
|
+
* @param {Function} [callback]
|
|
225
164
|
* @returns {*}
|
|
165
|
+
* @memberof MemoryCache
|
|
226
166
|
*/
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
245
|
-
const
|
|
246
|
-
|
|
247
|
-
|
|
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
|
-
*
|
|
251
|
-
*
|
|
259
|
+
*
|
|
260
|
+
*
|
|
261
|
+
* @param {string} key
|
|
262
|
+
* @param {Function} [callback]
|
|
252
263
|
* @returns {*}
|
|
264
|
+
* @memberof MemoryCache
|
|
253
265
|
*/
|
|
254
|
-
|
|
255
|
-
|
|
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
|
-
*
|
|
259
|
-
*
|
|
260
|
-
* @param key
|
|
261
|
-
* @param
|
|
274
|
+
*
|
|
275
|
+
*
|
|
276
|
+
* @param {string} key
|
|
277
|
+
* @param {number} seconds
|
|
278
|
+
* @param {Function} [callback]
|
|
262
279
|
* @returns {*}
|
|
280
|
+
* @memberof MemoryCache
|
|
263
281
|
*/
|
|
264
|
-
|
|
265
|
-
|
|
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
|
-
*
|
|
269
|
-
*
|
|
291
|
+
*
|
|
292
|
+
*
|
|
293
|
+
* @param {...any[]} keys
|
|
270
294
|
* @returns {*}
|
|
295
|
+
* @memberof MemoryCache
|
|
271
296
|
*/
|
|
272
|
-
|
|
273
|
-
|
|
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
|
-
*
|
|
277
|
-
*
|
|
312
|
+
*
|
|
313
|
+
*
|
|
314
|
+
* @param {...any[]} keys
|
|
278
315
|
* @returns {*}
|
|
316
|
+
* @memberof MemoryCache
|
|
279
317
|
*/
|
|
280
|
-
|
|
281
|
-
|
|
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
|
-
*
|
|
285
|
-
*
|
|
330
|
+
*
|
|
331
|
+
*
|
|
332
|
+
* @param {string} key
|
|
333
|
+
* @param {Function} [callback]
|
|
286
334
|
* @returns {*}
|
|
335
|
+
* @memberof MemoryCache
|
|
287
336
|
*/
|
|
288
|
-
|
|
289
|
-
|
|
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
|
-
*
|
|
348
|
+
*
|
|
349
|
+
*
|
|
350
|
+
* @param {string} key
|
|
351
|
+
* @param {number} amount
|
|
352
|
+
* @param {Function} [callback]
|
|
294
353
|
* @returns {*}
|
|
354
|
+
* @memberof MemoryCache
|
|
295
355
|
*/
|
|
296
|
-
|
|
297
|
-
|
|
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
|
-
*
|
|
302
|
-
* @param
|
|
367
|
+
*
|
|
368
|
+
*
|
|
369
|
+
* @param {string} key
|
|
370
|
+
* @param {Function} [callback]
|
|
303
371
|
* @returns {*}
|
|
372
|
+
* @memberof MemoryCache
|
|
304
373
|
*/
|
|
305
|
-
|
|
306
|
-
|
|
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}
|
|
312
|
-
* @param {
|
|
387
|
+
* @param {string} key
|
|
388
|
+
* @param {number} amount
|
|
389
|
+
* @param {Function} [callback]
|
|
313
390
|
* @returns {*}
|
|
314
|
-
* @memberof
|
|
391
|
+
* @memberof MemoryCache
|
|
315
392
|
*/
|
|
316
|
-
|
|
317
|
-
|
|
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
|
-
*
|
|
422
|
+
*
|
|
423
|
+
*
|
|
424
|
+
* @param {string} key
|
|
425
|
+
* @param {string} field
|
|
426
|
+
* @param {Function} [callback]
|
|
322
427
|
* @returns {*}
|
|
428
|
+
* @memberof MemoryCache
|
|
323
429
|
*/
|
|
324
|
-
|
|
325
|
-
|
|
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}
|
|
443
|
+
* @param {string} key
|
|
444
|
+
* @param {string} field
|
|
445
|
+
* @param {Function} [callback]
|
|
331
446
|
* @returns {*}
|
|
332
|
-
* @memberof
|
|
447
|
+
* @memberof MemoryCache
|
|
333
448
|
*/
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
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
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
this.
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
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
|
-
|
|
489
|
-
|
|
490
|
-
|
|
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
|
-
|
|
502
|
-
|
|
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}
|
|
517
|
+
* @param {string} key
|
|
508
518
|
* @param {Function} [callback]
|
|
509
519
|
* @returns {*}
|
|
510
520
|
* @memberof MemoryCache
|
|
511
521
|
*/
|
|
512
|
-
|
|
513
|
-
|
|
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}
|
|
549
|
+
* @param {string} key
|
|
519
550
|
* @param {Function} [callback]
|
|
520
551
|
* @returns {*}
|
|
521
552
|
* @memberof MemoryCache
|
|
522
553
|
*/
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
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}
|
|
568
|
+
* @param {string} key
|
|
531
569
|
* @param {Function} [callback]
|
|
532
570
|
* @returns {*}
|
|
533
571
|
* @memberof MemoryCache
|
|
534
572
|
*/
|
|
535
|
-
|
|
536
|
-
|
|
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 {
|
|
584
|
+
* @param {string} key
|
|
585
|
+
* @param {(string | number)} value
|
|
542
586
|
* @param {Function} [callback]
|
|
543
587
|
* @returns {*}
|
|
544
588
|
* @memberof MemoryCache
|
|
545
589
|
*/
|
|
546
|
-
|
|
547
|
-
|
|
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, '
|
|
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
|
-
*
|
|
605
|
+
*
|
|
571
606
|
*
|
|
572
607
|
* @param {string} key
|
|
573
608
|
* @param {(string | number)} value
|
|
574
|
-
* @param {
|
|
609
|
+
* @param {Function} [callback]
|
|
575
610
|
* @returns {*}
|
|
576
611
|
* @memberof MemoryCache
|
|
577
612
|
*/
|
|
578
|
-
|
|
579
|
-
|
|
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, '
|
|
627
|
-
if (notexist) {
|
|
628
|
-
return this._handleCallback(callback, retVal);
|
|
629
|
-
}
|
|
616
|
+
this._testType(key, 'list', true, callback);
|
|
630
617
|
}
|
|
631
|
-
else
|
|
632
|
-
|
|
618
|
+
else {
|
|
619
|
+
this.cache[key] = this._makeKey([], 'list');
|
|
633
620
|
}
|
|
634
|
-
|
|
635
|
-
|
|
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
|
-
|
|
646
|
-
let retVal =
|
|
647
|
-
if (
|
|
648
|
-
|
|
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
|
-
|
|
662
|
-
let retVal =
|
|
653
|
+
rpop(key, callback) {
|
|
654
|
+
let retVal = null;
|
|
663
655
|
if (this._hasKey(key)) {
|
|
664
|
-
this.
|
|
665
|
-
|
|
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 {
|
|
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
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
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 {
|
|
706
|
+
* @param {string} key
|
|
707
|
+
* @param {...any[]} members
|
|
694
708
|
* @returns {*}
|
|
695
709
|
* @memberof MemoryCache
|
|
696
710
|
*/
|
|
697
|
-
|
|
711
|
+
sadd(key, ...members) {
|
|
698
712
|
let retVal = 0;
|
|
699
|
-
const callback = this._retrieveCallback(
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
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
|
-
|
|
717
|
-
let retVal =
|
|
718
|
-
|
|
719
|
-
|
|
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 {
|
|
748
|
+
* @param {string} member
|
|
731
749
|
* @param {Function} [callback]
|
|
732
750
|
* @returns {*}
|
|
733
751
|
* @memberof MemoryCache
|
|
734
752
|
*/
|
|
735
|
-
|
|
736
|
-
let retVal =
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
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
|
-
|
|
754
|
-
let retVal =
|
|
755
|
-
|
|
756
|
-
|
|
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}
|
|
784
|
+
* @param {number} [count]
|
|
768
785
|
* @param {Function} [callback]
|
|
769
786
|
* @returns {*}
|
|
770
787
|
* @memberof MemoryCache
|
|
771
788
|
*/
|
|
772
|
-
|
|
789
|
+
spop(key, count, callback) {
|
|
773
790
|
let retVal = null;
|
|
774
|
-
|
|
775
|
-
|
|
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
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
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 {
|
|
805
|
-
* @param {Function} [callback]
|
|
811
|
+
* @param {...any[]} members
|
|
806
812
|
* @returns {*}
|
|
807
813
|
* @memberof MemoryCache
|
|
808
814
|
*/
|
|
809
|
-
|
|
810
|
-
let retVal =
|
|
815
|
+
srem(key, ...members) {
|
|
816
|
+
let retVal = 0;
|
|
817
|
+
const callback = this._retrieveCallback(members);
|
|
811
818
|
if (this._hasKey(key)) {
|
|
812
|
-
this._testType(key, '
|
|
813
|
-
|
|
814
|
-
|
|
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}
|
|
823
|
-
* @param {string}
|
|
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
|
-
|
|
845
|
+
smove(sourcekey, destkey, member, callback) {
|
|
829
846
|
let retVal = 0;
|
|
830
|
-
if (this._hasKey(
|
|
831
|
-
this._testType(
|
|
832
|
-
|
|
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 {
|
|
885
|
+
* @param {Function} [callback]
|
|
843
886
|
* @returns {*}
|
|
844
887
|
* @memberof MemoryCache
|
|
845
888
|
*/
|
|
846
|
-
|
|
847
|
-
let retVal =
|
|
848
|
-
const callback = this._retrieveCallback(fields);
|
|
889
|
+
pttl(key, callback) {
|
|
890
|
+
let retVal = -2;
|
|
849
891
|
if (this._hasKey(key)) {
|
|
850
|
-
this.
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
if (
|
|
854
|
-
|
|
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
|
-
|
|
870
|
-
|
|
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
|
-
* @
|
|
878
|
-
* @param {*} value
|
|
879
|
-
* @param {Function} [callback]
|
|
880
|
-
* @returns {*}
|
|
929
|
+
* @returns {*} {boolean}
|
|
881
930
|
* @memberof MemoryCache
|
|
882
931
|
*/
|
|
883
|
-
|
|
884
|
-
|
|
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
|
-
* @
|
|
897
|
-
* @param {
|
|
938
|
+
* @private
|
|
939
|
+
* @param {*} value
|
|
940
|
+
* @param {string} type
|
|
941
|
+
* @param {number} timeout
|
|
898
942
|
* @returns {*}
|
|
899
943
|
* @memberof MemoryCache
|
|
900
944
|
*/
|
|
901
|
-
|
|
902
|
-
|
|
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
|
-
|
|
934
|
-
|
|
935
|
-
|
|
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
|
-
|
|
953
|
-
let
|
|
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, '
|
|
956
|
-
|
|
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
|
-
|
|
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 {
|
|
994
|
+
* @param {string} type
|
|
995
|
+
* @param {boolean} [throwError]
|
|
965
996
|
* @param {Function} [callback]
|
|
966
997
|
* @returns {*}
|
|
967
998
|
* @memberof MemoryCache
|
|
968
999
|
*/
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
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
|
-
|
|
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
|
-
|
|
993
|
-
|
|
994
|
-
if (
|
|
995
|
-
this.
|
|
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
|
-
|
|
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 {
|
|
1011
|
-
* @returns {*}
|
|
1032
|
+
* @param {(number | string)} value
|
|
1012
1033
|
* @memberof MemoryCache
|
|
1013
1034
|
*/
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
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
|
-
|
|
1033
|
-
|
|
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, '
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1059
|
+
this._testType(key, 'hash', true, callback);
|
|
1060
|
+
if (this._hasField(key, field)) {
|
|
1061
|
+
value = this._getField(key, field);
|
|
1062
|
+
}
|
|
1039
1063
|
}
|
|
1040
|
-
|
|
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 {
|
|
1047
|
-
* @param {number} stop
|
|
1048
|
-
* @param {Function} [callback]
|
|
1081
|
+
* @param {string} field
|
|
1049
1082
|
* @returns {*}
|
|
1050
1083
|
* @memberof MemoryCache
|
|
1051
1084
|
*/
|
|
1052
|
-
|
|
1053
|
-
|
|
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 {
|
|
1087
|
-
* @returns {*}
|
|
1093
|
+
* @param {string} field
|
|
1094
|
+
* @returns {*} {boolean}
|
|
1088
1095
|
* @memberof MemoryCache
|
|
1089
1096
|
*/
|
|
1090
|
-
|
|
1091
|
-
let retVal =
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
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
|
-
|
|
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 {
|
|
1112
|
-
* @
|
|
1111
|
+
* @param {string} field
|
|
1112
|
+
* @param {*} value
|
|
1113
1113
|
* @memberof MemoryCache
|
|
1114
1114
|
*/
|
|
1115
|
-
|
|
1116
|
-
|
|
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
|
-
* @
|
|
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
|
-
|
|
1133
|
-
let
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
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
|
|
1158
|
+
return;
|
|
1142
1159
|
}
|
|
1143
1160
|
/**
|
|
1144
1161
|
*
|
|
1145
1162
|
*
|
|
1146
|
-
* @
|
|
1147
|
-
* @param {
|
|
1163
|
+
* @private
|
|
1164
|
+
* @param {any[]} [params]
|
|
1148
1165
|
* @returns {*}
|
|
1149
1166
|
* @memberof MemoryCache
|
|
1150
1167
|
*/
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
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
|
|
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
|
|
1197
|
+
* @memberof MemoryStore
|
|
1167
1198
|
*/
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1199
|
+
getConnection() {
|
|
1200
|
+
if (!this.pool) {
|
|
1201
|
+
this.pool = new MemoryCache({
|
|
1202
|
+
database: this.options.db
|
|
1203
|
+
});
|
|
1173
1204
|
}
|
|
1174
|
-
if (this.
|
|
1175
|
-
|
|
1176
|
-
this.
|
|
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.
|
|
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 {
|
|
1190
|
-
* @
|
|
1191
|
-
* @
|
|
1192
|
-
* @memberof MemoryCache
|
|
1224
|
+
* @param {*} conn
|
|
1225
|
+
* @returns {*} {Promise<void>}
|
|
1226
|
+
* @memberof MemoryStore
|
|
1193
1227
|
*/
|
|
1194
|
-
|
|
1195
|
-
|
|
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}
|
|
1218
|
-
* @param {string}
|
|
1219
|
-
* @
|
|
1220
|
-
* @
|
|
1221
|
-
* @returns {*}
|
|
1222
|
-
* @memberof MemoryCache
|
|
1244
|
+
* @param {string} name
|
|
1245
|
+
* @param {(string | number)} value
|
|
1246
|
+
* @returns {*} {Promise<any>}
|
|
1247
|
+
* @memberof MemoryStore
|
|
1223
1248
|
*/
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
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
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
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
|
-
* @
|
|
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
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
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
|
-
|
|
1329
|
+
// cluster
|
|
1330
|
+
opt.host = "";
|
|
1331
|
+
opt.port = null;
|
|
1332
|
+
opt.clusters = [...hosts];
|
|
1281
1333
|
}
|
|
1282
1334
|
}
|
|
1283
|
-
return
|
|
1335
|
+
return opt;
|
|
1284
1336
|
}
|
|
1285
1337
|
/**
|
|
1338
|
+
* create connection by native
|
|
1286
1339
|
*
|
|
1287
|
-
*
|
|
1288
|
-
* @
|
|
1289
|
-
* @
|
|
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
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
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
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
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
|
|
1378
|
+
* @memberof RedisStore
|
|
1324
1379
|
*/
|
|
1325
|
-
|
|
1326
|
-
|
|
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
|
|
1410
|
+
* @memberof RedisStore
|
|
1335
1411
|
*/
|
|
1336
|
-
|
|
1337
|
-
this.
|
|
1338
|
-
|
|
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
|
-
* @
|
|
1344
|
-
* @param {string} key
|
|
1345
|
-
* @param {number} amount
|
|
1346
|
-
* @param {Function} [callback]
|
|
1422
|
+
* @param {*} conn
|
|
1347
1423
|
* @returns {*}
|
|
1348
|
-
* @memberof
|
|
1424
|
+
* @memberof RedisStore
|
|
1349
1425
|
*/
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
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
|
-
|
|
1366
|
-
this._setKey(key, val.toString());
|
|
1367
|
-
return val;
|
|
1430
|
+
return Promise.resolve();
|
|
1368
1431
|
}
|
|
1369
1432
|
/**
|
|
1433
|
+
* defineCommand
|
|
1370
1434
|
*
|
|
1371
|
-
*
|
|
1372
|
-
* @
|
|
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
|
|
1438
|
+
* @memberof RedisStore
|
|
1379
1439
|
*/
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
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
|
|
1445
|
+
return conn;
|
|
1390
1446
|
}
|
|
1391
1447
|
/**
|
|
1448
|
+
* get and compare value
|
|
1392
1449
|
*
|
|
1393
|
-
*
|
|
1394
|
-
* @
|
|
1395
|
-
* @
|
|
1396
|
-
* @
|
|
1397
|
-
* @memberof MemoryCache
|
|
1450
|
+
* @param {string} name
|
|
1451
|
+
* @param {(string | number)} value
|
|
1452
|
+
* @returns {*} {Promise<any>}
|
|
1453
|
+
* @memberof RedisStore
|
|
1398
1454
|
*/
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
this.
|
|
1403
|
-
|
|
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
|
-
* @
|
|
1411
|
-
* @
|
|
1412
|
-
* @param {(number | string)} value
|
|
1413
|
-
* @memberof MemoryCache
|
|
1528
|
+
* @static
|
|
1529
|
+
* @returns
|
|
1414
1530
|
*/
|
|
1415
|
-
|
|
1416
|
-
this.
|
|
1417
|
-
|
|
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
|
-
* @
|
|
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
|
|
1559
|
+
* @memberof RedisStore
|
|
1430
1560
|
*/
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
return
|
|
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
|
-
|
|
1445
|
-
|
|
1568
|
+
catch (err) {
|
|
1569
|
+
throw err;
|
|
1446
1570
|
}
|
|
1447
|
-
|
|
1448
|
-
|
|
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
|
-
|
|
1466
|
-
return this.
|
|
1579
|
+
get(name) {
|
|
1580
|
+
return this.wrap('get', [`${this.options.keyPrefix || ""}${name}`]);
|
|
1467
1581
|
}
|
|
1468
1582
|
/**
|
|
1469
|
-
*
|
|
1470
|
-
*
|
|
1471
|
-
* @
|
|
1472
|
-
* @param
|
|
1473
|
-
* @
|
|
1474
|
-
* @returns {*} {boolean}
|
|
1475
|
-
* @memberof MemoryCache
|
|
1583
|
+
* 字符串写入
|
|
1584
|
+
* @param name
|
|
1585
|
+
* @param value
|
|
1586
|
+
* @param timeout
|
|
1587
|
+
* @returns {Promise}
|
|
1476
1588
|
*/
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
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
|
|
1593
|
+
return this.wrap('set', [`${this.options.keyPrefix || ""}${name}`, value, 'ex', timeout]);
|
|
1486
1594
|
}
|
|
1487
1595
|
/**
|
|
1488
|
-
*
|
|
1489
|
-
*
|
|
1490
|
-
* @
|
|
1491
|
-
* @param {string} field
|
|
1492
|
-
* @param {*} value
|
|
1493
|
-
* @memberof MemoryCache
|
|
1596
|
+
* 以秒为单位,返回给定 key 的剩余生存时间
|
|
1597
|
+
* @param name
|
|
1598
|
+
* @returns {*}
|
|
1494
1599
|
*/
|
|
1495
|
-
|
|
1496
|
-
this.
|
|
1600
|
+
ttl(name) {
|
|
1601
|
+
return this.wrap('ttl', [`${this.options.keyPrefix || ""}${name}`]);
|
|
1497
1602
|
}
|
|
1498
1603
|
/**
|
|
1499
|
-
*
|
|
1500
|
-
*
|
|
1501
|
-
* @
|
|
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
|
-
|
|
1510
|
-
|
|
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
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
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
|
-
* @
|
|
1544
|
-
* @
|
|
1545
|
-
* @returns {*}
|
|
1546
|
-
* @memberof MemoryCache
|
|
1621
|
+
* @param {*} name
|
|
1622
|
+
* @returns
|
|
1547
1623
|
*/
|
|
1548
|
-
|
|
1549
|
-
|
|
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
|
-
*
|
|
1567
|
-
* @param
|
|
1568
|
-
* @memberof MemoryStore
|
|
1628
|
+
* 判断key是否存在
|
|
1629
|
+
* @param name
|
|
1569
1630
|
*/
|
|
1570
|
-
|
|
1571
|
-
|
|
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
|
-
*
|
|
1577
|
-
*
|
|
1578
|
-
* @returns {*}
|
|
1579
|
-
* @memberof MemoryStore
|
|
1635
|
+
* 自增
|
|
1636
|
+
* @param name
|
|
1580
1637
|
*/
|
|
1581
|
-
|
|
1582
|
-
|
|
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;
|
|
1638
|
+
incr(name) {
|
|
1639
|
+
return this.wrap('incr', [`${this.options.keyPrefix || ""}${name}`]);
|
|
1592
1640
|
}
|
|
1593
1641
|
/**
|
|
1594
|
-
*
|
|
1595
|
-
*
|
|
1596
|
-
* @returns {*}
|
|
1597
|
-
* @memberof MemoryStore
|
|
1642
|
+
* 自减
|
|
1643
|
+
* @param name
|
|
1644
|
+
* @returns {*}
|
|
1598
1645
|
*/
|
|
1599
|
-
|
|
1600
|
-
this.
|
|
1601
|
-
this.client = null;
|
|
1646
|
+
decr(name) {
|
|
1647
|
+
return this.wrap('decr', [`${this.options.keyPrefix || ""}${name}`]);
|
|
1602
1648
|
}
|
|
1603
1649
|
/**
|
|
1604
|
-
*
|
|
1605
|
-
*
|
|
1606
|
-
* @param
|
|
1607
|
-
* @returns {*}
|
|
1608
|
-
* @memberof MemoryStore
|
|
1650
|
+
* 将 key 所储存的值增加增量
|
|
1651
|
+
* @param name
|
|
1652
|
+
* @param incr
|
|
1653
|
+
* @returns {*}
|
|
1609
1654
|
*/
|
|
1610
|
-
|
|
1611
|
-
return;
|
|
1655
|
+
incrby(name, incr = 1) {
|
|
1656
|
+
return this.wrap('incrby', [`${this.options.keyPrefix || ""}${name}`, incr]);
|
|
1612
1657
|
}
|
|
1613
1658
|
/**
|
|
1614
|
-
*
|
|
1659
|
+
* 将 key 所储存的值减去减量
|
|
1615
1660
|
*
|
|
1616
|
-
* @param {
|
|
1617
|
-
* @param {
|
|
1618
|
-
* @memberof MemoryStore
|
|
1661
|
+
* @param {any} name
|
|
1662
|
+
* @param {any} decr
|
|
1619
1663
|
*/
|
|
1620
|
-
|
|
1621
|
-
|
|
1664
|
+
decrby(name, decr = 1) {
|
|
1665
|
+
return this.wrap('decrby', [`${this.options.keyPrefix || ""}${name}`, decr]);
|
|
1622
1666
|
}
|
|
1623
1667
|
/**
|
|
1624
|
-
*
|
|
1625
|
-
*
|
|
1626
|
-
* @param
|
|
1627
|
-
* @param
|
|
1628
|
-
* @
|
|
1629
|
-
* @memberof MemoryStore
|
|
1668
|
+
* 哈希写入
|
|
1669
|
+
* @param name
|
|
1670
|
+
* @param key
|
|
1671
|
+
* @param value
|
|
1672
|
+
* @param timeout
|
|
1630
1673
|
*/
|
|
1631
|
-
|
|
1632
|
-
const
|
|
1633
|
-
|
|
1634
|
-
|
|
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
|
-
*
|
|
1663
|
-
* @param
|
|
1664
|
-
* @
|
|
1683
|
+
* 哈希获取
|
|
1684
|
+
* @param name
|
|
1685
|
+
* @param key
|
|
1686
|
+
* @returns {*}
|
|
1665
1687
|
*/
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
this.
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
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
|
-
|
|
1696
|
+
return dataArr[1] || null;
|
|
1697
|
+
});
|
|
1719
1698
|
}
|
|
1720
1699
|
/**
|
|
1721
|
-
*
|
|
1722
|
-
*
|
|
1723
|
-
* @param
|
|
1724
|
-
* @returns {*}
|
|
1725
|
-
* @memberof RedisStore
|
|
1700
|
+
* 查看哈希表 hashKey 中,给定域 key 是否存在
|
|
1701
|
+
* @param name
|
|
1702
|
+
* @param key
|
|
1703
|
+
* @returns {*}
|
|
1726
1704
|
*/
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
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
|
-
*
|
|
1757
|
-
*
|
|
1717
|
+
* 哈希删除
|
|
1718
|
+
* @param name
|
|
1719
|
+
* @param key
|
|
1758
1720
|
* @returns {*}
|
|
1759
|
-
* @memberof RedisStore
|
|
1760
1721
|
*/
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
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
|
-
*
|
|
1789
|
-
*
|
|
1728
|
+
* 返回哈希表 key 中域的数量
|
|
1729
|
+
* @param name
|
|
1790
1730
|
* @returns {*}
|
|
1791
|
-
* @memberof RedisStore
|
|
1792
1731
|
*/
|
|
1793
|
-
|
|
1794
|
-
this.
|
|
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
|
|
1736
|
+
* 给哈希表指定key,增加increment
|
|
1737
|
+
* @param name
|
|
1738
|
+
* @param key
|
|
1739
|
+
* @param incr
|
|
1804
1740
|
* @returns {*}
|
|
1805
|
-
* @memberof RedisStore
|
|
1806
1741
|
*/
|
|
1807
|
-
|
|
1808
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
1822
|
-
|
|
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}`]);
|
|
1827
1752
|
}
|
|
1828
1753
|
/**
|
|
1829
|
-
*
|
|
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]);
|
|
1785
|
+
}
|
|
1786
|
+
/**
|
|
1787
|
+
*
|
|
1830
1788
|
*
|
|
1831
1789
|
* @param {string} name
|
|
1832
1790
|
* @param {(string | number)} value
|
|
1833
|
-
* @returns {*}
|
|
1791
|
+
* @returns {*}
|
|
1834
1792
|
* @memberof RedisStore
|
|
1835
1793
|
*/
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
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
|
-
* @
|
|
1875
|
-
* @returns
|
|
1876
|
-
* @memberof
|
|
1808
|
+
* @param {string} name
|
|
1809
|
+
* @returns {*}
|
|
1810
|
+
* @memberof RedisStore
|
|
1877
1811
|
*/
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
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
|
|
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;
|