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