mm_redis 2.0.6 → 2.0.8
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/README.md +0 -1
- package/index.js +631 -642
- package/package.json +4 -6
- package/test_hmset.js +0 -91
package/index.js
CHANGED
|
@@ -1,20 +1,13 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileOverview redis缓存帮助类函数
|
|
3
|
-
* @author <a href="http://qww.elins.cn">邱文武</a>
|
|
4
|
-
* @version 1.5.0
|
|
5
|
-
*/
|
|
6
|
-
const {
|
|
7
|
-
BaseService
|
|
8
|
-
} = require('mm_base_service');
|
|
9
1
|
const {
|
|
10
2
|
createClient
|
|
11
3
|
} = require('redis');
|
|
4
|
+
const { Base } = require('mm_expand');
|
|
12
5
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class Redis extends
|
|
6
|
+
/**
|
|
7
|
+
* @class Redis
|
|
8
|
+
* @description Redis缓存帮助类函数
|
|
9
|
+
*/
|
|
10
|
+
class Redis extends Base {
|
|
18
11
|
/**
|
|
19
12
|
* @description 创建Redis帮助类函数 (构造函数)
|
|
20
13
|
* @param {Object} config 配置参数
|
|
@@ -68,8 +61,9 @@ class Redis extends BaseService {
|
|
|
68
61
|
* 应用键前缀
|
|
69
62
|
* @param {String} key 键
|
|
70
63
|
* @return {String} 处理后的键
|
|
64
|
+
* @private
|
|
71
65
|
*/
|
|
72
|
-
Redis.prototype.
|
|
66
|
+
Redis.prototype._addPrefix = function (key) {
|
|
73
67
|
return this.config.prefix ? this.config.prefix + key : key;
|
|
74
68
|
};
|
|
75
69
|
|
|
@@ -77,8 +71,9 @@ Redis.prototype.applyPrefix = function(key) {
|
|
|
77
71
|
* 移除键前缀
|
|
78
72
|
* @param {String} key 带前缀的键
|
|
79
73
|
* @return {String} 处理后的键
|
|
74
|
+
* @private
|
|
80
75
|
*/
|
|
81
|
-
Redis.prototype.
|
|
76
|
+
Redis.prototype._delPrefix = function (key) {
|
|
82
77
|
if (this.config.prefix && key.startsWith(this.config.prefix)) {
|
|
83
78
|
return key.slice(this.config.prefix.length);
|
|
84
79
|
}
|
|
@@ -91,13 +86,21 @@ Redis.prototype.removePrefix = function(key) {
|
|
|
91
86
|
* @param {Function} func 操作回调函数,可判断成功与否
|
|
92
87
|
* @return {Promise<Boolean>} 订阅结果
|
|
93
88
|
*/
|
|
94
|
-
Redis.prototype.subscribe = async function(channel, func) {
|
|
89
|
+
Redis.prototype.subscribe = async function (channel, func) {
|
|
95
90
|
try {
|
|
96
|
-
|
|
91
|
+
// 参数验证
|
|
92
|
+
if (!channel || typeof channel !== 'string') {
|
|
93
|
+
throw new TypeError('channel必须是非空字符串');
|
|
94
|
+
}
|
|
95
|
+
if (typeof func !== 'function') {
|
|
96
|
+
throw new TypeError('func必须是函数');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
await this.conn.subscribe(this._addPrefix(channel));
|
|
97
100
|
this.func_list[channel] = func;
|
|
98
101
|
return true;
|
|
99
102
|
} catch (err) {
|
|
100
|
-
|
|
103
|
+
this.logger('error', `订阅频道 ${channel} 失败:`, err);
|
|
101
104
|
return false;
|
|
102
105
|
}
|
|
103
106
|
};
|
|
@@ -107,13 +110,18 @@ Redis.prototype.subscribe = async function(channel, func) {
|
|
|
107
110
|
* @param {String} channel 订阅的频道
|
|
108
111
|
* @return {Promise<Boolean>} 取消订阅结果
|
|
109
112
|
*/
|
|
110
|
-
Redis.prototype.unsubscribe = async function(channel) {
|
|
113
|
+
Redis.prototype.unsubscribe = async function (channel) {
|
|
111
114
|
try {
|
|
112
|
-
|
|
115
|
+
// 参数验证
|
|
116
|
+
if (!channel || typeof channel !== 'string') {
|
|
117
|
+
throw new TypeError('channel必须是非空字符串');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
await this.conn.unsubscribe(this._addPrefix(channel));
|
|
113
121
|
delete this.func_list[channel];
|
|
114
122
|
return true;
|
|
115
123
|
} catch (err) {
|
|
116
|
-
|
|
124
|
+
this.logger('error', `取消订阅频道 ${channel} 失败:`, err);
|
|
117
125
|
return false;
|
|
118
126
|
}
|
|
119
127
|
};
|
|
@@ -124,12 +132,19 @@ Redis.prototype.unsubscribe = async function(channel) {
|
|
|
124
132
|
* @param {String} message 订阅的消息
|
|
125
133
|
* @return {Promise<Number>} 接收消息的客户端数量
|
|
126
134
|
*/
|
|
127
|
-
Redis.prototype.publish = async function(channel, message) {
|
|
135
|
+
Redis.prototype.publish = async function (channel, message) {
|
|
128
136
|
try {
|
|
129
|
-
|
|
137
|
+
// 参数验证
|
|
138
|
+
if (!channel || typeof channel !== 'string') {
|
|
139
|
+
throw new TypeError('channel必须是非空字符串');
|
|
140
|
+
}
|
|
141
|
+
if (message === undefined || message === null) {
|
|
142
|
+
throw new TypeError('message不能为undefined或null');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return await this.conn.publish(this._addPrefix(channel), message);
|
|
130
146
|
} catch (err) {
|
|
131
|
-
|
|
132
|
-
$.log.error('[Redis] 操作失败:', err);
|
|
147
|
+
this.logger('error', `发布消息到频道 ${channel} 失败:`, err);
|
|
133
148
|
return false;
|
|
134
149
|
}
|
|
135
150
|
};
|
|
@@ -139,9 +154,9 @@ Redis.prototype.publish = async function(channel, message) {
|
|
|
139
154
|
* @param {String} channel
|
|
140
155
|
* @param {String} message
|
|
141
156
|
*/
|
|
142
|
-
Redis.prototype.main = async function(channel, message) {
|
|
157
|
+
Redis.prototype.main = async function (channel, message) {
|
|
143
158
|
// 默认实现,可由子类重写
|
|
144
|
-
|
|
159
|
+
this.logger('debug', `收到未处理的消息 [${channel}]:`, message);
|
|
145
160
|
};
|
|
146
161
|
|
|
147
162
|
/**
|
|
@@ -149,15 +164,15 @@ Redis.prototype.main = async function(channel, message) {
|
|
|
149
164
|
* @param {String} channel 频道
|
|
150
165
|
* @param {String} message 消息
|
|
151
166
|
*/
|
|
152
|
-
Redis.prototype.message = function(channel, message) {
|
|
167
|
+
Redis.prototype.message = function (channel, message) {
|
|
153
168
|
// 移除前缀
|
|
154
|
-
channel = this.
|
|
169
|
+
channel = this._delPrefix(channel);
|
|
155
170
|
var func = this.func_list[channel];
|
|
156
171
|
if (func) {
|
|
157
172
|
try {
|
|
158
173
|
func(message);
|
|
159
174
|
} catch (err) {
|
|
160
|
-
|
|
175
|
+
this.logger('error', `处理频道 ${channel} 的消息时出错:`, err);
|
|
161
176
|
}
|
|
162
177
|
} else {
|
|
163
178
|
this.main(channel, message);
|
|
@@ -168,7 +183,7 @@ Redis.prototype.message = function(channel, message) {
|
|
|
168
183
|
* @description 设置配置
|
|
169
184
|
* @param {Object} config 配置对象或配置路径
|
|
170
185
|
*/
|
|
171
|
-
Redis.prototype.setConfig = function(config) {
|
|
186
|
+
Redis.prototype.setConfig = function (config) {
|
|
172
187
|
let obj = {};
|
|
173
188
|
if (typeof config === 'string') {
|
|
174
189
|
obj = config.loadJson(__dirname);
|
|
@@ -219,13 +234,13 @@ Redis.prototype.setConfig = function(config) {
|
|
|
219
234
|
|
|
220
235
|
// 初始化连接池
|
|
221
236
|
this._initPool();
|
|
222
|
-
//
|
|
237
|
+
// this.logger('debug','配置已更新');
|
|
223
238
|
this.identifier = this.config.host + "/" + this.config.database;
|
|
224
239
|
return this;
|
|
225
240
|
};
|
|
226
241
|
|
|
227
242
|
// 添加连接池初始化方法
|
|
228
|
-
Redis.prototype._initPool = function() {
|
|
243
|
+
Redis.prototype._initPool = function () {
|
|
229
244
|
// 确保连接池配置存在
|
|
230
245
|
if (!this.config.pool) {
|
|
231
246
|
this.config.pool = {
|
|
@@ -244,14 +259,14 @@ Redis.prototype._initPool = function() {
|
|
|
244
259
|
};
|
|
245
260
|
|
|
246
261
|
// 记录连接池初始化
|
|
247
|
-
//
|
|
262
|
+
// this.logger('debug','连接池已初始化,配置:', this.config.pool);
|
|
248
263
|
};
|
|
249
264
|
|
|
250
265
|
/**
|
|
251
266
|
* @description 连接Redis数据库
|
|
252
267
|
* @return {Promise<Boolean>} 连接结果
|
|
253
268
|
*/
|
|
254
|
-
Redis.prototype.open = async function() {
|
|
269
|
+
Redis.prototype.open = async function () {
|
|
255
270
|
if (this.conn && this.connected) {
|
|
256
271
|
return true;
|
|
257
272
|
}
|
|
@@ -273,7 +288,7 @@ Redis.prototype.open = async function() {
|
|
|
273
288
|
|
|
274
289
|
// 监听错误事件
|
|
275
290
|
this.conn.on('error', (err) => {
|
|
276
|
-
|
|
291
|
+
this.logger('error', 'Redis连接错误:', err);
|
|
277
292
|
this.connected = false;
|
|
278
293
|
// 尝试重连
|
|
279
294
|
this._reconnect();
|
|
@@ -281,25 +296,25 @@ Redis.prototype.open = async function() {
|
|
|
281
296
|
|
|
282
297
|
// 监听连接成功事件
|
|
283
298
|
this.conn.on('connect', () => {
|
|
284
|
-
//
|
|
299
|
+
// this.logger('debug','Redis已连接');
|
|
285
300
|
this.connected = true;
|
|
286
301
|
this.retry_count = 0;
|
|
287
302
|
});
|
|
288
303
|
|
|
289
304
|
// 监听断开连接事件
|
|
290
305
|
this.conn.on('end', () => {
|
|
291
|
-
//
|
|
306
|
+
// this.logger('debug','Redis连接已断开');
|
|
292
307
|
this.connected = false;
|
|
293
308
|
});
|
|
294
309
|
|
|
295
310
|
// 监听订阅成功事件
|
|
296
311
|
this.conn.on('subscribe', (channel, count) => {
|
|
297
|
-
|
|
312
|
+
this.logger('debug', `频道${this._delPrefix(channel)}订阅成功, 当前总计订阅数:${count}`);
|
|
298
313
|
});
|
|
299
314
|
|
|
300
315
|
// 监听取消订阅事件
|
|
301
316
|
this.conn.on('unsubscribe', (channel, count) => {
|
|
302
|
-
|
|
317
|
+
this.logger('debug', `频道${this._delPrefix(channel)}取消订阅, 当前总计订阅数:${count}`);
|
|
303
318
|
});
|
|
304
319
|
|
|
305
320
|
// 收到消息后执行回调
|
|
@@ -312,7 +327,7 @@ Redis.prototype.open = async function() {
|
|
|
312
327
|
this.connected = true;
|
|
313
328
|
return true;
|
|
314
329
|
} catch (err) {
|
|
315
|
-
|
|
330
|
+
this.logger('error', 'Redis连接失败:', err);
|
|
316
331
|
// 尝试重连
|
|
317
332
|
this._reconnect();
|
|
318
333
|
return false;
|
|
@@ -323,20 +338,20 @@ Redis.prototype.open = async function() {
|
|
|
323
338
|
* 内部重连方法
|
|
324
339
|
* @private
|
|
325
340
|
*/
|
|
326
|
-
Redis.prototype._reconnect = function() {
|
|
341
|
+
Redis.prototype._reconnect = function () {
|
|
327
342
|
if (this.retry_count >= this.config.retry_count) {
|
|
328
|
-
|
|
343
|
+
this.logger('error', `达到最大重连次数 ${this.config.retry_count},停止重连`);
|
|
329
344
|
return;
|
|
330
345
|
}
|
|
331
346
|
|
|
332
347
|
this.retry_count++;
|
|
333
|
-
|
|
348
|
+
this.logger('debug', `尝试第 ${this.retry_count} 次重连...`);
|
|
334
349
|
|
|
335
350
|
setTimeout(async () => {
|
|
336
351
|
try {
|
|
337
352
|
await this.open();
|
|
338
353
|
} catch (err) {
|
|
339
|
-
|
|
354
|
+
this.logger('error', `重连失败:`, err);
|
|
340
355
|
}
|
|
341
356
|
}, this.config.retry_delay);
|
|
342
357
|
};
|
|
@@ -346,9 +361,9 @@ Redis.prototype._reconnect = function() {
|
|
|
346
361
|
* @return {Promise<Boolean>} 关闭结果
|
|
347
362
|
*/
|
|
348
363
|
// 修复close方法,正确处理连接池
|
|
349
|
-
Redis.prototype.close = function() {
|
|
364
|
+
Redis.prototype.close = function () {
|
|
350
365
|
try {
|
|
351
|
-
//
|
|
366
|
+
// this.logger('debug','关闭所有连接...');
|
|
352
367
|
|
|
353
368
|
// 关闭所有使用中的连接
|
|
354
369
|
if (this.connection_pool && this.connection_pool.in_use) {
|
|
@@ -356,7 +371,7 @@ Redis.prototype.close = function() {
|
|
|
356
371
|
try {
|
|
357
372
|
connection.close();
|
|
358
373
|
} catch (e) {
|
|
359
|
-
|
|
374
|
+
this.logger('error', '关闭连接失败:', e);
|
|
360
375
|
}
|
|
361
376
|
}
|
|
362
377
|
this.connection_pool.in_use.clear();
|
|
@@ -373,68 +388,68 @@ Redis.prototype.close = function() {
|
|
|
373
388
|
// 某些Redis客户端可能使用end方法
|
|
374
389
|
connection.end();
|
|
375
390
|
} else {
|
|
376
|
-
|
|
391
|
+
this.logger('debug', '连接对象没有可用的关闭方法');
|
|
377
392
|
}
|
|
378
393
|
} catch (e) {
|
|
379
|
-
|
|
394
|
+
this.logger('error', '关闭连接失败:', e);
|
|
380
395
|
}
|
|
381
396
|
}
|
|
382
397
|
this.connection_pool.available = [];
|
|
383
398
|
}
|
|
384
399
|
|
|
385
400
|
this.connected = false;
|
|
386
|
-
|
|
401
|
+
this.logger('debug', 'Redis连接已断开');
|
|
387
402
|
return Promise.resolve(true);
|
|
388
403
|
} catch (error) {
|
|
389
|
-
|
|
404
|
+
this.logger('error', '关闭连接时发生错误:', error);
|
|
390
405
|
return Promise.resolve(false);
|
|
391
406
|
}
|
|
392
407
|
};
|
|
393
408
|
|
|
394
409
|
// 添加Pipeline支持
|
|
395
|
-
Redis.prototype.pipeline = function() {
|
|
410
|
+
Redis.prototype.pipeline = function () {
|
|
396
411
|
const redisInstance = this;
|
|
397
412
|
const commands = [];
|
|
398
413
|
|
|
399
414
|
return {
|
|
400
415
|
// 设置值
|
|
401
|
-
set: function(key, value, seconds) {
|
|
416
|
+
set: function (key, value, seconds) {
|
|
402
417
|
commands.push(['set', key, value, seconds]);
|
|
403
418
|
return this;
|
|
404
419
|
},
|
|
405
420
|
|
|
406
421
|
// 获取值
|
|
407
|
-
get: function(key) {
|
|
422
|
+
get: function (key) {
|
|
408
423
|
commands.push(['get', key]);
|
|
409
424
|
return this;
|
|
410
425
|
},
|
|
411
426
|
|
|
412
427
|
// 删除
|
|
413
|
-
del: function(key) {
|
|
428
|
+
del: function (key) {
|
|
414
429
|
commands.push(['del', key]);
|
|
415
430
|
return this;
|
|
416
431
|
},
|
|
417
432
|
|
|
418
433
|
// 判断存在
|
|
419
|
-
has: function(key) {
|
|
434
|
+
has: function (key) {
|
|
420
435
|
commands.push(['has', key]);
|
|
421
436
|
return this;
|
|
422
437
|
},
|
|
423
438
|
|
|
424
439
|
// 设置哈希字段
|
|
425
|
-
hset: function(key, field, value) {
|
|
440
|
+
hset: function (key, field, value) {
|
|
426
441
|
commands.push(['hset', key, field, value]);
|
|
427
442
|
return this;
|
|
428
443
|
},
|
|
429
444
|
|
|
430
445
|
// 过期时间设置
|
|
431
|
-
expire: function(key, seconds) {
|
|
446
|
+
expire: function (key, seconds) {
|
|
432
447
|
commands.push(['expire', key, seconds]);
|
|
433
448
|
return this;
|
|
434
449
|
},
|
|
435
450
|
|
|
436
451
|
// 执行所有命令
|
|
437
|
-
exec: async function() {
|
|
452
|
+
exec: async function () {
|
|
438
453
|
try {
|
|
439
454
|
// 使用Redis实例的方法获取连接
|
|
440
455
|
const connection = await redisInstance._getConnection();
|
|
@@ -451,7 +466,7 @@ Redis.prototype.pipeline = function() {
|
|
|
451
466
|
case 'set': {
|
|
452
467
|
// 键前缀处理和值序列化
|
|
453
468
|
const [key, value, seconds] = args;
|
|
454
|
-
const prefixedKey = redisInstance.
|
|
469
|
+
const prefixedKey = redisInstance._addPrefix(key);
|
|
455
470
|
let processedValue = value;
|
|
456
471
|
if (typeof value === 'object' && value !== null) {
|
|
457
472
|
processedValue = JSON.stringify(value);
|
|
@@ -465,7 +480,7 @@ Redis.prototype.pipeline = function() {
|
|
|
465
480
|
}
|
|
466
481
|
case 'get': {
|
|
467
482
|
const [key] = args;
|
|
468
|
-
const prefixedKey = redisInstance.
|
|
483
|
+
const prefixedKey = redisInstance._addPrefix(key);
|
|
469
484
|
result = await connection.get(prefixedKey);
|
|
470
485
|
// 尝试解析JSON
|
|
471
486
|
if (typeof result === 'string') {
|
|
@@ -482,25 +497,25 @@ Redis.prototype.pipeline = function() {
|
|
|
482
497
|
}
|
|
483
498
|
case 'del': {
|
|
484
499
|
const [key] = args;
|
|
485
|
-
const prefixedKey = redisInstance.
|
|
500
|
+
const prefixedKey = redisInstance._addPrefix(key);
|
|
486
501
|
result = await connection.del(prefixedKey);
|
|
487
502
|
break;
|
|
488
503
|
}
|
|
489
504
|
case 'has': {
|
|
490
505
|
const [key] = args;
|
|
491
|
-
const prefixedKey = redisInstance.
|
|
506
|
+
const prefixedKey = redisInstance._addPrefix(key);
|
|
492
507
|
result = await connection.exists(prefixedKey) > 0;
|
|
493
508
|
break;
|
|
494
509
|
}
|
|
495
510
|
case 'hset': {
|
|
496
511
|
const [key, field, value] = args;
|
|
497
|
-
const prefixedKey = redisInstance.
|
|
512
|
+
const prefixedKey = redisInstance._addPrefix(key);
|
|
498
513
|
result = await connection.hSet(prefixedKey, field, value);
|
|
499
514
|
break;
|
|
500
515
|
}
|
|
501
516
|
case 'expire': {
|
|
502
517
|
const [key, seconds] = args;
|
|
503
|
-
const prefixedKey = redisInstance.
|
|
518
|
+
const prefixedKey = redisInstance._addPrefix(key);
|
|
504
519
|
result = await connection.expire(prefixedKey, seconds);
|
|
505
520
|
break;
|
|
506
521
|
}
|
|
@@ -513,7 +528,7 @@ Redis.prototype.pipeline = function() {
|
|
|
513
528
|
// 直接返回结果值,符合测试期望的格式
|
|
514
529
|
results.push(result);
|
|
515
530
|
} catch (err) {
|
|
516
|
-
|
|
531
|
+
this.logger('error', `Pipeline命令执行失败 [${cmd[0]}]:`, err);
|
|
517
532
|
results.push(null);
|
|
518
533
|
}
|
|
519
534
|
}
|
|
@@ -522,7 +537,7 @@ Redis.prototype.pipeline = function() {
|
|
|
522
537
|
redisInstance._recycleConnection(connection);
|
|
523
538
|
return results;
|
|
524
539
|
} catch (error) {
|
|
525
|
-
|
|
540
|
+
this.logger('error', 'Pipeline执行失败:', error);
|
|
526
541
|
return [];
|
|
527
542
|
}
|
|
528
543
|
}
|
|
@@ -533,7 +548,7 @@ Redis.prototype.pipeline = function() {
|
|
|
533
548
|
* @description 检查连接状态
|
|
534
549
|
* @return {Boolean} 连接状态
|
|
535
550
|
*/
|
|
536
|
-
Redis.prototype.isConnected = function() {
|
|
551
|
+
Redis.prototype.isConnected = function () {
|
|
537
552
|
return this.connected && this.conn && this.conn.isReady;
|
|
538
553
|
};
|
|
539
554
|
|
|
@@ -549,11 +564,16 @@ Redis.prototype.isConnected = function() {
|
|
|
549
564
|
* @param {Number} [seconds] 过期时间(秒),不传此参数则获取剩余过期时间
|
|
550
565
|
* @return {Promise<Number|Boolean>} 不传seconds时返回剩余过期时间(-1表示无过期设置,-2表示已过期),传seconds时返回是否设置成功
|
|
551
566
|
*/
|
|
552
|
-
Redis.prototype.ttl = async function(key, seconds) {
|
|
567
|
+
Redis.prototype.ttl = async function (key, seconds) {
|
|
553
568
|
try {
|
|
569
|
+
// 参数验证
|
|
570
|
+
if (!key || typeof key !== 'string') {
|
|
571
|
+
throw new TypeError('key必须是非空字符串');
|
|
572
|
+
}
|
|
573
|
+
|
|
554
574
|
const connection = await this._getConnection();
|
|
555
575
|
try {
|
|
556
|
-
key = this.
|
|
576
|
+
key = this._addPrefix(key);
|
|
557
577
|
|
|
558
578
|
// 如果传入了seconds参数,则设置过期时间
|
|
559
579
|
if (seconds !== undefined) {
|
|
@@ -569,7 +589,7 @@ Redis.prototype.ttl = async function(key, seconds) {
|
|
|
569
589
|
await connection.execute('EXPIRE', [key, seconds]);
|
|
570
590
|
return true;
|
|
571
591
|
} else {
|
|
572
|
-
|
|
592
|
+
this.logger('error', '连接对象不支持expire操作');
|
|
573
593
|
return false;
|
|
574
594
|
}
|
|
575
595
|
}
|
|
@@ -580,14 +600,14 @@ Redis.prototype.ttl = async function(key, seconds) {
|
|
|
580
600
|
} else if (typeof connection.execute === 'function') {
|
|
581
601
|
return await connection.execute('TTL', [key]);
|
|
582
602
|
} else {
|
|
583
|
-
|
|
603
|
+
this.logger('error', '连接对象不支持ttl操作');
|
|
584
604
|
return -2; // 默认返回键不存在
|
|
585
605
|
}
|
|
586
606
|
} finally {
|
|
587
607
|
this._recycleConnection(connection);
|
|
588
608
|
}
|
|
589
609
|
} catch (err) {
|
|
590
|
-
|
|
610
|
+
this.logger('error', `${seconds !== undefined ? '设置' : '获取'}过期时间失败 [${key}]:`, err);
|
|
591
611
|
return seconds !== undefined ? false : -2;
|
|
592
612
|
}
|
|
593
613
|
};
|
|
@@ -599,30 +619,30 @@ Redis.prototype.ttl = async function(key, seconds) {
|
|
|
599
619
|
* @param {Number} [seconds=0] 过期时间(秒)
|
|
600
620
|
* @return {Promise<Number>} 计算后的结果
|
|
601
621
|
*/
|
|
602
|
-
Redis.prototype.addInt = async function(key, num, seconds = 0) {
|
|
622
|
+
Redis.prototype.addInt = async function (key, num, seconds = 0) {
|
|
603
623
|
try {
|
|
604
624
|
// 参数验证
|
|
605
625
|
if (!key || typeof key !== 'string') {
|
|
606
|
-
|
|
626
|
+
this.logger('error', '参数错误: 键必须是非空字符串');
|
|
607
627
|
return false;
|
|
608
628
|
}
|
|
609
629
|
if (typeof num !== 'number' || isNaN(num) || !Number.isInteger(num)) {
|
|
610
|
-
|
|
630
|
+
this.logger('error', '参数错误: 数值必须是有效整数');
|
|
611
631
|
return false;
|
|
612
632
|
}
|
|
613
633
|
|
|
614
634
|
// 触发前置事件,允许修改或阻止操作
|
|
615
|
-
const
|
|
635
|
+
const ctx = {
|
|
616
636
|
key,
|
|
617
637
|
value: num,
|
|
618
638
|
seconds,
|
|
619
639
|
cancel: false
|
|
620
640
|
};
|
|
621
|
-
this.emit('
|
|
641
|
+
this.emit('addInt:before', ctx);
|
|
622
642
|
|
|
623
643
|
// 如果事件处理器标记为取消,则返回false
|
|
624
|
-
if (
|
|
625
|
-
|
|
644
|
+
if (ctx.cancel) {
|
|
645
|
+
this.logger('debug', `addInt操作被事件处理器取消 [${key}]`);
|
|
626
646
|
return false;
|
|
627
647
|
}
|
|
628
648
|
|
|
@@ -631,11 +651,11 @@ Redis.prototype.addInt = async function(key, num, seconds = 0) {
|
|
|
631
651
|
key: finalKey,
|
|
632
652
|
value: finalNum,
|
|
633
653
|
seconds: finalSeconds
|
|
634
|
-
} =
|
|
654
|
+
} = ctx;
|
|
635
655
|
|
|
636
656
|
const connection = await this._getConnection();
|
|
637
657
|
try {
|
|
638
|
-
const prefixedKey = this.
|
|
658
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
639
659
|
let result;
|
|
640
660
|
if (finalNum > 0) {
|
|
641
661
|
// 增加整数值
|
|
@@ -645,7 +665,7 @@ Redis.prototype.addInt = async function(key, num, seconds = 0) {
|
|
|
645
665
|
result = await connection.execute('INCRBY', [prefixedKey, finalNum]);
|
|
646
666
|
} else {
|
|
647
667
|
// 如果出错,回退到先获取再设置的方式
|
|
648
|
-
|
|
668
|
+
this.logger('warn', `使用原子操作增加整数值失败,使用回退方案 [${key}]`);
|
|
649
669
|
let value = await this.get(prefixedKey);
|
|
650
670
|
let n = 0;
|
|
651
671
|
if (value) {
|
|
@@ -663,7 +683,7 @@ Redis.prototype.addInt = async function(key, num, seconds = 0) {
|
|
|
663
683
|
result = await connection.execute('DECRBY', [prefixedKey, -finalNum]);
|
|
664
684
|
} else {
|
|
665
685
|
// 如果出错,回退到先获取再设置的方式
|
|
666
|
-
|
|
686
|
+
this.logger('warn', `使用原子操作减少整数值失败,使用回退方案`);
|
|
667
687
|
let value = await this.get(prefixedKey);
|
|
668
688
|
let n = 0;
|
|
669
689
|
if (value) {
|
|
@@ -685,7 +705,7 @@ Redis.prototype.addInt = async function(key, num, seconds = 0) {
|
|
|
685
705
|
}
|
|
686
706
|
|
|
687
707
|
// 触发后置事件
|
|
688
|
-
this.emit('
|
|
708
|
+
this.emit('addInt:after', {
|
|
689
709
|
key: finalKey,
|
|
690
710
|
value: finalNum,
|
|
691
711
|
seconds: finalSeconds,
|
|
@@ -698,13 +718,13 @@ Redis.prototype.addInt = async function(key, num, seconds = 0) {
|
|
|
698
718
|
}
|
|
699
719
|
} catch (err) {
|
|
700
720
|
// 触发错误事件
|
|
701
|
-
this.emit('
|
|
721
|
+
this.emit('addInt:error', {
|
|
702
722
|
key,
|
|
703
723
|
value: num,
|
|
704
724
|
seconds,
|
|
705
725
|
error: err
|
|
706
726
|
});
|
|
707
|
-
|
|
727
|
+
this.logger('error', `增加整数值失败 [${key}]:`, err);
|
|
708
728
|
// 与CacheBase保持一致,错误时返回默认值而不是抛出异常
|
|
709
729
|
return 0;
|
|
710
730
|
}
|
|
@@ -717,33 +737,31 @@ Redis.prototype.addInt = async function(key, num, seconds = 0) {
|
|
|
717
737
|
* @param {Number} seconds 过期时间,0表示永不过期
|
|
718
738
|
* @return {Promise<Number>} 计算后的结果
|
|
719
739
|
*/
|
|
720
|
-
Redis.prototype.addFloat = async function(key, num, seconds = 0) {
|
|
740
|
+
Redis.prototype.addFloat = async function (key, num, seconds = 0) {
|
|
721
741
|
try {
|
|
722
742
|
// 参数验证
|
|
723
743
|
if (!key || typeof key !== 'string') {
|
|
724
|
-
|
|
725
|
-
return 0;
|
|
744
|
+
throw new TypeError('key必须是非空字符串');
|
|
726
745
|
}
|
|
727
746
|
|
|
728
747
|
// 验证num参数
|
|
729
748
|
num = parseFloat(num);
|
|
730
749
|
if (isNaN(num)) {
|
|
731
|
-
|
|
732
|
-
return 0;
|
|
750
|
+
throw new TypeError('num必须是有效的数值');
|
|
733
751
|
}
|
|
734
752
|
|
|
735
753
|
// 触发前置事件,允许修改或阻止操作
|
|
736
|
-
const
|
|
754
|
+
const ctx = {
|
|
737
755
|
key,
|
|
738
756
|
value: num,
|
|
739
757
|
seconds,
|
|
740
758
|
cancel: false
|
|
741
759
|
};
|
|
742
|
-
this.emit('
|
|
760
|
+
this.emit('addFloat:before', ctx);
|
|
743
761
|
|
|
744
762
|
// 如果事件处理器标记为取消,则返回默认值
|
|
745
|
-
if (
|
|
746
|
-
|
|
763
|
+
if (ctx.cancel) {
|
|
764
|
+
this.logger('debug', `addFloat操作被事件处理器取消 [${key}]`);
|
|
747
765
|
return 0;
|
|
748
766
|
}
|
|
749
767
|
|
|
@@ -752,12 +770,12 @@ Redis.prototype.addFloat = async function(key, num, seconds = 0) {
|
|
|
752
770
|
key: finalKey,
|
|
753
771
|
value: finalNum,
|
|
754
772
|
seconds: finalSeconds
|
|
755
|
-
} =
|
|
773
|
+
} = ctx;
|
|
756
774
|
let result;
|
|
757
775
|
|
|
758
776
|
const connection = await this._getConnection();
|
|
759
777
|
try {
|
|
760
|
-
const prefixedKey = this.
|
|
778
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
761
779
|
|
|
762
780
|
// 优先使用原生方法
|
|
763
781
|
if (typeof connection.incrByFloat === 'function') {
|
|
@@ -769,7 +787,7 @@ Redis.prototype.addFloat = async function(key, num, seconds = 0) {
|
|
|
769
787
|
}
|
|
770
788
|
// 回退方案
|
|
771
789
|
else {
|
|
772
|
-
|
|
790
|
+
this.logger('warn', `连接对象不支持incrByFloat操作,使用回退方案`);
|
|
773
791
|
let value = await this.get(prefixedKey);
|
|
774
792
|
let n = 0;
|
|
775
793
|
if (value) {
|
|
@@ -790,7 +808,7 @@ Redis.prototype.addFloat = async function(key, num, seconds = 0) {
|
|
|
790
808
|
}
|
|
791
809
|
|
|
792
810
|
// 触发后置事件
|
|
793
|
-
this.emit('
|
|
811
|
+
this.emit('addFloat:after', {
|
|
794
812
|
key: finalKey,
|
|
795
813
|
value: finalNum,
|
|
796
814
|
seconds: finalSeconds,
|
|
@@ -800,7 +818,7 @@ Redis.prototype.addFloat = async function(key, num, seconds = 0) {
|
|
|
800
818
|
return result;
|
|
801
819
|
} catch (err) {
|
|
802
820
|
// 如果出错,回退到先获取再设置的方式
|
|
803
|
-
|
|
821
|
+
this.logger('warn', `使用原子操作增加浮点数值失败,使用回退方案:`, err);
|
|
804
822
|
let value = await this.get(prefixedKey);
|
|
805
823
|
let n = 0;
|
|
806
824
|
if (value) {
|
|
@@ -810,7 +828,7 @@ Redis.prototype.addFloat = async function(key, num, seconds = 0) {
|
|
|
810
828
|
await this.set(prefixedKey, n, finalSeconds);
|
|
811
829
|
|
|
812
830
|
// 触发后置事件
|
|
813
|
-
this.emit('
|
|
831
|
+
this.emit('addFloat:after', {
|
|
814
832
|
key: finalKey,
|
|
815
833
|
value: finalNum,
|
|
816
834
|
seconds: finalSeconds,
|
|
@@ -823,13 +841,13 @@ Redis.prototype.addFloat = async function(key, num, seconds = 0) {
|
|
|
823
841
|
}
|
|
824
842
|
} catch (err) {
|
|
825
843
|
// 触发错误事件
|
|
826
|
-
this.emit('
|
|
844
|
+
this.emit('addFloat:error', {
|
|
827
845
|
key,
|
|
828
846
|
value: num,
|
|
829
847
|
seconds,
|
|
830
848
|
error: err
|
|
831
849
|
});
|
|
832
|
-
|
|
850
|
+
this.logger('error', `增加浮点数值失败 [${key}]:`, err);
|
|
833
851
|
// 与CacheBase保持一致,错误时返回默认值而不是抛出异常
|
|
834
852
|
return 0;
|
|
835
853
|
}
|
|
@@ -842,33 +860,31 @@ Redis.prototype.addFloat = async function(key, num, seconds = 0) {
|
|
|
842
860
|
* @param {Number} seconds 过期时间,0表示永不过期
|
|
843
861
|
* @return {Promise<Number>} 添加后的字符串长度
|
|
844
862
|
*/
|
|
845
|
-
Redis.prototype.addStr = async function(key, str, seconds = 0) {
|
|
863
|
+
Redis.prototype.addStr = async function (key, str, seconds = 0) {
|
|
846
864
|
try {
|
|
847
865
|
// 参数验证
|
|
848
866
|
if (!key || typeof key !== 'string') {
|
|
849
|
-
|
|
850
|
-
return 0;
|
|
867
|
+
throw new TypeError('key必须是非空字符串');
|
|
851
868
|
}
|
|
852
869
|
|
|
853
870
|
// 验证str参数
|
|
854
871
|
if (str === undefined || str === null) {
|
|
855
|
-
|
|
856
|
-
return 0;
|
|
872
|
+
throw new TypeError('str不能为undefined或null');
|
|
857
873
|
}
|
|
858
874
|
str = String(str);
|
|
859
875
|
|
|
860
876
|
// 触发前置事件,允许修改或阻止操作
|
|
861
|
-
const
|
|
877
|
+
const ctx = {
|
|
862
878
|
key,
|
|
863
879
|
value: str,
|
|
864
880
|
seconds,
|
|
865
881
|
cancel: false
|
|
866
882
|
};
|
|
867
|
-
this.emit('
|
|
883
|
+
this.emit('addStr:before', ctx);
|
|
868
884
|
|
|
869
885
|
// 如果事件处理器标记为取消,则返回0
|
|
870
|
-
if (
|
|
871
|
-
|
|
886
|
+
if (ctx.cancel) {
|
|
887
|
+
this.logger('debug', `addStr操作被事件处理器取消 [${key}]`);
|
|
872
888
|
return 0;
|
|
873
889
|
}
|
|
874
890
|
|
|
@@ -877,12 +893,12 @@ Redis.prototype.addStr = async function(key, str, seconds = 0) {
|
|
|
877
893
|
key: finalKey,
|
|
878
894
|
value: finalStr,
|
|
879
895
|
seconds: finalSeconds
|
|
880
|
-
} =
|
|
896
|
+
} = ctx;
|
|
881
897
|
let result;
|
|
882
898
|
|
|
883
899
|
const connection = await this._getConnection();
|
|
884
900
|
try {
|
|
885
|
-
const prefixedKey = this.
|
|
901
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
886
902
|
|
|
887
903
|
// 优先使用原生方法
|
|
888
904
|
if (typeof connection.append === 'function') {
|
|
@@ -894,7 +910,7 @@ Redis.prototype.addStr = async function(key, str, seconds = 0) {
|
|
|
894
910
|
}
|
|
895
911
|
// 回退方案
|
|
896
912
|
else {
|
|
897
|
-
|
|
913
|
+
this.logger('warn', `连接对象不支持append操作,使用回退方案`);
|
|
898
914
|
let value = await this.get(prefixedKey) || '';
|
|
899
915
|
value += finalStr;
|
|
900
916
|
await this.set(prefixedKey, value, finalSeconds);
|
|
@@ -911,7 +927,7 @@ Redis.prototype.addStr = async function(key, str, seconds = 0) {
|
|
|
911
927
|
}
|
|
912
928
|
|
|
913
929
|
// 触发后置事件
|
|
914
|
-
this.emit('
|
|
930
|
+
this.emit('addStr:after', {
|
|
915
931
|
key: finalKey,
|
|
916
932
|
value: finalStr,
|
|
917
933
|
seconds: finalSeconds,
|
|
@@ -920,14 +936,14 @@ Redis.prototype.addStr = async function(key, str, seconds = 0) {
|
|
|
920
936
|
});
|
|
921
937
|
return result;
|
|
922
938
|
} catch (err) {
|
|
923
|
-
|
|
939
|
+
this.logger('warn', '追加字符串失败:', err);
|
|
924
940
|
// 回退方案:先获取再设置
|
|
925
941
|
let value = await this.get(prefixedKey) || '';
|
|
926
942
|
value += finalStr;
|
|
927
943
|
await this.set(prefixedKey, value, finalSeconds);
|
|
928
944
|
|
|
929
945
|
// 触发后置事件
|
|
930
|
-
this.emit('
|
|
946
|
+
this.emit('addStr:after', {
|
|
931
947
|
key: finalKey,
|
|
932
948
|
value: finalStr,
|
|
933
949
|
seconds: finalSeconds,
|
|
@@ -940,13 +956,13 @@ Redis.prototype.addStr = async function(key, str, seconds = 0) {
|
|
|
940
956
|
}
|
|
941
957
|
} catch (err) {
|
|
942
958
|
// 触发错误事件
|
|
943
|
-
this.emit('
|
|
959
|
+
this.emit('addStr:error', {
|
|
944
960
|
key,
|
|
945
961
|
value: str,
|
|
946
962
|
seconds,
|
|
947
963
|
error: err
|
|
948
964
|
});
|
|
949
|
-
|
|
965
|
+
this.logger('error', `追加字符串失败 [${key}]:`, err);
|
|
950
966
|
return 0;
|
|
951
967
|
}
|
|
952
968
|
};
|
|
@@ -956,51 +972,47 @@ Redis.prototype.addStr = async function(key, str, seconds = 0) {
|
|
|
956
972
|
* @param {String|Array<String>} key 键或键数组
|
|
957
973
|
* @return {Promise<Boolean>} 成功返回true,失败返回false
|
|
958
974
|
*/
|
|
959
|
-
Redis.prototype.del = async function(key) {
|
|
975
|
+
Redis.prototype.del = async function (key) {
|
|
960
976
|
try {
|
|
961
977
|
// 键名必须是非空字符串或非空字符串数组
|
|
962
978
|
if (!key) {
|
|
963
|
-
|
|
964
|
-
return false;
|
|
979
|
+
throw new TypeError('key必须是非空字符串或非空字符串数组');
|
|
965
980
|
}
|
|
966
981
|
|
|
967
982
|
// 如果是单个键,验证是否为非空字符串
|
|
968
983
|
if (typeof key === 'string') {
|
|
969
984
|
if (!key) {
|
|
970
|
-
|
|
971
|
-
return false;
|
|
985
|
+
throw new TypeError('key必须是非空字符串');
|
|
972
986
|
}
|
|
973
987
|
}
|
|
974
988
|
// 如果是数组,验证每个元素是否为非空字符串
|
|
975
989
|
else if (Array.isArray(key)) {
|
|
976
990
|
for (const k of key) {
|
|
977
991
|
if (!k || typeof k !== 'string') {
|
|
978
|
-
|
|
979
|
-
return false;
|
|
992
|
+
throw new TypeError('key必须是非空字符串或非空字符串数组');
|
|
980
993
|
}
|
|
981
994
|
}
|
|
982
995
|
} else {
|
|
983
|
-
|
|
984
|
-
return false;
|
|
996
|
+
throw new TypeError('key必须是非空字符串或非空字符串数组');
|
|
985
997
|
}
|
|
986
998
|
|
|
987
999
|
// 触发前置事件,允许修改或阻止操作
|
|
988
|
-
const
|
|
1000
|
+
const ctx = {
|
|
989
1001
|
key,
|
|
990
1002
|
cancel: false
|
|
991
1003
|
};
|
|
992
|
-
this.emit('
|
|
1004
|
+
this.emit('del:before', ctx);
|
|
993
1005
|
|
|
994
1006
|
// 如果事件处理器标记为取消,则返回false
|
|
995
|
-
if (
|
|
996
|
-
|
|
1007
|
+
if (ctx.cancel) {
|
|
1008
|
+
this.logger('debug', `del操作被事件处理器取消 [${key}]`);
|
|
997
1009
|
return false;
|
|
998
1010
|
}
|
|
999
1011
|
|
|
1000
1012
|
// 使用可能被修改的值
|
|
1001
1013
|
let {
|
|
1002
1014
|
key: finalKey
|
|
1003
|
-
} =
|
|
1015
|
+
} = ctx;
|
|
1004
1016
|
|
|
1005
1017
|
const connection = await this._getConnection();
|
|
1006
1018
|
try {
|
|
@@ -1010,7 +1022,7 @@ Redis.prototype.del = async function(key) {
|
|
|
1010
1022
|
success = true;
|
|
1011
1023
|
const deleted = [];
|
|
1012
1024
|
for (const k of finalKey) {
|
|
1013
|
-
const prefixedKey = this.
|
|
1025
|
+
const prefixedKey = this._addPrefix(k);
|
|
1014
1026
|
const result = await connection.del(prefixedKey);
|
|
1015
1027
|
if (result !== 1) {
|
|
1016
1028
|
success = false;
|
|
@@ -1019,18 +1031,18 @@ Redis.prototype.del = async function(key) {
|
|
|
1019
1031
|
}
|
|
1020
1032
|
}
|
|
1021
1033
|
// 触发后置事件
|
|
1022
|
-
this.emit('
|
|
1034
|
+
this.emit('del:after', {
|
|
1023
1035
|
key: finalKey,
|
|
1024
1036
|
success,
|
|
1025
1037
|
deleted
|
|
1026
1038
|
});
|
|
1027
1039
|
} else {
|
|
1028
1040
|
// 单个删除
|
|
1029
|
-
const prefixedKey = this.
|
|
1041
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
1030
1042
|
const n = await connection.del(prefixedKey);
|
|
1031
1043
|
success = n === 1;
|
|
1032
1044
|
// 触发后置事件
|
|
1033
|
-
this.emit('
|
|
1045
|
+
this.emit('del:after', {
|
|
1034
1046
|
key: finalKey,
|
|
1035
1047
|
success,
|
|
1036
1048
|
deleted: success ? [finalKey] : []
|
|
@@ -1042,11 +1054,11 @@ Redis.prototype.del = async function(key) {
|
|
|
1042
1054
|
}
|
|
1043
1055
|
} catch (err) {
|
|
1044
1056
|
// 触发错误事件
|
|
1045
|
-
this.emit('
|
|
1057
|
+
this.emit('del:error', {
|
|
1046
1058
|
key,
|
|
1047
1059
|
error: err
|
|
1048
1060
|
});
|
|
1049
|
-
|
|
1061
|
+
this.logger('error', `删除缓存失败 [${key}]:`, err);
|
|
1050
1062
|
return false;
|
|
1051
1063
|
}
|
|
1052
1064
|
};
|
|
@@ -1065,26 +1077,25 @@ Redis.prototype.del = async function(key) {
|
|
|
1065
1077
|
* @param {Number} seconds 过期时间,0表示永不过期
|
|
1066
1078
|
* @return {Promise<Boolean>} 成功返回true,失败返回false
|
|
1067
1079
|
*/
|
|
1068
|
-
Redis.prototype.set = async function(key, value, seconds = 0) {
|
|
1080
|
+
Redis.prototype.set = async function (key, value, seconds = 0) {
|
|
1069
1081
|
try {
|
|
1070
1082
|
// 键名必须是非空字符串
|
|
1071
1083
|
if (!key || typeof key !== 'string') {
|
|
1072
|
-
|
|
1073
|
-
return false;
|
|
1084
|
+
throw new TypeError('key必须是非空字符串');
|
|
1074
1085
|
}
|
|
1075
1086
|
|
|
1076
1087
|
// 触发前置事件,允许修改或阻止操作
|
|
1077
|
-
const
|
|
1088
|
+
const ctx = {
|
|
1078
1089
|
key,
|
|
1079
1090
|
value,
|
|
1080
1091
|
seconds,
|
|
1081
1092
|
cancel: false
|
|
1082
1093
|
};
|
|
1083
|
-
this.emit('
|
|
1094
|
+
this.emit('set:before', ctx);
|
|
1084
1095
|
|
|
1085
1096
|
// 如果事件处理器标记为取消,则返回false
|
|
1086
|
-
if (
|
|
1087
|
-
|
|
1097
|
+
if (ctx.cancel) {
|
|
1098
|
+
this.logger('debug', `set操作被事件处理器取消 [${key}]`);
|
|
1088
1099
|
return false;
|
|
1089
1100
|
}
|
|
1090
1101
|
|
|
@@ -1093,12 +1104,12 @@ Redis.prototype.set = async function(key, value, seconds = 0) {
|
|
|
1093
1104
|
key: finalKey,
|
|
1094
1105
|
value: finalValue,
|
|
1095
1106
|
seconds: finalSeconds
|
|
1096
|
-
} =
|
|
1107
|
+
} = ctx;
|
|
1097
1108
|
|
|
1098
1109
|
const connection = await this._getConnection();
|
|
1099
1110
|
try {
|
|
1100
|
-
const prefixedKey = this.
|
|
1101
|
-
if (typeof(finalValue) === "object") {
|
|
1111
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
1112
|
+
if (typeof (finalValue) === "object") {
|
|
1102
1113
|
finalValue = JSON.stringify(finalValue);
|
|
1103
1114
|
}
|
|
1104
1115
|
|
|
@@ -1111,7 +1122,7 @@ Redis.prototype.set = async function(key, value, seconds = 0) {
|
|
|
1111
1122
|
}
|
|
1112
1123
|
|
|
1113
1124
|
// 触发后置事件
|
|
1114
|
-
this.emit('
|
|
1125
|
+
this.emit('set:after', {
|
|
1115
1126
|
key,
|
|
1116
1127
|
value,
|
|
1117
1128
|
seconds,
|
|
@@ -1122,9 +1133,9 @@ Redis.prototype.set = async function(key, value, seconds = 0) {
|
|
|
1122
1133
|
this._recycleConnection(connection);
|
|
1123
1134
|
}
|
|
1124
1135
|
} catch (err) {
|
|
1125
|
-
|
|
1136
|
+
this.logger('error', `设置缓存失败 [${key}]:`, err);
|
|
1126
1137
|
// 触发错误事件
|
|
1127
|
-
this.emit('
|
|
1138
|
+
this.emit('set:error', {
|
|
1128
1139
|
key,
|
|
1129
1140
|
value,
|
|
1130
1141
|
seconds,
|
|
@@ -1141,20 +1152,28 @@ Redis.prototype.set = async function(key, value, seconds = 0) {
|
|
|
1141
1152
|
* @param {Number} seconds 过期时间(秒)
|
|
1142
1153
|
* @return {Promise<Boolean>} 操作结果,键不存在时设置成功返回true,键已存在返回false
|
|
1143
1154
|
*/
|
|
1144
|
-
Redis.prototype.add = async function(key, value, seconds) {
|
|
1155
|
+
Redis.prototype.add = async function (key, value, seconds) {
|
|
1145
1156
|
try {
|
|
1157
|
+
// 参数验证
|
|
1158
|
+
if (!key || typeof key !== 'string') {
|
|
1159
|
+
throw new TypeError('key必须是非空字符串');
|
|
1160
|
+
}
|
|
1161
|
+
if (value === undefined || value === null) {
|
|
1162
|
+
throw new TypeError('value不能为undefined或null');
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1146
1165
|
// 触发前置事件,允许修改或阻止操作
|
|
1147
|
-
const
|
|
1166
|
+
const ctx = {
|
|
1148
1167
|
key,
|
|
1149
1168
|
value,
|
|
1150
1169
|
ttl: seconds,
|
|
1151
1170
|
cancel: false
|
|
1152
1171
|
};
|
|
1153
|
-
this.emit('
|
|
1172
|
+
this.emit('add:before', ctx);
|
|
1154
1173
|
|
|
1155
1174
|
// 如果事件处理器标记为取消,则返回false
|
|
1156
|
-
if (
|
|
1157
|
-
|
|
1175
|
+
if (ctx.cancel) {
|
|
1176
|
+
this.logger('debug', `add操作被事件处理器取消 [${key}]`);
|
|
1158
1177
|
return false;
|
|
1159
1178
|
}
|
|
1160
1179
|
|
|
@@ -1163,12 +1182,12 @@ Redis.prototype.add = async function(key, value, seconds) {
|
|
|
1163
1182
|
key: finalKey,
|
|
1164
1183
|
value: finalValue,
|
|
1165
1184
|
ttl: finalSeconds
|
|
1166
|
-
} =
|
|
1185
|
+
} = ctx;
|
|
1167
1186
|
|
|
1168
1187
|
const connection = await this._getConnection();
|
|
1169
1188
|
try {
|
|
1170
|
-
finalKey = this.
|
|
1171
|
-
if (typeof(finalValue) === "object") {
|
|
1189
|
+
finalKey = this._addPrefix(finalKey);
|
|
1190
|
+
if (typeof (finalValue) === "object") {
|
|
1172
1191
|
finalValue = JSON.stringify(finalValue);
|
|
1173
1192
|
}
|
|
1174
1193
|
|
|
@@ -1183,7 +1202,7 @@ Redis.prototype.add = async function(key, value, seconds) {
|
|
|
1183
1202
|
const success = result === "OK";
|
|
1184
1203
|
|
|
1185
1204
|
// 触发后置事件
|
|
1186
|
-
this.emit('
|
|
1205
|
+
this.emit('add:after', {
|
|
1187
1206
|
key: finalKey,
|
|
1188
1207
|
value: finalValue,
|
|
1189
1208
|
ttl: finalSeconds,
|
|
@@ -1194,9 +1213,9 @@ Redis.prototype.add = async function(key, value, seconds) {
|
|
|
1194
1213
|
this._recycleConnection(connection);
|
|
1195
1214
|
}
|
|
1196
1215
|
} catch (err) {
|
|
1197
|
-
|
|
1216
|
+
this.logger('error', `添加缓存失败 [${key}]:`, err);
|
|
1198
1217
|
// 触发错误事件
|
|
1199
|
-
this.emit('
|
|
1218
|
+
this.emit('add:error', {
|
|
1200
1219
|
key,
|
|
1201
1220
|
value,
|
|
1202
1221
|
ttl: seconds,
|
|
@@ -1216,36 +1235,35 @@ Redis.prototype.add = async function(key, value, seconds) {
|
|
|
1216
1235
|
* @param {String} key 键
|
|
1217
1236
|
* @return {Promise<*>} 获取到的值,不存在时返回null
|
|
1218
1237
|
*/
|
|
1219
|
-
Redis.prototype.get = async function(key) {
|
|
1238
|
+
Redis.prototype.get = async function (key) {
|
|
1220
1239
|
try {
|
|
1221
1240
|
// 参数验证
|
|
1222
1241
|
if (!key || typeof key !== 'string') {
|
|
1223
|
-
|
|
1224
|
-
return null;
|
|
1242
|
+
throw new TypeError('key必须是非空字符串');
|
|
1225
1243
|
}
|
|
1226
1244
|
|
|
1227
1245
|
// 触发前置事件,允许修改或阻止操作
|
|
1228
|
-
const
|
|
1246
|
+
const ctx = {
|
|
1229
1247
|
key,
|
|
1230
1248
|
cancel: false
|
|
1231
1249
|
};
|
|
1232
|
-
this.emit('
|
|
1250
|
+
this.emit('get:before', ctx);
|
|
1233
1251
|
|
|
1234
1252
|
// 如果事件处理器标记为取消,则返回null
|
|
1235
|
-
if (
|
|
1236
|
-
|
|
1253
|
+
if (ctx.cancel) {
|
|
1254
|
+
this.logger('debug', `get操作被事件处理器取消 [${key}]`);
|
|
1237
1255
|
return null;
|
|
1238
1256
|
}
|
|
1239
1257
|
|
|
1240
1258
|
// 使用可能被修改的值
|
|
1241
|
-
const finalKey =
|
|
1259
|
+
const finalKey = ctx.key;
|
|
1242
1260
|
|
|
1243
1261
|
const connection = await this._getConnection();
|
|
1244
1262
|
try {
|
|
1245
|
-
const prefixedKey = this.
|
|
1263
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
1246
1264
|
const value = await connection.get(prefixedKey);
|
|
1247
1265
|
let result = value;
|
|
1248
|
-
if (typeof(value) === "string") {
|
|
1266
|
+
if (typeof (value) === "string") {
|
|
1249
1267
|
// 尝试解析JSON
|
|
1250
1268
|
try {
|
|
1251
1269
|
if (value.startsWith("{") && value.endsWith("}") ||
|
|
@@ -1258,7 +1276,7 @@ Redis.prototype.get = async function(key) {
|
|
|
1258
1276
|
}
|
|
1259
1277
|
|
|
1260
1278
|
// 触发后置事件
|
|
1261
|
-
this.emit('
|
|
1279
|
+
this.emit('get:after', {
|
|
1262
1280
|
key: finalKey,
|
|
1263
1281
|
value: result,
|
|
1264
1282
|
success: true
|
|
@@ -1270,11 +1288,11 @@ Redis.prototype.get = async function(key) {
|
|
|
1270
1288
|
}
|
|
1271
1289
|
} catch (err) {
|
|
1272
1290
|
// 触发错误事件
|
|
1273
|
-
this.emit('
|
|
1291
|
+
this.emit('get:error', {
|
|
1274
1292
|
key,
|
|
1275
1293
|
error: err
|
|
1276
1294
|
});
|
|
1277
|
-
|
|
1295
|
+
this.logger('error', `获取缓存失败 [${key}]:`, err);
|
|
1278
1296
|
return null;
|
|
1279
1297
|
}
|
|
1280
1298
|
};
|
|
@@ -1284,38 +1302,37 @@ Redis.prototype.get = async function(key) {
|
|
|
1284
1302
|
* @param {String} key 键
|
|
1285
1303
|
* @return {Promise<Boolean>} 有返回true, 没有返回false
|
|
1286
1304
|
*/
|
|
1287
|
-
Redis.prototype.has = async function(key) {
|
|
1305
|
+
Redis.prototype.has = async function (key) {
|
|
1288
1306
|
try {
|
|
1289
1307
|
// 参数验证
|
|
1290
1308
|
if (!key || typeof key !== 'string') {
|
|
1291
|
-
|
|
1292
|
-
return false;
|
|
1309
|
+
throw new TypeError('key必须是非空字符串');
|
|
1293
1310
|
}
|
|
1294
1311
|
|
|
1295
1312
|
// 触发前置事件,允许修改或阻止操作
|
|
1296
|
-
const
|
|
1313
|
+
const ctx = {
|
|
1297
1314
|
key,
|
|
1298
1315
|
cancel: false
|
|
1299
1316
|
};
|
|
1300
|
-
this.emit('
|
|
1317
|
+
this.emit('has:before', ctx);
|
|
1301
1318
|
|
|
1302
1319
|
// 如果事件处理器标记为取消,则返回false
|
|
1303
|
-
if (
|
|
1304
|
-
|
|
1320
|
+
if (ctx.cancel) {
|
|
1321
|
+
this.logger('debug', `has操作被事件处理器取消 [${key}]`);
|
|
1305
1322
|
return false;
|
|
1306
1323
|
}
|
|
1307
1324
|
|
|
1308
1325
|
// 使用可能被修改的值
|
|
1309
|
-
const finalKey =
|
|
1326
|
+
const finalKey = ctx.key;
|
|
1310
1327
|
|
|
1311
1328
|
const connection = await this._getConnection();
|
|
1312
1329
|
try {
|
|
1313
|
-
const prefixedKey = this.
|
|
1330
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
1314
1331
|
const result = await connection.exists(prefixedKey);
|
|
1315
1332
|
const exists = result > 0;
|
|
1316
1333
|
|
|
1317
1334
|
// 触发后置事件
|
|
1318
|
-
this.emit('
|
|
1335
|
+
this.emit('has:after', {
|
|
1319
1336
|
key: finalKey,
|
|
1320
1337
|
result: exists,
|
|
1321
1338
|
success: true
|
|
@@ -1327,11 +1344,11 @@ Redis.prototype.has = async function(key) {
|
|
|
1327
1344
|
}
|
|
1328
1345
|
} catch (err) {
|
|
1329
1346
|
// 触发错误事件
|
|
1330
|
-
this.emit('
|
|
1347
|
+
this.emit('has:error', {
|
|
1331
1348
|
key,
|
|
1332
1349
|
error: err
|
|
1333
1350
|
});
|
|
1334
|
-
|
|
1351
|
+
this.logger('error', `检查键是否存在失败 [${key}]:`, err);
|
|
1335
1352
|
return false;
|
|
1336
1353
|
}
|
|
1337
1354
|
};
|
|
@@ -1341,63 +1358,59 @@ Redis.prototype.has = async function(key) {
|
|
|
1341
1358
|
* @param {String|Array<String>} key 键或键数组
|
|
1342
1359
|
* @return {Promise<Number>} 存在的键数量
|
|
1343
1360
|
*/
|
|
1344
|
-
Redis.prototype.exists = async function(key) {
|
|
1361
|
+
Redis.prototype.exists = async function (key) {
|
|
1345
1362
|
try {
|
|
1346
1363
|
// 参数验证
|
|
1347
1364
|
if (!key) {
|
|
1348
|
-
|
|
1349
|
-
return 0;
|
|
1365
|
+
throw new TypeError('key必须是非空字符串或非空字符串数组');
|
|
1350
1366
|
}
|
|
1351
1367
|
|
|
1352
1368
|
// 如果是单个键,验证是否为非空字符串
|
|
1353
1369
|
if (typeof key === 'string') {
|
|
1354
1370
|
if (!key) {
|
|
1355
|
-
|
|
1356
|
-
return 0;
|
|
1371
|
+
throw new TypeError('key必须是非空字符串');
|
|
1357
1372
|
}
|
|
1358
1373
|
}
|
|
1359
1374
|
// 如果是数组,验证每个元素是否为非空字符串
|
|
1360
1375
|
else if (Array.isArray(key)) {
|
|
1361
1376
|
for (const k of key) {
|
|
1362
1377
|
if (!k || typeof k !== 'string') {
|
|
1363
|
-
|
|
1364
|
-
return 0;
|
|
1378
|
+
throw new TypeError('key必须是非空字符串或非空字符串数组');
|
|
1365
1379
|
}
|
|
1366
1380
|
}
|
|
1367
1381
|
} else {
|
|
1368
|
-
|
|
1369
|
-
return 0;
|
|
1382
|
+
throw new TypeError('key必须是非空字符串或非空字符串数组');
|
|
1370
1383
|
}
|
|
1371
1384
|
|
|
1372
1385
|
// 触发前置事件,允许修改或阻止操作
|
|
1373
|
-
const
|
|
1386
|
+
const ctx = {
|
|
1374
1387
|
key,
|
|
1375
1388
|
cancel: false
|
|
1376
1389
|
};
|
|
1377
|
-
this.emit('
|
|
1390
|
+
this.emit('exists:before', ctx);
|
|
1378
1391
|
|
|
1379
1392
|
// 如果事件处理器标记为取消,则返回0
|
|
1380
|
-
if (
|
|
1381
|
-
|
|
1393
|
+
if (ctx.cancel) {
|
|
1394
|
+
this.logger('debug', `exists操作被事件处理器取消 [${key}]`);
|
|
1382
1395
|
return 0;
|
|
1383
1396
|
}
|
|
1384
1397
|
|
|
1385
1398
|
// 使用可能被修改的值
|
|
1386
|
-
const finalKey =
|
|
1399
|
+
const finalKey = ctx.key;
|
|
1387
1400
|
|
|
1388
1401
|
const connection = await this._getConnection();
|
|
1389
1402
|
try {
|
|
1390
1403
|
let result;
|
|
1391
1404
|
if (typeof finalKey === 'string') {
|
|
1392
|
-
const prefixedKey = this.
|
|
1405
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
1393
1406
|
result = await connection.exists(prefixedKey);
|
|
1394
1407
|
} else if (Array.isArray(finalKey)) {
|
|
1395
|
-
const prefixedKeys = finalKey.map(k => this.
|
|
1408
|
+
const prefixedKeys = finalKey.map(k => this._addPrefix(k));
|
|
1396
1409
|
result = await connection.exists(...prefixedKeys);
|
|
1397
1410
|
}
|
|
1398
1411
|
|
|
1399
1412
|
// 触发后置事件
|
|
1400
|
-
this.emit('
|
|
1413
|
+
this.emit('exists:after', {
|
|
1401
1414
|
key: finalKey,
|
|
1402
1415
|
result,
|
|
1403
1416
|
success: true
|
|
@@ -1409,11 +1422,11 @@ Redis.prototype.exists = async function(key) {
|
|
|
1409
1422
|
}
|
|
1410
1423
|
} catch (err) {
|
|
1411
1424
|
// 触发错误事件
|
|
1412
|
-
this.emit('
|
|
1425
|
+
this.emit('exists:error', {
|
|
1413
1426
|
key,
|
|
1414
1427
|
error: err
|
|
1415
1428
|
});
|
|
1416
|
-
|
|
1429
|
+
this.logger('error', `检查键存在性失败 [${key}]:`, err);
|
|
1417
1430
|
return 0;
|
|
1418
1431
|
}
|
|
1419
1432
|
};
|
|
@@ -1425,14 +1438,14 @@ Redis.prototype.exists = async function(key) {
|
|
|
1425
1438
|
* @param {Number} end 结束位置
|
|
1426
1439
|
* @return {Promise<String>} 查询值
|
|
1427
1440
|
*/
|
|
1428
|
-
Redis.prototype.getrange = async function(key, start, end) {
|
|
1441
|
+
Redis.prototype.getrange = async function (key, start, end) {
|
|
1429
1442
|
try {
|
|
1430
1443
|
const connection = await this._getConnection();
|
|
1431
1444
|
try {
|
|
1432
|
-
key = this.
|
|
1445
|
+
key = this._addPrefix(key);
|
|
1433
1446
|
return await connection.getRange(key, start, end);
|
|
1434
1447
|
} catch (err) {
|
|
1435
|
-
|
|
1448
|
+
this.logger('error', '获取字符串范围失败:', err);
|
|
1436
1449
|
// 回退方案
|
|
1437
1450
|
const value = await this.get(key);
|
|
1438
1451
|
if (value && typeof value === 'string') {
|
|
@@ -1443,7 +1456,7 @@ Redis.prototype.getrange = async function(key, start, end) {
|
|
|
1443
1456
|
this._recycleConnection(connection);
|
|
1444
1457
|
}
|
|
1445
1458
|
} catch (err) {
|
|
1446
|
-
|
|
1459
|
+
this.logger('error', `获取字符串范围失败 [${key}]:`, err);
|
|
1447
1460
|
return '';
|
|
1448
1461
|
}
|
|
1449
1462
|
};
|
|
@@ -1455,7 +1468,7 @@ Redis.prototype.getrange = async function(key, start, end) {
|
|
|
1455
1468
|
* @param {String} str_sub 插入的字符串
|
|
1456
1469
|
* @return {String} 插入后的字符串
|
|
1457
1470
|
*/
|
|
1458
|
-
Redis.prototype.insertString = function(str, index, str_sub) {
|
|
1471
|
+
Redis.prototype.insertString = function (str, index, str_sub) {
|
|
1459
1472
|
return str.substring(0, index) + str_sub + str.substring(index);
|
|
1460
1473
|
};
|
|
1461
1474
|
|
|
@@ -1466,20 +1479,20 @@ Redis.prototype.insertString = function(str, index, str_sub) {
|
|
|
1466
1479
|
* @param {String} value 变更的值
|
|
1467
1480
|
* @return {Promise<Number>} 字符串长度
|
|
1468
1481
|
*/
|
|
1469
|
-
Redis.prototype.setrange = async function(key, index, value) {
|
|
1482
|
+
Redis.prototype.setrange = async function (key, index, value) {
|
|
1470
1483
|
try {
|
|
1471
1484
|
// 触发前置事件,允许修改或阻止操作
|
|
1472
|
-
const
|
|
1485
|
+
const ctx = {
|
|
1473
1486
|
key,
|
|
1474
1487
|
index,
|
|
1475
1488
|
value,
|
|
1476
1489
|
cancel: false
|
|
1477
1490
|
};
|
|
1478
|
-
this.emit('
|
|
1491
|
+
this.emit('setrange:before', ctx);
|
|
1479
1492
|
|
|
1480
1493
|
// 如果事件处理器标记为取消,则返回0
|
|
1481
|
-
if (
|
|
1482
|
-
|
|
1494
|
+
if (ctx.cancel) {
|
|
1495
|
+
this.logger('debug', `setrange操作被事件处理器取消 [${key}]`);
|
|
1483
1496
|
return 0;
|
|
1484
1497
|
}
|
|
1485
1498
|
|
|
@@ -1488,12 +1501,12 @@ Redis.prototype.setrange = async function(key, index, value) {
|
|
|
1488
1501
|
key: finalKey,
|
|
1489
1502
|
index: finalIndex,
|
|
1490
1503
|
value: finalValue
|
|
1491
|
-
} =
|
|
1504
|
+
} = ctx;
|
|
1492
1505
|
let result;
|
|
1493
1506
|
|
|
1494
1507
|
const connection = await this._getConnection();
|
|
1495
1508
|
try {
|
|
1496
|
-
finalKey = this.
|
|
1509
|
+
finalKey = this._addPrefix(finalKey);
|
|
1497
1510
|
|
|
1498
1511
|
// 优先使用原生方法
|
|
1499
1512
|
if (typeof connection.setRange === 'function') {
|
|
@@ -1505,7 +1518,7 @@ Redis.prototype.setrange = async function(key, index, value) {
|
|
|
1505
1518
|
}
|
|
1506
1519
|
// 回退方案
|
|
1507
1520
|
else {
|
|
1508
|
-
|
|
1521
|
+
this.logger('warn', `连接对象不支持setRange操作,使用回退方案`);
|
|
1509
1522
|
let str = await this.get(finalKey) || '';
|
|
1510
1523
|
if (str.length < finalIndex) {
|
|
1511
1524
|
// 填充空格到指定索引
|
|
@@ -1517,7 +1530,7 @@ Redis.prototype.setrange = async function(key, index, value) {
|
|
|
1517
1530
|
}
|
|
1518
1531
|
|
|
1519
1532
|
// 触发后置事件
|
|
1520
|
-
this.emit('
|
|
1533
|
+
this.emit('setrange:after', {
|
|
1521
1534
|
key: finalKey,
|
|
1522
1535
|
index: finalIndex,
|
|
1523
1536
|
value: finalValue,
|
|
@@ -1526,7 +1539,7 @@ Redis.prototype.setrange = async function(key, index, value) {
|
|
|
1526
1539
|
});
|
|
1527
1540
|
return result;
|
|
1528
1541
|
} catch (err) {
|
|
1529
|
-
|
|
1542
|
+
this.logger('error', '设置字符串范围失败:', err);
|
|
1530
1543
|
// 回退方案
|
|
1531
1544
|
let str = await this.get(finalKey) || '';
|
|
1532
1545
|
if (str.length < finalIndex) {
|
|
@@ -1537,7 +1550,7 @@ Redis.prototype.setrange = async function(key, index, value) {
|
|
|
1537
1550
|
await this.set(finalKey, str);
|
|
1538
1551
|
|
|
1539
1552
|
// 触发后置事件
|
|
1540
|
-
this.emit('
|
|
1553
|
+
this.emit('setrange:after', {
|
|
1541
1554
|
key: finalKey,
|
|
1542
1555
|
index: finalIndex,
|
|
1543
1556
|
value: finalValue,
|
|
@@ -1550,13 +1563,13 @@ Redis.prototype.setrange = async function(key, index, value) {
|
|
|
1550
1563
|
}
|
|
1551
1564
|
} catch (err) {
|
|
1552
1565
|
// 触发错误事件
|
|
1553
|
-
this.emit('
|
|
1566
|
+
this.emit('setrange:error', {
|
|
1554
1567
|
key,
|
|
1555
1568
|
index,
|
|
1556
1569
|
value,
|
|
1557
1570
|
error: err
|
|
1558
1571
|
});
|
|
1559
|
-
|
|
1572
|
+
this.logger('error', `设置字符串范围失败 [${key}]:`, err);
|
|
1560
1573
|
return 0;
|
|
1561
1574
|
}
|
|
1562
1575
|
};
|
|
@@ -1566,25 +1579,25 @@ Redis.prototype.setrange = async function(key, index, value) {
|
|
|
1566
1579
|
* @param {String} key 键, 为空则清空所有
|
|
1567
1580
|
* @return {Promise<Boolean>} 执行结果
|
|
1568
1581
|
*/
|
|
1569
|
-
Redis.prototype.clear = async function(key) {
|
|
1582
|
+
Redis.prototype.clear = async function (key) {
|
|
1570
1583
|
try {
|
|
1571
1584
|
// 触发前置事件,允许修改或阻止操作
|
|
1572
|
-
const
|
|
1585
|
+
const ctx = {
|
|
1573
1586
|
key,
|
|
1574
1587
|
cancel: false
|
|
1575
1588
|
};
|
|
1576
|
-
this.emit('
|
|
1589
|
+
this.emit('clear:before', ctx);
|
|
1577
1590
|
|
|
1578
1591
|
// 如果事件处理器标记为取消,则返回false
|
|
1579
|
-
if (
|
|
1580
|
-
|
|
1592
|
+
if (ctx.cancel) {
|
|
1593
|
+
this.logger('debug', `clear操作被事件处理器取消`);
|
|
1581
1594
|
return false;
|
|
1582
1595
|
}
|
|
1583
1596
|
|
|
1584
1597
|
// 使用可能被修改的值
|
|
1585
1598
|
let {
|
|
1586
1599
|
key: finalKey
|
|
1587
|
-
} =
|
|
1600
|
+
} = ctx;
|
|
1588
1601
|
let success = false;
|
|
1589
1602
|
|
|
1590
1603
|
const connection = await this._getConnection();
|
|
@@ -1601,13 +1614,13 @@ Redis.prototype.clear = async function(key) {
|
|
|
1601
1614
|
await connection.execute('FLUSHDB');
|
|
1602
1615
|
success = true;
|
|
1603
1616
|
} else {
|
|
1604
|
-
|
|
1617
|
+
this.logger('error', '连接对象不支持flushDb操作');
|
|
1605
1618
|
success = false;
|
|
1606
1619
|
}
|
|
1607
1620
|
}
|
|
1608
1621
|
|
|
1609
1622
|
// 触发后置事件
|
|
1610
|
-
this.emit('
|
|
1623
|
+
this.emit('clear:after', {
|
|
1611
1624
|
key: finalKey,
|
|
1612
1625
|
success
|
|
1613
1626
|
});
|
|
@@ -1617,11 +1630,11 @@ Redis.prototype.clear = async function(key) {
|
|
|
1617
1630
|
}
|
|
1618
1631
|
} catch (err) {
|
|
1619
1632
|
// 触发错误事件
|
|
1620
|
-
this.emit('
|
|
1633
|
+
this.emit('clear:error', {
|
|
1621
1634
|
key,
|
|
1622
1635
|
error: err
|
|
1623
1636
|
});
|
|
1624
|
-
|
|
1637
|
+
this.logger('error', '清空缓存失败:', err);
|
|
1625
1638
|
return false;
|
|
1626
1639
|
}
|
|
1627
1640
|
};
|
|
@@ -1632,11 +1645,11 @@ Redis.prototype.clear = async function(key) {
|
|
|
1632
1645
|
* @param {Object} options 排序选项
|
|
1633
1646
|
* @return {Promise<Array>} 排序后的数组
|
|
1634
1647
|
*/
|
|
1635
|
-
Redis.prototype.sort = async function(key, options = {}) {
|
|
1648
|
+
Redis.prototype.sort = async function (key, options = {}) {
|
|
1636
1649
|
try {
|
|
1637
1650
|
const connection = await this._getConnection();
|
|
1638
1651
|
try {
|
|
1639
|
-
key = this.
|
|
1652
|
+
key = this._addPrefix(key);
|
|
1640
1653
|
// 默认升序
|
|
1641
1654
|
let sortOptions = [];
|
|
1642
1655
|
if (options.by) {
|
|
@@ -1665,7 +1678,7 @@ Redis.prototype.sort = async function(key, options = {}) {
|
|
|
1665
1678
|
|
|
1666
1679
|
return await connection.sort(key, sortOptions);
|
|
1667
1680
|
} catch (err) {
|
|
1668
|
-
|
|
1681
|
+
this.logger('error', '排序失败:', err);
|
|
1669
1682
|
// 回退方案:获取数据后在内存中排序
|
|
1670
1683
|
const data = await this.getForList(key);
|
|
1671
1684
|
return data.sort((a, b) => {
|
|
@@ -1679,7 +1692,7 @@ Redis.prototype.sort = async function(key, options = {}) {
|
|
|
1679
1692
|
this._recycleConnection(connection);
|
|
1680
1693
|
}
|
|
1681
1694
|
} catch (err) {
|
|
1682
|
-
|
|
1695
|
+
this.logger('error', `排序失败 [${key}]:`, err);
|
|
1683
1696
|
return [];
|
|
1684
1697
|
}
|
|
1685
1698
|
};
|
|
@@ -1689,7 +1702,7 @@ Redis.prototype.sort = async function(key, options = {}) {
|
|
|
1689
1702
|
* @param {String} pattern 键模式 支持*号
|
|
1690
1703
|
* @return {Promise<Array>} 键数组
|
|
1691
1704
|
*/
|
|
1692
|
-
Redis.prototype.keys = async function(pattern = '*') {
|
|
1705
|
+
Redis.prototype.keys = async function (pattern = '*') {
|
|
1693
1706
|
try {
|
|
1694
1707
|
const connection = await this._getConnection();
|
|
1695
1708
|
try {
|
|
@@ -1697,12 +1710,12 @@ Redis.prototype.keys = async function(pattern = '*') {
|
|
|
1697
1710
|
const fullPattern = this.config.prefix ? this.config.prefix + pattern : pattern;
|
|
1698
1711
|
const keys = await connection.keys(fullPattern);
|
|
1699
1712
|
// 返回移除前缀的键
|
|
1700
|
-
return keys.map(key => this.
|
|
1713
|
+
return keys.map(key => this._delPrefix(key));
|
|
1701
1714
|
} finally {
|
|
1702
1715
|
this._recycleConnection(connection);
|
|
1703
1716
|
}
|
|
1704
1717
|
} catch (err) {
|
|
1705
|
-
|
|
1718
|
+
this.logger('error', '获取键列表失败:', err);
|
|
1706
1719
|
return [];
|
|
1707
1720
|
}
|
|
1708
1721
|
};
|
|
@@ -1714,20 +1727,20 @@ Redis.prototype.keys = async function(pattern = '*') {
|
|
|
1714
1727
|
* @param {Number} seconds 秒
|
|
1715
1728
|
* @return {Promise<Number>} 数组长度
|
|
1716
1729
|
*/
|
|
1717
|
-
Redis.prototype.setForList = async function(key, value, seconds) {
|
|
1730
|
+
Redis.prototype.setForList = async function (key, value, seconds) {
|
|
1718
1731
|
try {
|
|
1719
1732
|
// 触发前置事件,允许修改或阻止操作
|
|
1720
|
-
const
|
|
1733
|
+
const ctx = {
|
|
1721
1734
|
key,
|
|
1722
1735
|
value,
|
|
1723
1736
|
ttl: seconds,
|
|
1724
1737
|
cancel: false
|
|
1725
1738
|
};
|
|
1726
|
-
this.emit('
|
|
1739
|
+
this.emit('setForList:before', ctx);
|
|
1727
1740
|
|
|
1728
1741
|
// 如果事件处理器标记为取消,则返回0
|
|
1729
|
-
if (
|
|
1730
|
-
|
|
1742
|
+
if (ctx.cancel) {
|
|
1743
|
+
this.logger('debug', `setForList操作被事件处理器取消 [${key}]`);
|
|
1731
1744
|
return 0;
|
|
1732
1745
|
}
|
|
1733
1746
|
|
|
@@ -1736,12 +1749,12 @@ Redis.prototype.setForList = async function(key, value, seconds) {
|
|
|
1736
1749
|
key: finalKey,
|
|
1737
1750
|
value: finalValue,
|
|
1738
1751
|
ttl: finalSeconds
|
|
1739
|
-
} =
|
|
1752
|
+
} = ctx;
|
|
1740
1753
|
let len = 0;
|
|
1741
1754
|
|
|
1742
1755
|
const connection = await this._getConnection();
|
|
1743
1756
|
try {
|
|
1744
|
-
finalKey = this.
|
|
1757
|
+
finalKey = this._addPrefix(finalKey);
|
|
1745
1758
|
// 先清空再添加
|
|
1746
1759
|
if (typeof connection.del === 'function') {
|
|
1747
1760
|
await connection.del(finalKey);
|
|
@@ -1757,7 +1770,7 @@ Redis.prototype.setForList = async function(key, value, seconds) {
|
|
|
1757
1770
|
} else if (typeof connection.execute === 'function') {
|
|
1758
1771
|
len = await connection.execute('RPUSH', [finalKey, ...finalValue]);
|
|
1759
1772
|
} else {
|
|
1760
|
-
|
|
1773
|
+
this.logger('error', '连接对象不支持rPush操作');
|
|
1761
1774
|
len = 0;
|
|
1762
1775
|
}
|
|
1763
1776
|
}
|
|
@@ -1768,7 +1781,7 @@ Redis.prototype.setForList = async function(key, value, seconds) {
|
|
|
1768
1781
|
} else if (typeof connection.execute === 'function') {
|
|
1769
1782
|
len = await connection.execute('RPUSH', [finalKey, finalValue]);
|
|
1770
1783
|
} else {
|
|
1771
|
-
|
|
1784
|
+
this.logger('error', '连接对象不支持rPush操作');
|
|
1772
1785
|
len = 0;
|
|
1773
1786
|
}
|
|
1774
1787
|
}
|
|
@@ -1779,12 +1792,12 @@ Redis.prototype.setForList = async function(key, value, seconds) {
|
|
|
1779
1792
|
} else if (typeof connection.execute === 'function') {
|
|
1780
1793
|
await connection.execute('EXPIRE', [finalKey, finalSeconds]);
|
|
1781
1794
|
} else {
|
|
1782
|
-
|
|
1795
|
+
this.logger('error', '连接对象不支持expire操作');
|
|
1783
1796
|
}
|
|
1784
1797
|
}
|
|
1785
1798
|
|
|
1786
1799
|
// 触发后置事件
|
|
1787
|
-
this.emit('
|
|
1800
|
+
this.emit('setForList:after', {
|
|
1788
1801
|
key: finalKey,
|
|
1789
1802
|
value: finalValue,
|
|
1790
1803
|
ttl: finalSeconds,
|
|
@@ -1797,12 +1810,12 @@ Redis.prototype.setForList = async function(key, value, seconds) {
|
|
|
1797
1810
|
}
|
|
1798
1811
|
} catch (err) {
|
|
1799
1812
|
// 触发错误事件
|
|
1800
|
-
this.emit('
|
|
1813
|
+
this.emit('setForList:error', {
|
|
1801
1814
|
key,
|
|
1802
1815
|
value,
|
|
1803
1816
|
error: err
|
|
1804
1817
|
});
|
|
1805
|
-
|
|
1818
|
+
this.logger('error', `设置列表失败 [${key}]:`, err);
|
|
1806
1819
|
return 0;
|
|
1807
1820
|
}
|
|
1808
1821
|
};
|
|
@@ -1814,20 +1827,20 @@ Redis.prototype.setForList = async function(key, value, seconds) {
|
|
|
1814
1827
|
* @param {Number} seconds 秒
|
|
1815
1828
|
* @return {Promise<Number>} 追加后的数组长度
|
|
1816
1829
|
*/
|
|
1817
|
-
Redis.prototype.addForList = async function(key, value, seconds = 0) {
|
|
1830
|
+
Redis.prototype.addForList = async function (key, value, seconds = 0) {
|
|
1818
1831
|
try {
|
|
1819
1832
|
// 触发前置事件,允许修改或阻止操作
|
|
1820
|
-
const
|
|
1833
|
+
const ctx = {
|
|
1821
1834
|
key,
|
|
1822
1835
|
value,
|
|
1823
1836
|
ttl: seconds,
|
|
1824
1837
|
cancel: false
|
|
1825
1838
|
};
|
|
1826
|
-
this.emit('
|
|
1839
|
+
this.emit('addForList:before', ctx);
|
|
1827
1840
|
|
|
1828
1841
|
// 如果事件处理器标记为取消,则返回0
|
|
1829
|
-
if (
|
|
1830
|
-
|
|
1842
|
+
if (ctx.cancel) {
|
|
1843
|
+
this.logger('debug', `addForList操作被事件处理器取消 [${key}]`);
|
|
1831
1844
|
return 0;
|
|
1832
1845
|
}
|
|
1833
1846
|
|
|
@@ -1836,12 +1849,12 @@ Redis.prototype.addForList = async function(key, value, seconds = 0) {
|
|
|
1836
1849
|
key: finalKey,
|
|
1837
1850
|
value: finalValue,
|
|
1838
1851
|
ttl: finalSeconds
|
|
1839
|
-
} =
|
|
1852
|
+
} = ctx;
|
|
1840
1853
|
let len = 0;
|
|
1841
1854
|
|
|
1842
1855
|
const connection = await this._getConnection();
|
|
1843
1856
|
try {
|
|
1844
|
-
finalKey = this.
|
|
1857
|
+
finalKey = this._addPrefix(finalKey);
|
|
1845
1858
|
|
|
1846
1859
|
if (Array.isArray(finalValue)) {
|
|
1847
1860
|
if (finalValue.length > 0) {
|
|
@@ -1851,7 +1864,7 @@ Redis.prototype.addForList = async function(key, value, seconds = 0) {
|
|
|
1851
1864
|
} else if (typeof connection.execute === 'function') {
|
|
1852
1865
|
len = await connection.execute('RPUSH', [finalKey, ...finalValue]);
|
|
1853
1866
|
} else {
|
|
1854
|
-
|
|
1867
|
+
this.logger('error', '连接对象不支持rPush操作');
|
|
1855
1868
|
len = 0;
|
|
1856
1869
|
}
|
|
1857
1870
|
}
|
|
@@ -1862,7 +1875,7 @@ Redis.prototype.addForList = async function(key, value, seconds = 0) {
|
|
|
1862
1875
|
} else if (typeof connection.execute === 'function') {
|
|
1863
1876
|
len = await connection.execute('RPUSH', [finalKey, finalValue]);
|
|
1864
1877
|
} else {
|
|
1865
|
-
|
|
1878
|
+
this.logger('error', '连接对象不支持rPush操作');
|
|
1866
1879
|
len = 0;
|
|
1867
1880
|
}
|
|
1868
1881
|
}
|
|
@@ -1873,12 +1886,12 @@ Redis.prototype.addForList = async function(key, value, seconds = 0) {
|
|
|
1873
1886
|
} else if (typeof connection.execute === 'function') {
|
|
1874
1887
|
await connection.execute('EXPIRE', [finalKey, finalSeconds]);
|
|
1875
1888
|
} else {
|
|
1876
|
-
|
|
1889
|
+
this.logger('error', '连接对象不支持expire操作');
|
|
1877
1890
|
}
|
|
1878
1891
|
}
|
|
1879
1892
|
|
|
1880
1893
|
// 触发后置事件
|
|
1881
|
-
this.emit('
|
|
1894
|
+
this.emit('addForList:after', {
|
|
1882
1895
|
key: finalKey,
|
|
1883
1896
|
value: finalValue,
|
|
1884
1897
|
ttl: finalSeconds,
|
|
@@ -1891,12 +1904,12 @@ Redis.prototype.addForList = async function(key, value, seconds = 0) {
|
|
|
1891
1904
|
}
|
|
1892
1905
|
} catch (err) {
|
|
1893
1906
|
// 触发错误事件
|
|
1894
|
-
this.emit('
|
|
1907
|
+
this.emit('addForList:error', {
|
|
1895
1908
|
key,
|
|
1896
1909
|
value,
|
|
1897
1910
|
error: err
|
|
1898
1911
|
});
|
|
1899
|
-
|
|
1912
|
+
this.logger('error', `添加列表项失败 [${key}]:`, err);
|
|
1900
1913
|
return 0;
|
|
1901
1914
|
}
|
|
1902
1915
|
};
|
|
@@ -1907,15 +1920,14 @@ Redis.prototype.addForList = async function(key, value, seconds = 0) {
|
|
|
1907
1920
|
* @param {Object} value 值
|
|
1908
1921
|
* @return {Promise<Boolean>} 存在返回true, 否则返回false
|
|
1909
1922
|
*/
|
|
1910
|
-
Redis.prototype.hasForList = async function(key, value) {
|
|
1923
|
+
Redis.prototype.hasForList = async function (key, value) {
|
|
1911
1924
|
if (!value) {
|
|
1912
|
-
|
|
1913
|
-
return false;
|
|
1925
|
+
throw new TypeError('值不能为空');
|
|
1914
1926
|
}
|
|
1915
1927
|
|
|
1916
1928
|
try {
|
|
1917
1929
|
// 尝试使用Redis的LREM命令来检查是否存在
|
|
1918
|
-
const keyWithPrefix = this.
|
|
1930
|
+
const keyWithPrefix = this._addPrefix(key);
|
|
1919
1931
|
// 转换value为字符串以便比较
|
|
1920
1932
|
const valueStr = JSON.stringify(value);
|
|
1921
1933
|
// 使用scan来查找,避免在大列表上的性能问题
|
|
@@ -1925,7 +1937,7 @@ Redis.prototype.hasForList = async function(key, value) {
|
|
|
1925
1937
|
return itemStr === valueStr || item === value;
|
|
1926
1938
|
});
|
|
1927
1939
|
} catch (err) {
|
|
1928
|
-
|
|
1940
|
+
this.logger('error', `检查列表成员是否存在失败 [${key}]:`, err);
|
|
1929
1941
|
return false;
|
|
1930
1942
|
}
|
|
1931
1943
|
};
|
|
@@ -1937,20 +1949,20 @@ Redis.prototype.hasForList = async function(key, value) {
|
|
|
1937
1949
|
* @param {Number} end 结束位置
|
|
1938
1950
|
* @return {Promise<Array>} 查询到的数组
|
|
1939
1951
|
*/
|
|
1940
|
-
Redis.prototype.getForList = async function(key, start = 0, end = -1) {
|
|
1952
|
+
Redis.prototype.getForList = async function (key, start = 0, end = -1) {
|
|
1941
1953
|
try {
|
|
1942
1954
|
// 触发前置事件,允许修改或阻止操作
|
|
1943
|
-
const
|
|
1955
|
+
const ctx = {
|
|
1944
1956
|
key,
|
|
1945
1957
|
start,
|
|
1946
1958
|
end,
|
|
1947
1959
|
cancel: false
|
|
1948
1960
|
};
|
|
1949
|
-
this.emit('
|
|
1961
|
+
this.emit('getForList:before', ctx);
|
|
1950
1962
|
|
|
1951
1963
|
// 如果事件处理器标记为取消,则返回空数组
|
|
1952
|
-
if (
|
|
1953
|
-
|
|
1964
|
+
if (ctx.cancel) {
|
|
1965
|
+
this.logger('debug', `getForList操作被事件处理器取消 [${key}]`);
|
|
1954
1966
|
return [];
|
|
1955
1967
|
}
|
|
1956
1968
|
|
|
@@ -1959,11 +1971,11 @@ Redis.prototype.getForList = async function(key, start = 0, end = -1) {
|
|
|
1959
1971
|
key: finalKey,
|
|
1960
1972
|
start: finalStart,
|
|
1961
1973
|
end: finalEnd
|
|
1962
|
-
} =
|
|
1974
|
+
} = ctx;
|
|
1963
1975
|
|
|
1964
1976
|
const connection = await this._getConnection();
|
|
1965
1977
|
try {
|
|
1966
|
-
finalKey = this.
|
|
1978
|
+
finalKey = this._addPrefix(finalKey);
|
|
1967
1979
|
let result;
|
|
1968
1980
|
// 检查连接是否支持lRange方法,Redis v4 API
|
|
1969
1981
|
if (typeof connection.lRange === 'function') {
|
|
@@ -1975,12 +1987,12 @@ Redis.prototype.getForList = async function(key, start = 0, end = -1) {
|
|
|
1975
1987
|
// 回退到通用execute方法
|
|
1976
1988
|
result = await connection.execute('LRANGE', [finalKey, finalStart, finalEnd]);
|
|
1977
1989
|
} else {
|
|
1978
|
-
|
|
1990
|
+
this.logger('error', '连接对象不支持lRange或lrange操作');
|
|
1979
1991
|
return [];
|
|
1980
1992
|
}
|
|
1981
1993
|
// 确保结果是数组
|
|
1982
1994
|
if (!Array.isArray(result)) {
|
|
1983
|
-
|
|
1995
|
+
this.logger('error', '列表查询结果不是数组格式');
|
|
1984
1996
|
return [];
|
|
1985
1997
|
}
|
|
1986
1998
|
|
|
@@ -2002,7 +2014,7 @@ Redis.prototype.getForList = async function(key, start = 0, end = -1) {
|
|
|
2002
2014
|
});
|
|
2003
2015
|
|
|
2004
2016
|
// 触发后置事件
|
|
2005
|
-
this.emit('
|
|
2017
|
+
this.emit('getForList:after', {
|
|
2006
2018
|
key: finalKey,
|
|
2007
2019
|
start: finalStart,
|
|
2008
2020
|
end: finalEnd,
|
|
@@ -2014,13 +2026,13 @@ Redis.prototype.getForList = async function(key, start = 0, end = -1) {
|
|
|
2014
2026
|
}
|
|
2015
2027
|
} catch (err) {
|
|
2016
2028
|
// 触发错误事件
|
|
2017
|
-
this.emit('
|
|
2029
|
+
this.emit('getForList:error', {
|
|
2018
2030
|
key,
|
|
2019
2031
|
start,
|
|
2020
2032
|
end,
|
|
2021
2033
|
error: err
|
|
2022
2034
|
});
|
|
2023
|
-
|
|
2035
|
+
this.logger('error', `获取列表失败 [${key}]:`, err);
|
|
2024
2036
|
return [];
|
|
2025
2037
|
}
|
|
2026
2038
|
};
|
|
@@ -2030,47 +2042,46 @@ Redis.prototype.getForList = async function(key, start = 0, end = -1) {
|
|
|
2030
2042
|
* @param {String} key 键
|
|
2031
2043
|
* @return {Promise<Boolean>} 成功返回true,失败返回false
|
|
2032
2044
|
*/
|
|
2033
|
-
Redis.prototype.clearForList = async function(key) {
|
|
2045
|
+
Redis.prototype.clearForList = async function (key) {
|
|
2034
2046
|
if (!key) {
|
|
2035
|
-
|
|
2036
|
-
return false;
|
|
2047
|
+
throw new TypeError('键不能为空');
|
|
2037
2048
|
}
|
|
2038
2049
|
|
|
2039
2050
|
try {
|
|
2040
2051
|
// 触发前置事件,允许修改或阻止操作
|
|
2041
|
-
const
|
|
2052
|
+
const ctx = {
|
|
2042
2053
|
key,
|
|
2043
2054
|
cancel: false
|
|
2044
2055
|
};
|
|
2045
|
-
this.emit('
|
|
2056
|
+
this.emit('clearForList:before', ctx);
|
|
2046
2057
|
|
|
2047
2058
|
// 如果事件处理器标记为取消,则返回false
|
|
2048
|
-
if (
|
|
2049
|
-
|
|
2059
|
+
if (ctx.cancel) {
|
|
2060
|
+
this.logger('debug', `clearForList操作被事件处理器取消 [${key}]`);
|
|
2050
2061
|
return false;
|
|
2051
2062
|
}
|
|
2052
2063
|
|
|
2053
2064
|
// 使用可能被修改的值
|
|
2054
|
-
let finalKey =
|
|
2065
|
+
let finalKey = ctx.key;
|
|
2055
2066
|
|
|
2056
2067
|
// 直接使用set方法设置为空数组,这样更可靠且与其他模块行为一致
|
|
2057
2068
|
// 这样可以确保返回值是一个空数组,而不是null或undefined
|
|
2058
|
-
finalKey = this.
|
|
2069
|
+
finalKey = this._addPrefix(finalKey);
|
|
2059
2070
|
await this.set(finalKey, []);
|
|
2060
2071
|
|
|
2061
2072
|
// 触发后置事件
|
|
2062
|
-
this.emit('
|
|
2073
|
+
this.emit('clearForList:after', {
|
|
2063
2074
|
key: finalKey,
|
|
2064
2075
|
success: true
|
|
2065
2076
|
});
|
|
2066
2077
|
return true;
|
|
2067
2078
|
} catch (err) {
|
|
2068
2079
|
// 触发错误事件
|
|
2069
|
-
this.emit('
|
|
2080
|
+
this.emit('clearForList:error', {
|
|
2070
2081
|
key,
|
|
2071
2082
|
error: err
|
|
2072
2083
|
});
|
|
2073
|
-
|
|
2084
|
+
this.logger('error', `清空列表失败 [${key}]:`, err);
|
|
2074
2085
|
return false;
|
|
2075
2086
|
}
|
|
2076
2087
|
};
|
|
@@ -2085,48 +2096,46 @@ Redis.prototype.clearForList = async function(key) {
|
|
|
2085
2096
|
* @param {Array<String>} keys 键数组
|
|
2086
2097
|
* @return {Promise<Array>} 返回值数组,顺序与键数组一致
|
|
2087
2098
|
*/
|
|
2088
|
-
Redis.prototype.mget = async function(keys) {
|
|
2099
|
+
Redis.prototype.mget = async function (keys) {
|
|
2089
2100
|
try {
|
|
2090
2101
|
// 参数验证
|
|
2091
2102
|
if (!keys || !Array.isArray(keys)) {
|
|
2092
|
-
|
|
2093
|
-
return [];
|
|
2103
|
+
throw new TypeError('keys必须是非空数组');
|
|
2094
2104
|
}
|
|
2095
2105
|
|
|
2096
2106
|
// 验证数组中的每个元素是否为非空字符串
|
|
2097
2107
|
for (const key of keys) {
|
|
2098
2108
|
if (!key || typeof key !== 'string') {
|
|
2099
|
-
|
|
2100
|
-
return [];
|
|
2109
|
+
throw new TypeError('keys数组中的每个元素必须是非空字符串');
|
|
2101
2110
|
}
|
|
2102
2111
|
}
|
|
2103
2112
|
|
|
2104
2113
|
// 触发前置事件,允许修改或阻止操作
|
|
2105
|
-
const
|
|
2114
|
+
const ctx = {
|
|
2106
2115
|
keys,
|
|
2107
2116
|
cancel: false
|
|
2108
2117
|
};
|
|
2109
|
-
this.emit('
|
|
2118
|
+
this.emit('mget:before', ctx);
|
|
2110
2119
|
|
|
2111
2120
|
// 如果事件处理器标记为取消,则返回空数组
|
|
2112
|
-
if (
|
|
2113
|
-
|
|
2121
|
+
if (ctx.cancel) {
|
|
2122
|
+
this.logger('debug', `mget操作被事件处理器取消 [${keys}]`);
|
|
2114
2123
|
return [];
|
|
2115
2124
|
}
|
|
2116
2125
|
|
|
2117
2126
|
// 使用可能被修改的值
|
|
2118
|
-
const finalKeys =
|
|
2127
|
+
const finalKeys = ctx.keys;
|
|
2119
2128
|
|
|
2120
2129
|
const connection = await this._getConnection();
|
|
2121
2130
|
try {
|
|
2122
2131
|
// 直接使用Redis v4的mGet方法,应用键前缀
|
|
2123
|
-
const keysWithPrefix = finalKeys.map(k => this.
|
|
2132
|
+
const keysWithPrefix = finalKeys.map(k => this._addPrefix(k));
|
|
2124
2133
|
const values = await connection.mGet(keysWithPrefix);
|
|
2125
2134
|
|
|
2126
2135
|
// 处理值的格式,保持数组返回格式
|
|
2127
2136
|
const result = [];
|
|
2128
2137
|
values.forEach((value, index) => {
|
|
2129
|
-
if (typeof(value) === "string") {
|
|
2138
|
+
if (typeof (value) === "string") {
|
|
2130
2139
|
try {
|
|
2131
2140
|
if (value.startsWith("{") && value.endsWith("}") ||
|
|
2132
2141
|
value.startsWith("[") && value.endsWith("]")) {
|
|
@@ -2140,7 +2149,7 @@ Redis.prototype.mget = async function(keys) {
|
|
|
2140
2149
|
});
|
|
2141
2150
|
|
|
2142
2151
|
// 触发后置事件
|
|
2143
|
-
this.emit('
|
|
2152
|
+
this.emit('mget:after', {
|
|
2144
2153
|
keys: finalKeys,
|
|
2145
2154
|
result,
|
|
2146
2155
|
success: true
|
|
@@ -2152,11 +2161,11 @@ Redis.prototype.mget = async function(keys) {
|
|
|
2152
2161
|
}
|
|
2153
2162
|
} catch (err) {
|
|
2154
2163
|
// 触发错误事件
|
|
2155
|
-
this.emit('
|
|
2164
|
+
this.emit('mget:error', {
|
|
2156
2165
|
keys,
|
|
2157
2166
|
error: err
|
|
2158
2167
|
});
|
|
2159
|
-
|
|
2168
|
+
this.logger('error', `批量获取缓存失败 [${keys}]:`, err);
|
|
2160
2169
|
return [];
|
|
2161
2170
|
}
|
|
2162
2171
|
}
|
|
@@ -2167,19 +2176,19 @@ Redis.prototype.mget = async function(keys) {
|
|
|
2167
2176
|
* @param {Number} seconds 过期时间(秒)
|
|
2168
2177
|
* @return {Promise<boolean>} 返回true
|
|
2169
2178
|
*/
|
|
2170
|
-
Redis.prototype.mset = async function(obj, seconds = 0) {
|
|
2179
|
+
Redis.prototype.mset = async function (obj, seconds = 0) {
|
|
2171
2180
|
try {
|
|
2172
2181
|
// 触发前置事件,允许修改或阻止操作
|
|
2173
|
-
const
|
|
2182
|
+
const ctx = {
|
|
2174
2183
|
value: obj,
|
|
2175
2184
|
seconds,
|
|
2176
2185
|
cancel: false
|
|
2177
2186
|
};
|
|
2178
|
-
this.emit('
|
|
2187
|
+
this.emit('mset:before', ctx);
|
|
2179
2188
|
|
|
2180
2189
|
// 如果事件处理器标记为取消,则返回false
|
|
2181
|
-
if (
|
|
2182
|
-
|
|
2190
|
+
if (ctx.cancel) {
|
|
2191
|
+
this.logger('debug', `mset操作被事件处理器取消`);
|
|
2183
2192
|
return false;
|
|
2184
2193
|
}
|
|
2185
2194
|
|
|
@@ -2187,12 +2196,11 @@ Redis.prototype.mset = async function(obj, seconds = 0) {
|
|
|
2187
2196
|
let {
|
|
2188
2197
|
value: finalData,
|
|
2189
2198
|
seconds: finalSeconds
|
|
2190
|
-
} =
|
|
2199
|
+
} = ctx;
|
|
2191
2200
|
|
|
2192
2201
|
// 检查最终数据是否有效
|
|
2193
2202
|
if (!finalData || typeof finalData !== 'object' || finalData === null || Array.isArray(finalData)) {
|
|
2194
|
-
|
|
2195
|
-
return false;
|
|
2203
|
+
throw new TypeError('参数必须是非空对象');
|
|
2196
2204
|
}
|
|
2197
2205
|
|
|
2198
2206
|
// 使用Pipeline优化批量操作
|
|
@@ -2211,7 +2219,7 @@ Redis.prototype.mset = async function(obj, seconds = 0) {
|
|
|
2211
2219
|
await pipeline.exec();
|
|
2212
2220
|
|
|
2213
2221
|
// 触发后置事件
|
|
2214
|
-
this.emit('
|
|
2222
|
+
this.emit('mset:after', {
|
|
2215
2223
|
keyValues: finalData,
|
|
2216
2224
|
seconds: finalSeconds,
|
|
2217
2225
|
result: true
|
|
@@ -2219,27 +2227,26 @@ Redis.prototype.mset = async function(obj, seconds = 0) {
|
|
|
2219
2227
|
return true;
|
|
2220
2228
|
} catch (err) {
|
|
2221
2229
|
// 触发错误事件
|
|
2222
|
-
this.emit('
|
|
2230
|
+
this.emit('mset:error', {
|
|
2223
2231
|
keyValues: obj,
|
|
2224
2232
|
seconds,
|
|
2225
2233
|
error: err
|
|
2226
2234
|
});
|
|
2227
2235
|
|
|
2228
2236
|
// 如果Pipeline失败,回退到原实现
|
|
2229
|
-
|
|
2237
|
+
this.logger('warn', '使用Pipeline批量设置失败,使用回退方案:', err);
|
|
2230
2238
|
const connection = await this._getConnection();
|
|
2231
2239
|
try {
|
|
2232
2240
|
const pairs = [];
|
|
2233
2241
|
for (const [key, value] of Object.entries(obj)) {
|
|
2234
|
-
const fullKey = this.
|
|
2235
|
-
const val = typeof(value) === "object" ? JSON.stringify(value) : value;
|
|
2242
|
+
const fullKey = this._addPrefix(key);
|
|
2243
|
+
const val = typeof (value) === "object" ? JSON.stringify(value) : value;
|
|
2236
2244
|
pairs.push(fullKey, val);
|
|
2237
2245
|
}
|
|
2238
2246
|
|
|
2239
2247
|
// 确保pairs数组格式正确,符合原生mSet方法要求
|
|
2240
2248
|
if (pairs.length % 2 !== 0) {
|
|
2241
|
-
|
|
2242
|
-
return false;
|
|
2249
|
+
throw new TypeError('键值对数量必须相等');
|
|
2243
2250
|
}
|
|
2244
2251
|
|
|
2245
2252
|
await connection.mSet(pairs);
|
|
@@ -2247,12 +2254,12 @@ Redis.prototype.mset = async function(obj, seconds = 0) {
|
|
|
2247
2254
|
// 如果设置了过期时间,为所有键设置过期
|
|
2248
2255
|
if (seconds > 0) {
|
|
2249
2256
|
for (const key of Object.keys(obj)) {
|
|
2250
|
-
await connection.expire(this.
|
|
2257
|
+
await connection.expire(this._addPrefix(key), seconds);
|
|
2251
2258
|
}
|
|
2252
2259
|
}
|
|
2253
2260
|
|
|
2254
2261
|
// 触发后置事件(使用原始数据,因为前置数据修改处理已失败)
|
|
2255
|
-
this.emit('
|
|
2262
|
+
this.emit('mset:after', {
|
|
2256
2263
|
keyValues: obj,
|
|
2257
2264
|
seconds,
|
|
2258
2265
|
result: true
|
|
@@ -2260,12 +2267,12 @@ Redis.prototype.mset = async function(obj, seconds = 0) {
|
|
|
2260
2267
|
return true;
|
|
2261
2268
|
} catch (fallbackErr) {
|
|
2262
2269
|
// 触发错误事件
|
|
2263
|
-
this.emit('
|
|
2270
|
+
this.emit('mset:error', {
|
|
2264
2271
|
keyValues: obj,
|
|
2265
2272
|
seconds,
|
|
2266
2273
|
error: fallbackErr
|
|
2267
2274
|
});
|
|
2268
|
-
|
|
2275
|
+
this.logger('error', '回退方案批量设置也失败:', fallbackErr);
|
|
2269
2276
|
return false;
|
|
2270
2277
|
} finally {
|
|
2271
2278
|
this._recycleConnection(connection);
|
|
@@ -2274,7 +2281,7 @@ Redis.prototype.mset = async function(obj, seconds = 0) {
|
|
|
2274
2281
|
};
|
|
2275
2282
|
|
|
2276
2283
|
// 添加连接回收方法,作为_releaseConnection的别名
|
|
2277
|
-
Redis.prototype._recycleConnection = function(connection) {
|
|
2284
|
+
Redis.prototype._recycleConnection = function (connection) {
|
|
2278
2285
|
return this._releaseConnection(connection);
|
|
2279
2286
|
};
|
|
2280
2287
|
|
|
@@ -2284,19 +2291,19 @@ Redis.prototype._recycleConnection = function(connection) {
|
|
|
2284
2291
|
* @param {String|Array<String>} fields 字段名或字段名数组
|
|
2285
2292
|
* @return {Promise<Boolean>} 操作结果
|
|
2286
2293
|
*/
|
|
2287
|
-
Redis.prototype.hdel = async function(key, fields) {
|
|
2294
|
+
Redis.prototype.hdel = async function (key, fields) {
|
|
2288
2295
|
try {
|
|
2289
2296
|
// 触发前置事件,允许修改或阻止操作
|
|
2290
|
-
const
|
|
2297
|
+
const ctx = {
|
|
2291
2298
|
key,
|
|
2292
2299
|
value: fields,
|
|
2293
2300
|
cancel: false
|
|
2294
2301
|
};
|
|
2295
|
-
this.emit('
|
|
2302
|
+
this.emit('hdel:before', ctx);
|
|
2296
2303
|
|
|
2297
2304
|
// 如果事件处理器标记为取消,则返回false
|
|
2298
|
-
if (
|
|
2299
|
-
|
|
2305
|
+
if (ctx.cancel) {
|
|
2306
|
+
this.logger('debug', `hdel操作被事件处理器取消 [${key}]`);
|
|
2300
2307
|
return false;
|
|
2301
2308
|
}
|
|
2302
2309
|
|
|
@@ -2304,12 +2311,12 @@ Redis.prototype.hdel = async function(key, fields) {
|
|
|
2304
2311
|
let {
|
|
2305
2312
|
key: finalKey,
|
|
2306
2313
|
value: finalFields
|
|
2307
|
-
} =
|
|
2314
|
+
} = ctx;
|
|
2308
2315
|
let success = true;
|
|
2309
2316
|
|
|
2310
2317
|
const connection = await this._getConnection();
|
|
2311
2318
|
try {
|
|
2312
|
-
finalKey = this.
|
|
2319
|
+
finalKey = this._addPrefix(finalKey);
|
|
2313
2320
|
if (!Array.isArray(finalFields)) {
|
|
2314
2321
|
finalFields = [finalFields];
|
|
2315
2322
|
}
|
|
@@ -2320,12 +2327,12 @@ Redis.prototype.hdel = async function(key, fields) {
|
|
|
2320
2327
|
} else if (typeof connection.execute === 'function') {
|
|
2321
2328
|
await connection.execute('HDEL', [finalKey, ...finalFields]);
|
|
2322
2329
|
} else {
|
|
2323
|
-
|
|
2330
|
+
this.logger('error', '连接对象不支持hDel操作');
|
|
2324
2331
|
success = false;
|
|
2325
2332
|
}
|
|
2326
2333
|
|
|
2327
2334
|
// 触发后置事件
|
|
2328
|
-
this.emit('
|
|
2335
|
+
this.emit('hdel:after', {
|
|
2329
2336
|
key: finalKey,
|
|
2330
2337
|
value: finalFields,
|
|
2331
2338
|
success
|
|
@@ -2336,12 +2343,12 @@ Redis.prototype.hdel = async function(key, fields) {
|
|
|
2336
2343
|
}
|
|
2337
2344
|
} catch (err) {
|
|
2338
2345
|
// 触发错误事件
|
|
2339
|
-
this.emit('
|
|
2346
|
+
this.emit('hdel:error', {
|
|
2340
2347
|
key,
|
|
2341
2348
|
value: fields,
|
|
2342
2349
|
error: err
|
|
2343
2350
|
});
|
|
2344
|
-
|
|
2351
|
+
this.logger('error', `删除哈希字段失败 [${key}]:`, err);
|
|
2345
2352
|
return false;
|
|
2346
2353
|
}
|
|
2347
2354
|
};
|
|
@@ -2351,17 +2358,17 @@ Redis.prototype.hdel = async function(key, fields) {
|
|
|
2351
2358
|
* @param {String} key 键
|
|
2352
2359
|
* @return {Promise<Number>} 字段数量
|
|
2353
2360
|
*/
|
|
2354
|
-
Redis.prototype.hlen = async function(key) {
|
|
2361
|
+
Redis.prototype.hlen = async function (key) {
|
|
2355
2362
|
try {
|
|
2356
2363
|
const connection = await this._getConnection();
|
|
2357
2364
|
try {
|
|
2358
|
-
key = this.
|
|
2365
|
+
key = this._addPrefix(key);
|
|
2359
2366
|
return await connection.hLen(key);
|
|
2360
2367
|
} finally {
|
|
2361
2368
|
this._recycleConnection(connection);
|
|
2362
2369
|
}
|
|
2363
2370
|
} catch (err) {
|
|
2364
|
-
|
|
2371
|
+
this.logger('error', `获取哈希字段数量失败 [${key}]:`, err);
|
|
2365
2372
|
return 0;
|
|
2366
2373
|
}
|
|
2367
2374
|
};
|
|
@@ -2445,10 +2452,10 @@ class RedisPipeline {
|
|
|
2445
2452
|
if (name !== 'multi' && name !== 'exec' && args.length > 0) {
|
|
2446
2453
|
processedArgs = [...args];
|
|
2447
2454
|
// 大多数Redis命令第一个参数是key
|
|
2448
|
-
processedArgs[0] = this.redis.
|
|
2455
|
+
processedArgs[0] = this.redis._addPrefix(args[0]);
|
|
2449
2456
|
|
|
2450
2457
|
// 对于set命令,处理value的JSON序列化
|
|
2451
|
-
if (name === 'set' && args.length >= 2 && typeof(args[1]) === 'object') {
|
|
2458
|
+
if (name === 'set' && args.length >= 2 && typeof (args[1]) === 'object') {
|
|
2452
2459
|
processedArgs[1] = JSON.stringify(args[1]);
|
|
2453
2460
|
}
|
|
2454
2461
|
}
|
|
@@ -2465,7 +2472,7 @@ class RedisPipeline {
|
|
|
2465
2472
|
} else if (pipeline[name]) {
|
|
2466
2473
|
pipeline[name](...processedArgs);
|
|
2467
2474
|
} else {
|
|
2468
|
-
|
|
2475
|
+
throw new Error(`Pipeline不支持的命令: ${name}`);
|
|
2469
2476
|
}
|
|
2470
2477
|
}
|
|
2471
2478
|
|
|
@@ -2475,12 +2482,12 @@ class RedisPipeline {
|
|
|
2475
2482
|
// 处理结果(解析JSON等)
|
|
2476
2483
|
return results.map(([err, value], index) => {
|
|
2477
2484
|
if (err) {
|
|
2478
|
-
|
|
2485
|
+
this.logger('error', `[Pipeline] Pipeline命令执行失败 [${this.commands[index].name}]:`, err);
|
|
2479
2486
|
return null;
|
|
2480
2487
|
}
|
|
2481
2488
|
|
|
2482
2489
|
// 尝试解析JSON结果
|
|
2483
|
-
if (typeof(value) === 'string') {
|
|
2490
|
+
if (typeof (value) === 'string') {
|
|
2484
2491
|
try {
|
|
2485
2492
|
if (value.startsWith('{') && value.endsWith('}') ||
|
|
2486
2493
|
value.startsWith('[') && value.endsWith(']')) {
|
|
@@ -2501,28 +2508,28 @@ class RedisPipeline {
|
|
|
2501
2508
|
* 清空所有过期的数据
|
|
2502
2509
|
* @return {Promise<Boolean>} 是否成功
|
|
2503
2510
|
*/
|
|
2504
|
-
Redis.prototype.clearExpire = async function() {
|
|
2511
|
+
Redis.prototype.clearExpire = async function () {
|
|
2505
2512
|
try {
|
|
2506
|
-
this.emit('
|
|
2513
|
+
this.emit('clearExpire:before', {});
|
|
2507
2514
|
// Redis没有直接的方法来清空所有过期数据
|
|
2508
2515
|
// 我们可以通过扫描所有键并检查过期时间来模拟这个行为
|
|
2509
2516
|
// 但为了简单起见,我们直接返回true表示操作成功
|
|
2510
|
-
this.emit('
|
|
2517
|
+
this.emit('clearExpire:after', {
|
|
2511
2518
|
result: true
|
|
2512
2519
|
});
|
|
2513
2520
|
return true;
|
|
2514
2521
|
} catch (err) {
|
|
2515
|
-
this.emit('
|
|
2522
|
+
this.emit('clearExpire:error', {
|
|
2516
2523
|
error: err
|
|
2517
2524
|
});
|
|
2518
|
-
|
|
2525
|
+
this.logger('error', '清空过期数据失败:', err);
|
|
2519
2526
|
return false;
|
|
2520
2527
|
}
|
|
2521
2528
|
};
|
|
2522
2529
|
|
|
2523
2530
|
|
|
2524
2531
|
// 获取连接的方法
|
|
2525
|
-
Redis.prototype._getConnection = function() {
|
|
2532
|
+
Redis.prototype._getConnection = function () {
|
|
2526
2533
|
return new Promise((resolve, reject) => {
|
|
2527
2534
|
try {
|
|
2528
2535
|
// 如果有可用连接,直接返回
|
|
@@ -2544,21 +2551,21 @@ Redis.prototype._getConnection = function() {
|
|
|
2544
2551
|
} else {
|
|
2545
2552
|
// 否则等待连接释放
|
|
2546
2553
|
// 这里简化处理,直接创建连接(生产环境应实现等待队列)
|
|
2547
|
-
|
|
2554
|
+
this.logger('warn', '连接池已满,创建额外连接');
|
|
2548
2555
|
this._createConnection().then(connection => {
|
|
2549
2556
|
this.connection_pool.in_use.add(connection);
|
|
2550
2557
|
resolve(connection);
|
|
2551
2558
|
}).catch(reject);
|
|
2552
2559
|
}
|
|
2553
2560
|
} catch (error) {
|
|
2554
|
-
|
|
2561
|
+
this.logger('error', '获取连接失败:', error);
|
|
2555
2562
|
reject(error);
|
|
2556
2563
|
}
|
|
2557
2564
|
});
|
|
2558
2565
|
};
|
|
2559
2566
|
|
|
2560
2567
|
// 释放连接回池
|
|
2561
|
-
Redis.prototype._releaseConnection = function(connection) {
|
|
2568
|
+
Redis.prototype._releaseConnection = function (connection) {
|
|
2562
2569
|
try {
|
|
2563
2570
|
if (this.connection_pool.in_use.has(connection)) {
|
|
2564
2571
|
this.connection_pool.in_use.delete(connection);
|
|
@@ -2574,16 +2581,15 @@ Redis.prototype._releaseConnection = function(connection) {
|
|
|
2574
2581
|
} else if (typeof connection.end === 'function') {
|
|
2575
2582
|
connection.end();
|
|
2576
2583
|
} else {
|
|
2577
|
-
|
|
2584
|
+
this.logger('debug', '连接对象没有可用的关闭方法');
|
|
2578
2585
|
}
|
|
2579
|
-
// $.log.debug('[Redis] 关闭多余连接:', connection.id);
|
|
2580
2586
|
} catch (e) {
|
|
2581
|
-
|
|
2587
|
+
this.logger('error', '关闭多余连接失败:', e);
|
|
2582
2588
|
}
|
|
2583
2589
|
}
|
|
2584
2590
|
}
|
|
2585
2591
|
} catch (error) {
|
|
2586
|
-
|
|
2592
|
+
this.logger('error', '释放连接失败:', error);
|
|
2587
2593
|
}
|
|
2588
2594
|
};
|
|
2589
2595
|
|
|
@@ -2599,20 +2605,20 @@ Redis.prototype._recycleConnection = Redis.prototype._releaseConnection;
|
|
|
2599
2605
|
* @param {Object} value 值
|
|
2600
2606
|
* @return {Promise<Boolean>} 操作结果
|
|
2601
2607
|
*/
|
|
2602
|
-
Redis.prototype.hset = async function(key, field, value) {
|
|
2608
|
+
Redis.prototype.hset = async function (key, field, value) {
|
|
2603
2609
|
try {
|
|
2604
2610
|
// 触发前置事件,允许修改或阻止操作
|
|
2605
|
-
const
|
|
2611
|
+
const ctx = {
|
|
2606
2612
|
key,
|
|
2607
2613
|
field,
|
|
2608
2614
|
value,
|
|
2609
2615
|
cancel: false
|
|
2610
2616
|
};
|
|
2611
|
-
this.emit('
|
|
2617
|
+
this.emit('hset:before', ctx);
|
|
2612
2618
|
|
|
2613
2619
|
// 如果事件处理器标记为取消,则返回false
|
|
2614
|
-
if (
|
|
2615
|
-
|
|
2620
|
+
if (ctx.cancel) {
|
|
2621
|
+
this.logger('debug', `hset操作被事件处理器取消 [${key}:${field}]`);
|
|
2616
2622
|
return false;
|
|
2617
2623
|
}
|
|
2618
2624
|
|
|
@@ -2621,20 +2627,20 @@ Redis.prototype.hset = async function(key, field, value) {
|
|
|
2621
2627
|
key: finalKey,
|
|
2622
2628
|
field: finalField,
|
|
2623
2629
|
value: finalValue
|
|
2624
|
-
} =
|
|
2630
|
+
} = ctx;
|
|
2625
2631
|
|
|
2626
2632
|
const connection = await this._getConnection();
|
|
2627
2633
|
try {
|
|
2628
|
-
finalKey = this.
|
|
2634
|
+
finalKey = this._addPrefix(finalKey);
|
|
2629
2635
|
// 确保所有非字符串值都转换为字符串
|
|
2630
|
-
if (typeof(finalValue) !== "string") {
|
|
2636
|
+
if (typeof (finalValue) !== "string") {
|
|
2631
2637
|
finalValue = JSON.stringify(finalValue);
|
|
2632
2638
|
}
|
|
2633
2639
|
// 使用正确的Redis v4 API - hSet方法
|
|
2634
2640
|
const result = await connection.hSet(finalKey, finalField, finalValue);
|
|
2635
2641
|
|
|
2636
2642
|
// 触发后置事件
|
|
2637
|
-
this.emit('
|
|
2643
|
+
this.emit('hset:after', {
|
|
2638
2644
|
key: finalKey,
|
|
2639
2645
|
field: finalField,
|
|
2640
2646
|
value: finalValue,
|
|
@@ -2645,9 +2651,9 @@ Redis.prototype.hset = async function(key, field, value) {
|
|
|
2645
2651
|
this._recycleConnection(connection);
|
|
2646
2652
|
}
|
|
2647
2653
|
} catch (err) {
|
|
2648
|
-
|
|
2654
|
+
this.logger('error', `设置哈希字段失败 [${key}:${field}]:`, err);
|
|
2649
2655
|
// 触发错误事件
|
|
2650
|
-
this.emit('
|
|
2656
|
+
this.emit('hset:error', {
|
|
2651
2657
|
key,
|
|
2652
2658
|
field,
|
|
2653
2659
|
value,
|
|
@@ -2663,15 +2669,15 @@ Redis.prototype.hset = async function(key, field, value) {
|
|
|
2663
2669
|
* @param {String} field 字段
|
|
2664
2670
|
* @return {Promise<Object>} 字段值
|
|
2665
2671
|
*/
|
|
2666
|
-
Redis.prototype.hget = async function(key, field) {
|
|
2672
|
+
Redis.prototype.hget = async function (key, field) {
|
|
2667
2673
|
try {
|
|
2668
2674
|
const connection = await this._getConnection();
|
|
2669
2675
|
try {
|
|
2670
|
-
key = this.
|
|
2676
|
+
key = this._addPrefix(key);
|
|
2671
2677
|
// 使用正确的Redis v4 API - hGet方法
|
|
2672
2678
|
const value = await connection.hGet(key, field);
|
|
2673
2679
|
// 尝试解析JSON
|
|
2674
|
-
if (value && typeof(value) === 'string') {
|
|
2680
|
+
if (value && typeof (value) === 'string') {
|
|
2675
2681
|
try {
|
|
2676
2682
|
if (value.startsWith('{') && value.endsWith('}') ||
|
|
2677
2683
|
value.startsWith('[') && value.endsWith(']')) {
|
|
@@ -2687,7 +2693,7 @@ Redis.prototype.hget = async function(key, field) {
|
|
|
2687
2693
|
this._recycleConnection(connection);
|
|
2688
2694
|
}
|
|
2689
2695
|
} catch (err) {
|
|
2690
|
-
|
|
2696
|
+
this.logger('error', `获取哈希字段失败 [${key}:${field}]:`, err);
|
|
2691
2697
|
return null;
|
|
2692
2698
|
}
|
|
2693
2699
|
};
|
|
@@ -2698,19 +2704,19 @@ Redis.prototype.hget = async function(key, field) {
|
|
|
2698
2704
|
* @param {Object} obj 字段值对象
|
|
2699
2705
|
* @return {Promise<Boolean>} 操作结果
|
|
2700
2706
|
*/
|
|
2701
|
-
Redis.prototype.hmset = async function(key, obj) {
|
|
2707
|
+
Redis.prototype.hmset = async function (key, obj) {
|
|
2702
2708
|
try {
|
|
2703
2709
|
// 触发前置事件,允许修改或阻止操作
|
|
2704
|
-
const
|
|
2710
|
+
const ctx = {
|
|
2705
2711
|
key,
|
|
2706
2712
|
value: obj,
|
|
2707
2713
|
cancel: false
|
|
2708
2714
|
};
|
|
2709
|
-
this.emit('
|
|
2715
|
+
this.emit('hmset:before', ctx);
|
|
2710
2716
|
|
|
2711
2717
|
// 如果事件处理器标记为取消,则返回false
|
|
2712
|
-
if (
|
|
2713
|
-
|
|
2718
|
+
if (ctx.cancel) {
|
|
2719
|
+
this.logger('debug', `hmset操作被事件处理器取消 [${key}]`);
|
|
2714
2720
|
return false;
|
|
2715
2721
|
}
|
|
2716
2722
|
|
|
@@ -2718,27 +2724,27 @@ Redis.prototype.hmset = async function(key, obj) {
|
|
|
2718
2724
|
let {
|
|
2719
2725
|
key: finalKey,
|
|
2720
2726
|
value: finalObj
|
|
2721
|
-
} =
|
|
2727
|
+
} = ctx;
|
|
2722
2728
|
|
|
2723
2729
|
const connection = await this._getConnection();
|
|
2724
2730
|
try {
|
|
2725
|
-
finalKey = this.
|
|
2731
|
+
finalKey = this._addPrefix(finalKey);
|
|
2726
2732
|
|
|
2727
2733
|
// 检查Redis版本,支持不同的方法
|
|
2728
|
-
|
|
2729
|
-
`
|
|
2734
|
+
this.logger('debug',
|
|
2735
|
+
`hmset方法检测到连接对象方法: hSet=${typeof connection.hSet === 'function'}, hmset=${typeof connection.hmset === 'function'}`
|
|
2730
2736
|
);
|
|
2731
2737
|
let success = true;
|
|
2732
2738
|
|
|
2733
2739
|
// 优化策略:对所有Redis版本都使用逐个字段设置的方式,确保兼容性和正确性
|
|
2734
|
-
|
|
2740
|
+
this.logger('debug', `对键 ${finalKey} 强制使用逐个字段设置策略`);
|
|
2735
2741
|
|
|
2736
2742
|
// 获取适合的设置字段方法
|
|
2737
2743
|
const setFieldMethod = typeof connection.hSet === 'function' ? 'hSet' :
|
|
2738
2744
|
typeof connection.hset === 'function' ? 'hset' : null;
|
|
2739
2745
|
|
|
2740
2746
|
if (!setFieldMethod) {
|
|
2741
|
-
|
|
2747
|
+
this.logger('error', `连接对象不支持hSet或hset操作`);
|
|
2742
2748
|
return false;
|
|
2743
2749
|
}
|
|
2744
2750
|
|
|
@@ -2750,10 +2756,10 @@ Redis.prototype.hmset = async function(key, obj) {
|
|
|
2750
2756
|
if (typeof value !== 'string') {
|
|
2751
2757
|
value = JSON.stringify(value);
|
|
2752
2758
|
}
|
|
2753
|
-
|
|
2759
|
+
this.logger('debug', `单独设置字段: ${setFieldMethod}(${finalKey}, ${field}, ${value})`);
|
|
2754
2760
|
await connection[setFieldMethod](finalKey, field, value);
|
|
2755
2761
|
} catch (singleError) {
|
|
2756
|
-
|
|
2762
|
+
this.logger('error', `设置单个字段失败 ${field}: ${singleError.message}`);
|
|
2757
2763
|
success = false;
|
|
2758
2764
|
break;
|
|
2759
2765
|
}
|
|
@@ -2762,19 +2768,19 @@ Redis.prototype.hmset = async function(key, obj) {
|
|
|
2762
2768
|
|
|
2763
2769
|
// 验证所有字段是否都设置成功
|
|
2764
2770
|
if (success) {
|
|
2765
|
-
|
|
2771
|
+
this.logger('debug', `验证所有字段设置情况`);
|
|
2766
2772
|
for (const field in finalObj) {
|
|
2767
2773
|
if (finalObj.hasOwnProperty(field)) {
|
|
2768
2774
|
try {
|
|
2769
2775
|
const hgetMethod = typeof connection.hGet === 'function' ? 'hGet' : 'hget';
|
|
2770
2776
|
const value = await connection[hgetMethod](finalKey, field);
|
|
2771
|
-
|
|
2777
|
+
this.logger('debug', `验证字段 ${field}: ${value !== null ? '存在' : '不存在'}`);
|
|
2772
2778
|
// 如果字段不存在,更新success状态
|
|
2773
2779
|
if (value === null) {
|
|
2774
2780
|
success = false;
|
|
2775
2781
|
}
|
|
2776
2782
|
} catch (getError) {
|
|
2777
|
-
|
|
2783
|
+
this.logger('error', `验证字段失败 ${field}: ${getError.message}`);
|
|
2778
2784
|
success = false;
|
|
2779
2785
|
}
|
|
2780
2786
|
}
|
|
@@ -2782,7 +2788,7 @@ Redis.prototype.hmset = async function(key, obj) {
|
|
|
2782
2788
|
}
|
|
2783
2789
|
|
|
2784
2790
|
// 触发后置事件
|
|
2785
|
-
this.emit('
|
|
2791
|
+
this.emit('hmset:after', {
|
|
2786
2792
|
key: finalKey,
|
|
2787
2793
|
value: finalObj,
|
|
2788
2794
|
success: success
|
|
@@ -2792,9 +2798,9 @@ Redis.prototype.hmset = async function(key, obj) {
|
|
|
2792
2798
|
this._recycleConnection(connection);
|
|
2793
2799
|
}
|
|
2794
2800
|
} catch (err) {
|
|
2795
|
-
|
|
2801
|
+
this.logger('error', `批量设置哈希字段失败 [${key}]:`, err);
|
|
2796
2802
|
// 触发错误事件
|
|
2797
|
-
this.emit('
|
|
2803
|
+
this.emit('hmset:error', {
|
|
2798
2804
|
key,
|
|
2799
2805
|
value: obj,
|
|
2800
2806
|
error: err
|
|
@@ -2808,23 +2814,23 @@ Redis.prototype.hmset = async function(key, obj) {
|
|
|
2808
2814
|
* @param {String} key 键
|
|
2809
2815
|
* @return {Promise<Object>} 所有字段和值
|
|
2810
2816
|
*/
|
|
2811
|
-
Redis.prototype.hgetall = async function(key) {
|
|
2817
|
+
Redis.prototype.hgetall = async function (key) {
|
|
2812
2818
|
try {
|
|
2813
2819
|
const connection = await this._getConnection();
|
|
2814
2820
|
try {
|
|
2815
|
-
key = this.
|
|
2821
|
+
key = this._addPrefix(key);
|
|
2816
2822
|
if (typeof connection.hGetAll === 'function') {
|
|
2817
2823
|
const result = await connection.hGetAll(key);
|
|
2818
2824
|
return result;
|
|
2819
2825
|
} else {
|
|
2820
|
-
|
|
2826
|
+
this.logger('error', '连接对象不支持hGetAll操作');
|
|
2821
2827
|
return {};
|
|
2822
2828
|
}
|
|
2823
2829
|
} finally {
|
|
2824
2830
|
this._recycleConnection(connection);
|
|
2825
2831
|
}
|
|
2826
2832
|
} catch (err) {
|
|
2827
|
-
|
|
2833
|
+
this.logger('error', `获取哈希所有字段和值失败 [${key}]:`, err);
|
|
2828
2834
|
return {};
|
|
2829
2835
|
}
|
|
2830
2836
|
};
|
|
@@ -2835,28 +2841,26 @@ Redis.prototype.hgetall = async function(key) {
|
|
|
2835
2841
|
* @param {Array} fields 字段名数组
|
|
2836
2842
|
* @return {Promise<Array>} 与字段名顺序对应的数组值,不存在返回undefined
|
|
2837
2843
|
*/
|
|
2838
|
-
Redis.prototype.hmget = async function(key, fields) {
|
|
2844
|
+
Redis.prototype.hmget = async function (key, fields) {
|
|
2839
2845
|
try {
|
|
2840
2846
|
if (!Array.isArray(fields)) {
|
|
2841
|
-
|
|
2842
|
-
// 返回空数组而不是false,保持与注释类型一致
|
|
2843
|
-
return [];
|
|
2847
|
+
throw new TypeError('fields必须是数组');
|
|
2844
2848
|
}
|
|
2845
2849
|
|
|
2846
|
-
this.emit('
|
|
2850
|
+
this.emit('hmget:before', {
|
|
2847
2851
|
key,
|
|
2848
2852
|
fields
|
|
2849
2853
|
});
|
|
2850
2854
|
|
|
2851
2855
|
const connection = await this._getConnection();
|
|
2852
2856
|
try {
|
|
2853
|
-
key = this.
|
|
2857
|
+
key = this._addPrefix(key);
|
|
2854
2858
|
|
|
2855
2859
|
if (typeof connection.hmGet === 'function') {
|
|
2856
2860
|
const result = await connection.hmGet(key, fields);
|
|
2857
2861
|
// 将null转换为undefined以保持与CacheBase行为一致
|
|
2858
2862
|
const finalResult = result.map(value => value === null ? undefined : value);
|
|
2859
|
-
this.emit('
|
|
2863
|
+
this.emit('hmget:after', {
|
|
2860
2864
|
key,
|
|
2861
2865
|
fields,
|
|
2862
2866
|
result: finalResult
|
|
@@ -2869,15 +2873,15 @@ Redis.prototype.hmget = async function(key, fields) {
|
|
|
2869
2873
|
const value = allFields[field];
|
|
2870
2874
|
return value === null || value === undefined ? undefined : value;
|
|
2871
2875
|
});
|
|
2872
|
-
this.emit('
|
|
2876
|
+
this.emit('hmget:after', {
|
|
2873
2877
|
key,
|
|
2874
2878
|
fields,
|
|
2875
2879
|
result: finalResult
|
|
2876
2880
|
});
|
|
2877
2881
|
return finalResult;
|
|
2878
2882
|
} else {
|
|
2879
|
-
|
|
2880
|
-
|
|
2883
|
+
this.logger('error', '连接对象不支持hmGet操作');
|
|
2884
|
+
this.logger('error', '错误: Redis客户端不支持hmget操作');
|
|
2881
2885
|
// 返回与fields长度相同的undefined数组,保持与注释一致
|
|
2882
2886
|
return fields.map(() => undefined);
|
|
2883
2887
|
}
|
|
@@ -2885,12 +2889,12 @@ Redis.prototype.hmget = async function(key, fields) {
|
|
|
2885
2889
|
this._recycleConnection(connection);
|
|
2886
2890
|
}
|
|
2887
2891
|
} catch (err) {
|
|
2888
|
-
this.emit('
|
|
2892
|
+
this.emit('hmget:error', {
|
|
2889
2893
|
key,
|
|
2890
2894
|
fields,
|
|
2891
2895
|
error: err
|
|
2892
2896
|
});
|
|
2893
|
-
|
|
2897
|
+
this.logger('error', `哈希表批量获取失败 [${key}]:`, err);
|
|
2894
2898
|
// 返回与fields长度相同的undefined数组,保持与注释类型一致
|
|
2895
2899
|
return fields.map(() => undefined);
|
|
2896
2900
|
}
|
|
@@ -2901,41 +2905,41 @@ Redis.prototype.hmget = async function(key, fields) {
|
|
|
2901
2905
|
* @param {Number} seconds 过期时间(秒)
|
|
2902
2906
|
* @return {Promise<Boolean>} 操作结果
|
|
2903
2907
|
*/
|
|
2904
|
-
Redis.prototype.expire = async function(key, seconds) {
|
|
2908
|
+
Redis.prototype.expire = async function (key, seconds) {
|
|
2905
2909
|
try {
|
|
2906
2910
|
// 触发前置事件
|
|
2907
|
-
const
|
|
2911
|
+
const ctx = {
|
|
2908
2912
|
key,
|
|
2909
2913
|
ttl: seconds,
|
|
2910
2914
|
cancel: false
|
|
2911
2915
|
};
|
|
2912
|
-
this.emit('
|
|
2916
|
+
this.emit('expire:before', ctx);
|
|
2913
2917
|
|
|
2914
|
-
if (
|
|
2915
|
-
|
|
2918
|
+
if (ctx.cancel) {
|
|
2919
|
+
this.logger('debug', `expire操作被事件处理器取消 [${key}]`);
|
|
2916
2920
|
return false;
|
|
2917
2921
|
}
|
|
2918
2922
|
|
|
2919
2923
|
const {
|
|
2920
2924
|
key: finalKey,
|
|
2921
2925
|
ttl: finalSeconds
|
|
2922
|
-
} =
|
|
2926
|
+
} = ctx;
|
|
2923
2927
|
|
|
2924
2928
|
const connection = await this._getConnection();
|
|
2925
2929
|
try {
|
|
2926
2930
|
// 使用正确的Redis客户端Promise API
|
|
2927
|
-
const result = await connection.expire(this.
|
|
2931
|
+
const result = await connection.expire(this._addPrefix(finalKey), finalSeconds);
|
|
2928
2932
|
|
|
2929
2933
|
// 触发后置事件
|
|
2930
|
-
this.emit('
|
|
2934
|
+
this.emit('expire:after', {
|
|
2931
2935
|
key: finalKey,
|
|
2932
2936
|
ttl: finalSeconds,
|
|
2933
2937
|
success: result === 1
|
|
2934
2938
|
});
|
|
2935
2939
|
return result === 1;
|
|
2936
2940
|
} catch (err) {
|
|
2937
|
-
|
|
2938
|
-
this.emit('
|
|
2941
|
+
this.logger('error', `设置过期时间失败 [${finalKey}]:`, err);
|
|
2942
|
+
this.emit('expire:error', {
|
|
2939
2943
|
key: finalKey,
|
|
2940
2944
|
ttl: finalSeconds,
|
|
2941
2945
|
error: err
|
|
@@ -2945,8 +2949,8 @@ Redis.prototype.expire = async function(key, seconds) {
|
|
|
2945
2949
|
this._recycleConnection(connection);
|
|
2946
2950
|
}
|
|
2947
2951
|
} catch (err) {
|
|
2948
|
-
|
|
2949
|
-
this.emit('
|
|
2952
|
+
this.logger('error', `设置过期时间失败 [${key}]:`, err);
|
|
2953
|
+
this.emit('expire:error', {
|
|
2950
2954
|
key,
|
|
2951
2955
|
ttl: seconds,
|
|
2952
2956
|
error: err
|
|
@@ -2961,59 +2965,57 @@ Redis.prototype.expire = async function(key, seconds) {
|
|
|
2961
2965
|
* @param {Number} milliseconds 过期时间(毫秒)
|
|
2962
2966
|
* @return {Promise<Boolean>} 操作结果
|
|
2963
2967
|
*/
|
|
2964
|
-
Redis.prototype.pexpire = async function(key, milliseconds) {
|
|
2968
|
+
Redis.prototype.pexpire = async function (key, milliseconds) {
|
|
2965
2969
|
try {
|
|
2966
2970
|
// 参数验证
|
|
2967
2971
|
if (!key || typeof key !== 'string') {
|
|
2968
|
-
|
|
2969
|
-
return false;
|
|
2972
|
+
throw new TypeError('key必须是非空字符串');
|
|
2970
2973
|
}
|
|
2971
2974
|
if (!Number.isInteger(milliseconds) || milliseconds <= 0) {
|
|
2972
|
-
|
|
2973
|
-
return false;
|
|
2975
|
+
throw new TypeError('milliseconds必须是正整数');
|
|
2974
2976
|
}
|
|
2975
2977
|
|
|
2976
2978
|
// 触发前置事件
|
|
2977
|
-
const
|
|
2979
|
+
const ctx = {
|
|
2978
2980
|
key,
|
|
2979
2981
|
ttl: milliseconds,
|
|
2980
2982
|
cancel: false
|
|
2981
2983
|
};
|
|
2982
|
-
this.emit('
|
|
2984
|
+
this.emit('pexpire:before', ctx);
|
|
2983
2985
|
|
|
2984
|
-
if (
|
|
2985
|
-
|
|
2986
|
+
if (ctx.cancel) {
|
|
2987
|
+
this.logger('debug', `pexpire操作被事件处理器取消 [${key}]`);
|
|
2986
2988
|
return false;
|
|
2987
2989
|
}
|
|
2988
2990
|
|
|
2989
2991
|
const {
|
|
2990
2992
|
key: finalKey,
|
|
2991
2993
|
ttl: finalMilliseconds
|
|
2992
|
-
} =
|
|
2994
|
+
} = ctx;
|
|
2993
2995
|
|
|
2994
2996
|
const connection = await this._getConnection();
|
|
2995
2997
|
try {
|
|
2996
2998
|
// 使用正确的Redis客户端Promise API
|
|
2997
2999
|
let result;
|
|
2998
3000
|
if (typeof connection.pexpire === 'function') {
|
|
2999
|
-
result = await connection.pexpire(this.
|
|
3001
|
+
result = await connection.pexpire(this._addPrefix(finalKey), finalMilliseconds);
|
|
3000
3002
|
} else if (typeof connection.execute === 'function') {
|
|
3001
|
-
result = await connection.execute('PEXPIRE', [this.
|
|
3003
|
+
result = await connection.execute('PEXPIRE', [this._addPrefix(finalKey), finalMilliseconds]);
|
|
3002
3004
|
} else {
|
|
3003
|
-
|
|
3005
|
+
this.logger('error', '连接对象不支持pexpire操作');
|
|
3004
3006
|
return false;
|
|
3005
3007
|
}
|
|
3006
3008
|
|
|
3007
3009
|
// 触发后置事件
|
|
3008
|
-
this.emit('
|
|
3010
|
+
this.emit('pexpire:after', {
|
|
3009
3011
|
key: finalKey,
|
|
3010
3012
|
ttl: finalMilliseconds,
|
|
3011
3013
|
success: result === 1
|
|
3012
3014
|
});
|
|
3013
3015
|
return result === 1;
|
|
3014
3016
|
} catch (err) {
|
|
3015
|
-
|
|
3016
|
-
this.emit('
|
|
3017
|
+
this.logger('error', `设置过期时间(毫秒)失败 [${finalKey}]:`, err);
|
|
3018
|
+
this.emit('pexpire:error', {
|
|
3017
3019
|
key: finalKey,
|
|
3018
3020
|
ttl: finalMilliseconds,
|
|
3019
3021
|
error: err
|
|
@@ -3023,8 +3025,8 @@ Redis.prototype.pexpire = async function(key, milliseconds) {
|
|
|
3023
3025
|
this._recycleConnection(connection);
|
|
3024
3026
|
}
|
|
3025
3027
|
} catch (err) {
|
|
3026
|
-
|
|
3027
|
-
this.emit('
|
|
3028
|
+
this.logger('error', `设置过期时间(毫秒)失败 [${key}]:`, err);
|
|
3029
|
+
this.emit('pexpire:error', {
|
|
3028
3030
|
key,
|
|
3029
3031
|
ttl: milliseconds,
|
|
3030
3032
|
error: err
|
|
@@ -3034,38 +3036,38 @@ Redis.prototype.pexpire = async function(key, milliseconds) {
|
|
|
3034
3036
|
};
|
|
3035
3037
|
|
|
3036
3038
|
// 新增persist方法实现
|
|
3037
|
-
Redis.prototype.persist = async function(key) {
|
|
3039
|
+
Redis.prototype.persist = async function (key) {
|
|
3038
3040
|
try {
|
|
3039
3041
|
// 触发前置事件
|
|
3040
|
-
const
|
|
3042
|
+
const ctx = {
|
|
3041
3043
|
key,
|
|
3042
3044
|
cancel: false
|
|
3043
3045
|
};
|
|
3044
|
-
this.emit('
|
|
3046
|
+
this.emit('persist:before', ctx);
|
|
3045
3047
|
|
|
3046
|
-
if (
|
|
3047
|
-
|
|
3048
|
+
if (ctx.cancel) {
|
|
3049
|
+
this.logger('debug', `persist操作被事件处理器取消 [${key}]`);
|
|
3048
3050
|
return false;
|
|
3049
3051
|
}
|
|
3050
3052
|
|
|
3051
3053
|
const {
|
|
3052
3054
|
key: finalKey
|
|
3053
|
-
} =
|
|
3055
|
+
} = ctx;
|
|
3054
3056
|
|
|
3055
3057
|
const connection = await this._getConnection();
|
|
3056
3058
|
try {
|
|
3057
3059
|
// 使用正确的Redis客户端Promise API
|
|
3058
|
-
const result = await connection.persist(this.
|
|
3060
|
+
const result = await connection.persist(this._addPrefix(finalKey));
|
|
3059
3061
|
|
|
3060
3062
|
// 触发后置事件
|
|
3061
|
-
this.emit('
|
|
3063
|
+
this.emit('persist:after', {
|
|
3062
3064
|
key: finalKey,
|
|
3063
3065
|
success: result === 1
|
|
3064
3066
|
});
|
|
3065
3067
|
return result === 1;
|
|
3066
3068
|
} catch (err) {
|
|
3067
|
-
|
|
3068
|
-
this.emit('
|
|
3069
|
+
this.logger('error', `移除过期时间失败 [${finalKey}]:`, err);
|
|
3070
|
+
this.emit('persist:error', {
|
|
3069
3071
|
key: finalKey,
|
|
3070
3072
|
error: err
|
|
3071
3073
|
});
|
|
@@ -3074,8 +3076,8 @@ Redis.prototype.persist = async function(key) {
|
|
|
3074
3076
|
this._recycleConnection(connection);
|
|
3075
3077
|
}
|
|
3076
3078
|
} catch (err) {
|
|
3077
|
-
|
|
3078
|
-
this.emit('
|
|
3079
|
+
this.logger('error', `移除过期时间失败 [${key}]:`, err);
|
|
3080
|
+
this.emit('persist:error', {
|
|
3079
3081
|
key,
|
|
3080
3082
|
error: err
|
|
3081
3083
|
});
|
|
@@ -3089,35 +3091,34 @@ Redis.prototype.persist = async function(key) {
|
|
|
3089
3091
|
* @param {Number} [seconds=0] 过期时间(秒)
|
|
3090
3092
|
* @return {Promise<Number>} 增加后的值
|
|
3091
3093
|
*/
|
|
3092
|
-
Redis.prototype.incr = async function(key, seconds = 0) {
|
|
3094
|
+
Redis.prototype.incr = async function (key, seconds = 0) {
|
|
3093
3095
|
try {
|
|
3094
3096
|
// 参数验证
|
|
3095
3097
|
if (!key || typeof key !== 'string') {
|
|
3096
|
-
|
|
3097
|
-
return null;
|
|
3098
|
+
throw new TypeError('键必须是非空字符串');
|
|
3098
3099
|
}
|
|
3099
3100
|
|
|
3100
3101
|
// 触发前置事件
|
|
3101
|
-
const
|
|
3102
|
+
const ctx = {
|
|
3102
3103
|
key,
|
|
3103
3104
|
seconds,
|
|
3104
3105
|
cancel: false
|
|
3105
3106
|
};
|
|
3106
|
-
this.emit('
|
|
3107
|
+
this.emit('incr:before', ctx);
|
|
3107
3108
|
|
|
3108
|
-
if (
|
|
3109
|
-
|
|
3109
|
+
if (ctx.cancel) {
|
|
3110
|
+
this.logger('debug', `incr操作被事件处理器取消 [${key}]`);
|
|
3110
3111
|
return null;
|
|
3111
3112
|
}
|
|
3112
3113
|
|
|
3113
3114
|
const {
|
|
3114
3115
|
key: finalKey,
|
|
3115
3116
|
seconds: finalSeconds
|
|
3116
|
-
} =
|
|
3117
|
+
} = ctx;
|
|
3117
3118
|
|
|
3118
3119
|
const connection = await this._getConnection();
|
|
3119
3120
|
try {
|
|
3120
|
-
const prefixedKey = this.
|
|
3121
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
3121
3122
|
// 使用正确的Redis客户端Promise API
|
|
3122
3123
|
const result = await connection.incr(prefixedKey);
|
|
3123
3124
|
|
|
@@ -3130,15 +3131,15 @@ Redis.prototype.incr = async function(key, seconds = 0) {
|
|
|
3130
3131
|
}
|
|
3131
3132
|
}
|
|
3132
3133
|
|
|
3133
|
-
this.emit('
|
|
3134
|
+
this.emit('incr:after', {
|
|
3134
3135
|
key: finalKey,
|
|
3135
3136
|
seconds: finalSeconds,
|
|
3136
3137
|
result
|
|
3137
3138
|
});
|
|
3138
3139
|
return result;
|
|
3139
3140
|
} catch (err) {
|
|
3140
|
-
|
|
3141
|
-
this.emit('
|
|
3141
|
+
this.logger('error', `增加整数值失败 [${finalKey}]:`, err);
|
|
3142
|
+
this.emit('incr:error', {
|
|
3142
3143
|
key: finalKey,
|
|
3143
3144
|
seconds: finalSeconds,
|
|
3144
3145
|
error: err
|
|
@@ -3148,8 +3149,8 @@ Redis.prototype.incr = async function(key, seconds = 0) {
|
|
|
3148
3149
|
this._recycleConnection(connection);
|
|
3149
3150
|
}
|
|
3150
3151
|
} catch (err) {
|
|
3151
|
-
|
|
3152
|
-
this.emit('
|
|
3152
|
+
this.logger('error', `增加整数值失败 [${key}]:`, err);
|
|
3153
|
+
this.emit('incr:error', {
|
|
3153
3154
|
key,
|
|
3154
3155
|
seconds,
|
|
3155
3156
|
error: err
|
|
@@ -3164,35 +3165,34 @@ Redis.prototype.incr = async function(key, seconds = 0) {
|
|
|
3164
3165
|
* @param {Number} [seconds=0] 过期时间(秒)
|
|
3165
3166
|
* @return {Promise<Number>} 减少后的值
|
|
3166
3167
|
*/
|
|
3167
|
-
Redis.prototype.decr = async function(key, seconds = 0) {
|
|
3168
|
+
Redis.prototype.decr = async function (key, seconds = 0) {
|
|
3168
3169
|
try {
|
|
3169
3170
|
// 参数验证
|
|
3170
3171
|
if (!key || typeof key !== 'string') {
|
|
3171
|
-
|
|
3172
|
-
return null;
|
|
3172
|
+
throw new TypeError('键必须是非空字符串');
|
|
3173
3173
|
}
|
|
3174
3174
|
|
|
3175
3175
|
// 触发前置事件
|
|
3176
|
-
const
|
|
3176
|
+
const ctx = {
|
|
3177
3177
|
key,
|
|
3178
3178
|
seconds,
|
|
3179
3179
|
cancel: false
|
|
3180
3180
|
};
|
|
3181
|
-
this.emit('
|
|
3181
|
+
this.emit('decr:before', ctx);
|
|
3182
3182
|
|
|
3183
|
-
if (
|
|
3184
|
-
|
|
3183
|
+
if (ctx.cancel) {
|
|
3184
|
+
this.logger('debug', `decr操作被事件处理器取消 [${key}]`);
|
|
3185
3185
|
return null;
|
|
3186
3186
|
}
|
|
3187
3187
|
|
|
3188
3188
|
const {
|
|
3189
3189
|
key: finalKey,
|
|
3190
3190
|
seconds: finalSeconds
|
|
3191
|
-
} =
|
|
3191
|
+
} = ctx;
|
|
3192
3192
|
|
|
3193
3193
|
const connection = await this._getConnection();
|
|
3194
3194
|
try {
|
|
3195
|
-
const prefixedKey = this.
|
|
3195
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
3196
3196
|
// 使用正确的Redis客户端Promise API
|
|
3197
3197
|
const result = await connection.decr(prefixedKey);
|
|
3198
3198
|
|
|
@@ -3205,15 +3205,15 @@ Redis.prototype.decr = async function(key, seconds = 0) {
|
|
|
3205
3205
|
}
|
|
3206
3206
|
}
|
|
3207
3207
|
|
|
3208
|
-
this.emit('
|
|
3208
|
+
this.emit('decr:after', {
|
|
3209
3209
|
key: finalKey,
|
|
3210
3210
|
seconds: finalSeconds,
|
|
3211
3211
|
result
|
|
3212
3212
|
});
|
|
3213
3213
|
return result;
|
|
3214
3214
|
} catch (err) {
|
|
3215
|
-
|
|
3216
|
-
this.emit('
|
|
3215
|
+
this.logger('error', `减少整数值失败 [${finalKey}]:`, err);
|
|
3216
|
+
this.emit('decr:error', {
|
|
3217
3217
|
key: finalKey,
|
|
3218
3218
|
seconds: finalSeconds,
|
|
3219
3219
|
error: err
|
|
@@ -3223,8 +3223,8 @@ Redis.prototype.decr = async function(key, seconds = 0) {
|
|
|
3223
3223
|
this._recycleConnection(connection);
|
|
3224
3224
|
}
|
|
3225
3225
|
} catch (err) {
|
|
3226
|
-
|
|
3227
|
-
this.emit('
|
|
3226
|
+
this.logger('error', `减少整数值失败 [${key}]:`, err);
|
|
3227
|
+
this.emit('decr:error', {
|
|
3228
3228
|
key,
|
|
3229
3229
|
seconds,
|
|
3230
3230
|
error: err
|
|
@@ -3240,29 +3240,27 @@ Redis.prototype.decr = async function(key, seconds = 0) {
|
|
|
3240
3240
|
* @param {Number} [seconds=0] 过期时间(秒)
|
|
3241
3241
|
* @return {Promise<Number>} 增加后的值
|
|
3242
3242
|
*/
|
|
3243
|
-
Redis.prototype.incrbyfloat = async function(key, increment, seconds = 0) {
|
|
3243
|
+
Redis.prototype.incrbyfloat = async function (key, increment, seconds = 0) {
|
|
3244
3244
|
try {
|
|
3245
3245
|
// 参数验证
|
|
3246
3246
|
if (!key || typeof key !== 'string') {
|
|
3247
|
-
|
|
3248
|
-
return null;
|
|
3247
|
+
throw new TypeError('键必须是非空字符串');
|
|
3249
3248
|
}
|
|
3250
3249
|
if (typeof increment !== 'number' || isNaN(increment)) {
|
|
3251
|
-
|
|
3252
|
-
return null;
|
|
3250
|
+
throw new TypeError('增量必须是有效数字');
|
|
3253
3251
|
}
|
|
3254
3252
|
|
|
3255
3253
|
// 触发前置事件
|
|
3256
|
-
const
|
|
3254
|
+
const ctx = {
|
|
3257
3255
|
key,
|
|
3258
3256
|
increment,
|
|
3259
3257
|
seconds,
|
|
3260
3258
|
cancel: false
|
|
3261
3259
|
};
|
|
3262
|
-
this.emit('
|
|
3260
|
+
this.emit('incrbyfloat:before', ctx);
|
|
3263
3261
|
|
|
3264
|
-
if (
|
|
3265
|
-
|
|
3262
|
+
if (ctx.cancel) {
|
|
3263
|
+
this.logger('debug', `incrbyfloat操作被事件处理器取消 [${key}]`);
|
|
3266
3264
|
return null;
|
|
3267
3265
|
}
|
|
3268
3266
|
|
|
@@ -3270,11 +3268,11 @@ Redis.prototype.incrbyfloat = async function(key, increment, seconds = 0) {
|
|
|
3270
3268
|
key: finalKey,
|
|
3271
3269
|
increment: finalIncrement,
|
|
3272
3270
|
seconds: finalSeconds
|
|
3273
|
-
} =
|
|
3271
|
+
} = ctx;
|
|
3274
3272
|
|
|
3275
3273
|
const connection = await this._getConnection();
|
|
3276
3274
|
try {
|
|
3277
|
-
const prefixedKey = this.
|
|
3275
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
3278
3276
|
// 使用正确的Redis客户端Promise API
|
|
3279
3277
|
const result = await connection.incrByFloat(prefixedKey, finalIncrement);
|
|
3280
3278
|
const parsedResult = parseFloat(result);
|
|
@@ -3288,7 +3286,7 @@ Redis.prototype.incrbyfloat = async function(key, increment, seconds = 0) {
|
|
|
3288
3286
|
}
|
|
3289
3287
|
}
|
|
3290
3288
|
|
|
3291
|
-
this.emit('
|
|
3289
|
+
this.emit('incrbyfloat:after', {
|
|
3292
3290
|
key: finalKey,
|
|
3293
3291
|
increment: finalIncrement,
|
|
3294
3292
|
seconds: finalSeconds,
|
|
@@ -3296,8 +3294,8 @@ Redis.prototype.incrbyfloat = async function(key, increment, seconds = 0) {
|
|
|
3296
3294
|
});
|
|
3297
3295
|
return parsedResult;
|
|
3298
3296
|
} catch (err) {
|
|
3299
|
-
|
|
3300
|
-
this.emit('
|
|
3297
|
+
this.logger('error', `增加浮点数值失败 [${finalKey}]:`, err);
|
|
3298
|
+
this.emit('incrbyfloat:error', {
|
|
3301
3299
|
key: finalKey,
|
|
3302
3300
|
increment: finalIncrement,
|
|
3303
3301
|
seconds: finalSeconds,
|
|
@@ -3308,8 +3306,8 @@ Redis.prototype.incrbyfloat = async function(key, increment, seconds = 0) {
|
|
|
3308
3306
|
this._recycleConnection(connection);
|
|
3309
3307
|
}
|
|
3310
3308
|
} catch (err) {
|
|
3311
|
-
|
|
3312
|
-
this.emit('
|
|
3309
|
+
this.logger('error', `增加浮点数值失败 [${key}]:`, err);
|
|
3310
|
+
this.emit('incrbyfloat:error', {
|
|
3313
3311
|
key,
|
|
3314
3312
|
increment,
|
|
3315
3313
|
seconds,
|
|
@@ -3326,29 +3324,27 @@ Redis.prototype.incrbyfloat = async function(key, increment, seconds = 0) {
|
|
|
3326
3324
|
* @param {Number} [seconds=0] 过期时间(秒)
|
|
3327
3325
|
* @return {Promise<Number>} 增加后的值
|
|
3328
3326
|
*/
|
|
3329
|
-
Redis.prototype.incrby = async function(key, increment, seconds = 0) {
|
|
3327
|
+
Redis.prototype.incrby = async function (key, increment, seconds = 0) {
|
|
3330
3328
|
try {
|
|
3331
3329
|
// 参数验证
|
|
3332
3330
|
if (!key || typeof key !== 'string') {
|
|
3333
|
-
|
|
3334
|
-
return null;
|
|
3331
|
+
throw new TypeError('键必须是非空字符串');
|
|
3335
3332
|
}
|
|
3336
3333
|
if (typeof increment !== 'number' || isNaN(increment) || !Number.isInteger(increment)) {
|
|
3337
|
-
|
|
3338
|
-
return null;
|
|
3334
|
+
throw new TypeError('增量必须是有效整数');
|
|
3339
3335
|
}
|
|
3340
3336
|
|
|
3341
3337
|
// 触发前置事件
|
|
3342
|
-
const
|
|
3338
|
+
const ctx = {
|
|
3343
3339
|
key,
|
|
3344
3340
|
increment,
|
|
3345
3341
|
seconds,
|
|
3346
3342
|
cancel: false
|
|
3347
3343
|
};
|
|
3348
|
-
this.emit('
|
|
3344
|
+
this.emit('incrby:before', ctx);
|
|
3349
3345
|
|
|
3350
|
-
if (
|
|
3351
|
-
|
|
3346
|
+
if (ctx.cancel) {
|
|
3347
|
+
this.logger('debug', `incrby操作被事件处理器取消 [${key}]`);
|
|
3352
3348
|
return null;
|
|
3353
3349
|
}
|
|
3354
3350
|
|
|
@@ -3356,11 +3352,11 @@ Redis.prototype.incrby = async function(key, increment, seconds = 0) {
|
|
|
3356
3352
|
key: finalKey,
|
|
3357
3353
|
increment: finalIncrement,
|
|
3358
3354
|
seconds: finalSeconds
|
|
3359
|
-
} =
|
|
3355
|
+
} = ctx;
|
|
3360
3356
|
|
|
3361
3357
|
const connection = await this._getConnection();
|
|
3362
3358
|
try {
|
|
3363
|
-
const prefixedKey = this.
|
|
3359
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
3364
3360
|
// 使用正确的Redis客户端Promise API
|
|
3365
3361
|
const result = await connection.incrBy(prefixedKey, finalIncrement);
|
|
3366
3362
|
|
|
@@ -3373,7 +3369,7 @@ Redis.prototype.incrby = async function(key, increment, seconds = 0) {
|
|
|
3373
3369
|
}
|
|
3374
3370
|
}
|
|
3375
3371
|
|
|
3376
|
-
this.emit('
|
|
3372
|
+
this.emit('incrby:after', {
|
|
3377
3373
|
key: finalKey,
|
|
3378
3374
|
increment: finalIncrement,
|
|
3379
3375
|
seconds: finalSeconds,
|
|
@@ -3381,8 +3377,8 @@ Redis.prototype.incrby = async function(key, increment, seconds = 0) {
|
|
|
3381
3377
|
});
|
|
3382
3378
|
return result;
|
|
3383
3379
|
} catch (err) {
|
|
3384
|
-
|
|
3385
|
-
this.emit('
|
|
3380
|
+
this.logger('error', `增加指定值失败 [${finalKey}]:`, err);
|
|
3381
|
+
this.emit('incrby:error', {
|
|
3386
3382
|
key: finalKey,
|
|
3387
3383
|
increment: finalIncrement,
|
|
3388
3384
|
seconds: finalSeconds,
|
|
@@ -3393,8 +3389,8 @@ Redis.prototype.incrby = async function(key, increment, seconds = 0) {
|
|
|
3393
3389
|
this._recycleConnection(connection);
|
|
3394
3390
|
}
|
|
3395
3391
|
} catch (err) {
|
|
3396
|
-
|
|
3397
|
-
this.emit('
|
|
3392
|
+
this.logger('error', `增加指定值失败 [${key}]:`, err);
|
|
3393
|
+
this.emit('incrby:error', {
|
|
3398
3394
|
key,
|
|
3399
3395
|
increment,
|
|
3400
3396
|
seconds,
|
|
@@ -3411,29 +3407,27 @@ Redis.prototype.incrby = async function(key, increment, seconds = 0) {
|
|
|
3411
3407
|
* @param {Number} [seconds=0] 过期时间(秒)
|
|
3412
3408
|
* @return {Promise<Number>} 减少后的值
|
|
3413
3409
|
*/
|
|
3414
|
-
Redis.prototype.decrby = async function(key, decrement, seconds = 0) {
|
|
3410
|
+
Redis.prototype.decrby = async function (key, decrement, seconds = 0) {
|
|
3415
3411
|
try {
|
|
3416
3412
|
// 参数验证
|
|
3417
3413
|
if (!key || typeof key !== 'string') {
|
|
3418
|
-
|
|
3419
|
-
return null;
|
|
3414
|
+
throw new TypeError('键必须是非空字符串');
|
|
3420
3415
|
}
|
|
3421
3416
|
if (typeof decrement !== 'number' || isNaN(decrement) || !Number.isInteger(decrement)) {
|
|
3422
|
-
|
|
3423
|
-
return null;
|
|
3417
|
+
throw new TypeError('减量必须是有效整数');
|
|
3424
3418
|
}
|
|
3425
3419
|
|
|
3426
3420
|
// 触发前置事件
|
|
3427
|
-
const
|
|
3421
|
+
const ctx = {
|
|
3428
3422
|
key,
|
|
3429
3423
|
decrement,
|
|
3430
3424
|
seconds,
|
|
3431
3425
|
cancel: false
|
|
3432
3426
|
};
|
|
3433
|
-
this.emit('
|
|
3427
|
+
this.emit('decrby:before', ctx);
|
|
3434
3428
|
|
|
3435
|
-
if (
|
|
3436
|
-
|
|
3429
|
+
if (ctx.cancel) {
|
|
3430
|
+
this.logger('debug', `decrby操作被事件处理器取消 [${key}]`);
|
|
3437
3431
|
return null;
|
|
3438
3432
|
}
|
|
3439
3433
|
|
|
@@ -3441,11 +3435,11 @@ Redis.prototype.decrby = async function(key, decrement, seconds = 0) {
|
|
|
3441
3435
|
key: finalKey,
|
|
3442
3436
|
decrement: finalDecrement,
|
|
3443
3437
|
seconds: finalSeconds
|
|
3444
|
-
} =
|
|
3438
|
+
} = ctx;
|
|
3445
3439
|
|
|
3446
3440
|
const connection = await this._getConnection();
|
|
3447
3441
|
try {
|
|
3448
|
-
const prefixedKey = this.
|
|
3442
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
3449
3443
|
// 使用正确的Redis客户端Promise API
|
|
3450
3444
|
const result = await connection.decrBy(prefixedKey, finalDecrement);
|
|
3451
3445
|
|
|
@@ -3458,7 +3452,7 @@ Redis.prototype.decrby = async function(key, decrement, seconds = 0) {
|
|
|
3458
3452
|
}
|
|
3459
3453
|
}
|
|
3460
3454
|
|
|
3461
|
-
this.emit('
|
|
3455
|
+
this.emit('decrby:after', {
|
|
3462
3456
|
key: finalKey,
|
|
3463
3457
|
decrement: finalDecrement,
|
|
3464
3458
|
seconds: finalSeconds,
|
|
@@ -3466,8 +3460,8 @@ Redis.prototype.decrby = async function(key, decrement, seconds = 0) {
|
|
|
3466
3460
|
});
|
|
3467
3461
|
return result;
|
|
3468
3462
|
} catch (err) {
|
|
3469
|
-
|
|
3470
|
-
this.emit('
|
|
3463
|
+
this.logger('error', `减少指定值失败 [${finalKey}]:`, err);
|
|
3464
|
+
this.emit('decrby:error', {
|
|
3471
3465
|
key: finalKey,
|
|
3472
3466
|
decrement: finalDecrement,
|
|
3473
3467
|
seconds: finalSeconds,
|
|
@@ -3478,8 +3472,8 @@ Redis.prototype.decrby = async function(key, decrement, seconds = 0) {
|
|
|
3478
3472
|
this._recycleConnection(connection);
|
|
3479
3473
|
}
|
|
3480
3474
|
} catch (err) {
|
|
3481
|
-
|
|
3482
|
-
this.emit('
|
|
3475
|
+
this.logger('error', `减少指定值失败 [${key}]:`, err);
|
|
3476
|
+
this.emit('decrby:error', {
|
|
3483
3477
|
key,
|
|
3484
3478
|
decrement,
|
|
3485
3479
|
seconds,
|
|
@@ -3497,33 +3491,33 @@ Redis.prototype.decrby = async function(key, decrement, seconds = 0) {
|
|
|
3497
3491
|
* @param {String|Array} members 成员或成员数组
|
|
3498
3492
|
* @return {Promise<Number>} 添加的成员数量
|
|
3499
3493
|
*/
|
|
3500
|
-
Redis.prototype.sadd = async function(key, members) {
|
|
3494
|
+
Redis.prototype.sadd = async function (key, members) {
|
|
3501
3495
|
try {
|
|
3502
3496
|
// 触发前置事件
|
|
3503
|
-
const
|
|
3497
|
+
const ctx = {
|
|
3504
3498
|
key,
|
|
3505
3499
|
members: Array.isArray(members) ? members : [members],
|
|
3506
3500
|
cancel: false
|
|
3507
3501
|
};
|
|
3508
|
-
this.emit('
|
|
3502
|
+
this.emit('sadd:before', ctx);
|
|
3509
3503
|
|
|
3510
|
-
if (
|
|
3511
|
-
|
|
3504
|
+
if (ctx.cancel) {
|
|
3505
|
+
this.logger('debug', `sadd操作被事件处理器取消 [${key}]`);
|
|
3512
3506
|
return 0;
|
|
3513
3507
|
}
|
|
3514
3508
|
|
|
3515
3509
|
const {
|
|
3516
3510
|
key: finalKey,
|
|
3517
3511
|
members: finalMembers
|
|
3518
|
-
} =
|
|
3512
|
+
} = ctx;
|
|
3519
3513
|
|
|
3520
3514
|
const connection = await this._getConnection();
|
|
3521
3515
|
try {
|
|
3522
|
-
const prefixedKey = this.
|
|
3516
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
3523
3517
|
const result = await connection.sAdd(prefixedKey, finalMembers);
|
|
3524
3518
|
|
|
3525
3519
|
// 触发后置事件
|
|
3526
|
-
this.emit('
|
|
3520
|
+
this.emit('sadd:after', {
|
|
3527
3521
|
key: finalKey,
|
|
3528
3522
|
members: finalMembers,
|
|
3529
3523
|
result
|
|
@@ -3533,8 +3527,8 @@ Redis.prototype.sadd = async function(key, members) {
|
|
|
3533
3527
|
this._recycleConnection(connection);
|
|
3534
3528
|
}
|
|
3535
3529
|
} catch (err) {
|
|
3536
|
-
|
|
3537
|
-
this.emit('
|
|
3530
|
+
this.logger('error', `添加集合成员失败 [${key}]:`, err);
|
|
3531
|
+
this.emit('sadd:error', {
|
|
3538
3532
|
key,
|
|
3539
3533
|
members,
|
|
3540
3534
|
error: err
|
|
@@ -3549,33 +3543,33 @@ Redis.prototype.sadd = async function(key, members) {
|
|
|
3549
3543
|
* @param {String|Array} members 成员或成员数组
|
|
3550
3544
|
* @return {Promise<Number>} 移除的成员数量
|
|
3551
3545
|
*/
|
|
3552
|
-
Redis.prototype.srem = async function(key, members) {
|
|
3546
|
+
Redis.prototype.srem = async function (key, members) {
|
|
3553
3547
|
try {
|
|
3554
3548
|
// 触发前置事件
|
|
3555
|
-
const
|
|
3549
|
+
const ctx = {
|
|
3556
3550
|
key,
|
|
3557
3551
|
members: Array.isArray(members) ? members : [members],
|
|
3558
3552
|
cancel: false
|
|
3559
3553
|
};
|
|
3560
|
-
this.emit('
|
|
3554
|
+
this.emit('srem:before', ctx);
|
|
3561
3555
|
|
|
3562
|
-
if (
|
|
3563
|
-
|
|
3556
|
+
if (ctx.cancel) {
|
|
3557
|
+
this.logger('debug', `srem操作被事件处理器取消 [${key}]`);
|
|
3564
3558
|
return 0;
|
|
3565
3559
|
}
|
|
3566
3560
|
|
|
3567
3561
|
const {
|
|
3568
3562
|
key: finalKey,
|
|
3569
3563
|
members: finalMembers
|
|
3570
|
-
} =
|
|
3564
|
+
} = ctx;
|
|
3571
3565
|
|
|
3572
3566
|
const connection = await this._getConnection();
|
|
3573
3567
|
try {
|
|
3574
|
-
const prefixedKey = this.
|
|
3568
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
3575
3569
|
const result = await connection.sRem(prefixedKey, finalMembers);
|
|
3576
3570
|
|
|
3577
3571
|
// 触发后置事件
|
|
3578
|
-
this.emit('
|
|
3572
|
+
this.emit('srem:after', {
|
|
3579
3573
|
key: finalKey,
|
|
3580
3574
|
members: finalMembers,
|
|
3581
3575
|
result
|
|
@@ -3585,8 +3579,8 @@ Redis.prototype.srem = async function(key, members) {
|
|
|
3585
3579
|
this._recycleConnection(connection);
|
|
3586
3580
|
}
|
|
3587
3581
|
} catch (err) {
|
|
3588
|
-
|
|
3589
|
-
this.emit('
|
|
3582
|
+
this.logger('error', `移除集合成员失败 [${key}]:`, err);
|
|
3583
|
+
this.emit('srem:error', {
|
|
3590
3584
|
key,
|
|
3591
3585
|
members,
|
|
3592
3586
|
error: err
|
|
@@ -3601,29 +3595,27 @@ Redis.prototype.srem = async function(key, members) {
|
|
|
3601
3595
|
* @param {String} member 成员
|
|
3602
3596
|
* @return {Promise<Boolean>} 是否存在
|
|
3603
3597
|
*/
|
|
3604
|
-
Redis.prototype.sismember = async function(key, member) {
|
|
3598
|
+
Redis.prototype.sismember = async function (key, member) {
|
|
3605
3599
|
try {
|
|
3606
3600
|
// 参数验证
|
|
3607
3601
|
if (!key || typeof key !== 'string') {
|
|
3608
|
-
|
|
3609
|
-
return false;
|
|
3602
|
+
throw new TypeError('key必须是非空字符串');
|
|
3610
3603
|
}
|
|
3611
3604
|
if (member === undefined || member === null) {
|
|
3612
|
-
|
|
3613
|
-
return false;
|
|
3605
|
+
throw new TypeError('member不能为undefined或null');
|
|
3614
3606
|
}
|
|
3615
3607
|
|
|
3616
|
-
this.emit('
|
|
3608
|
+
this.emit('sismember:before', {
|
|
3617
3609
|
key,
|
|
3618
3610
|
member
|
|
3619
3611
|
});
|
|
3620
3612
|
const connection = await this._getConnection();
|
|
3621
3613
|
try {
|
|
3622
|
-
const prefixedKey = this.
|
|
3614
|
+
const prefixedKey = this._addPrefix(key);
|
|
3623
3615
|
// 将成员转换为字符串,与其他模块行为一致
|
|
3624
3616
|
const memberStr = String(member);
|
|
3625
3617
|
const result = await connection.sIsMember(prefixedKey, memberStr);
|
|
3626
|
-
this.emit('
|
|
3618
|
+
this.emit('sismember:after', {
|
|
3627
3619
|
key,
|
|
3628
3620
|
member,
|
|
3629
3621
|
result
|
|
@@ -3633,12 +3625,12 @@ Redis.prototype.sismember = async function(key, member) {
|
|
|
3633
3625
|
this._recycleConnection(connection);
|
|
3634
3626
|
}
|
|
3635
3627
|
} catch (err) {
|
|
3636
|
-
this.emit('
|
|
3628
|
+
this.emit('sismember:error', {
|
|
3637
3629
|
key,
|
|
3638
3630
|
member,
|
|
3639
3631
|
error: err
|
|
3640
3632
|
});
|
|
3641
|
-
|
|
3633
|
+
this.logger('error', `检查集合成员失败 [${key}:${member}]:`, err);
|
|
3642
3634
|
return false;
|
|
3643
3635
|
}
|
|
3644
3636
|
};
|
|
@@ -3648,13 +3640,13 @@ Redis.prototype.sismember = async function(key, member) {
|
|
|
3648
3640
|
* @param {String} key 键
|
|
3649
3641
|
* @return {Promise<Array>} 成员数组
|
|
3650
3642
|
*/
|
|
3651
|
-
Redis.prototype.smembers = async function(key) {
|
|
3643
|
+
Redis.prototype.smembers = async function (key) {
|
|
3652
3644
|
try {
|
|
3653
3645
|
const connection = await this._getConnection();
|
|
3654
3646
|
try {
|
|
3655
|
-
const prefixedKey = this.
|
|
3647
|
+
const prefixedKey = this._addPrefix(key);
|
|
3656
3648
|
const result = await connection.sMembers(prefixedKey);
|
|
3657
|
-
this.emit('
|
|
3649
|
+
this.emit('smembers:after', {
|
|
3658
3650
|
key,
|
|
3659
3651
|
result
|
|
3660
3652
|
});
|
|
@@ -3663,8 +3655,8 @@ Redis.prototype.smembers = async function(key) {
|
|
|
3663
3655
|
this._recycleConnection(connection);
|
|
3664
3656
|
}
|
|
3665
3657
|
} catch (err) {
|
|
3666
|
-
|
|
3667
|
-
this.emit('
|
|
3658
|
+
this.logger('error', `获取集合所有成员失败 [${key}]:`, err);
|
|
3659
|
+
this.emit('smembers:error', {
|
|
3668
3660
|
key,
|
|
3669
3661
|
error: err
|
|
3670
3662
|
});
|
|
@@ -3677,18 +3669,18 @@ Redis.prototype.smembers = async function(key) {
|
|
|
3677
3669
|
* @param {String} key 键
|
|
3678
3670
|
* @return {Promise<Number>} 成员数量
|
|
3679
3671
|
*/
|
|
3680
|
-
Redis.prototype.scard = async function(key) {
|
|
3672
|
+
Redis.prototype.scard = async function (key) {
|
|
3681
3673
|
try {
|
|
3682
3674
|
const connection = await this._getConnection();
|
|
3683
3675
|
try {
|
|
3684
|
-
const prefixedKey = this.
|
|
3676
|
+
const prefixedKey = this._addPrefix(key);
|
|
3685
3677
|
const result = await connection.sCard(prefixedKey);
|
|
3686
3678
|
return result;
|
|
3687
3679
|
} finally {
|
|
3688
3680
|
this._recycleConnection(connection);
|
|
3689
3681
|
}
|
|
3690
3682
|
} catch (err) {
|
|
3691
|
-
|
|
3683
|
+
this.logger('error', `获取集合大小失败 [${key}]:`, err);
|
|
3692
3684
|
return 0;
|
|
3693
3685
|
}
|
|
3694
3686
|
};
|
|
@@ -3698,11 +3690,11 @@ Redis.prototype.scard = async function(key) {
|
|
|
3698
3690
|
* @param {Array} keys 键数组
|
|
3699
3691
|
* @return {Promise<Array>} 交集成员数组
|
|
3700
3692
|
*/
|
|
3701
|
-
Redis.prototype.sinter = async function(keys) {
|
|
3693
|
+
Redis.prototype.sinter = async function (keys) {
|
|
3702
3694
|
try {
|
|
3703
3695
|
const connection = await this._getConnection();
|
|
3704
3696
|
try {
|
|
3705
|
-
const prefixedKeys = keys.map(key => this.
|
|
3697
|
+
const prefixedKeys = keys.map(key => this._addPrefix(key));
|
|
3706
3698
|
// 使用Redis v4正确的方法
|
|
3707
3699
|
const result = await connection.sInter(...prefixedKeys);
|
|
3708
3700
|
return result || [];
|
|
@@ -3710,7 +3702,7 @@ Redis.prototype.sinter = async function(keys) {
|
|
|
3710
3702
|
this._recycleConnection(connection);
|
|
3711
3703
|
}
|
|
3712
3704
|
} catch (err) {
|
|
3713
|
-
|
|
3705
|
+
this.logger('error', `获取集合交集失败:`, err);
|
|
3714
3706
|
return [];
|
|
3715
3707
|
}
|
|
3716
3708
|
};
|
|
@@ -3720,11 +3712,11 @@ Redis.prototype.sinter = async function(keys) {
|
|
|
3720
3712
|
* @param {Array} keys 键数组
|
|
3721
3713
|
* @return {Promise<Array>} 并集成员数组
|
|
3722
3714
|
*/
|
|
3723
|
-
Redis.prototype.sunion = async function(keys) {
|
|
3715
|
+
Redis.prototype.sunion = async function (keys) {
|
|
3724
3716
|
try {
|
|
3725
3717
|
const connection = await this._getConnection();
|
|
3726
3718
|
try {
|
|
3727
|
-
const prefixedKeys = keys.map(key => this.
|
|
3719
|
+
const prefixedKeys = keys.map(key => this._addPrefix(key));
|
|
3728
3720
|
// 使用Redis v4正确的方法
|
|
3729
3721
|
const result = await connection.sUnion(...prefixedKeys);
|
|
3730
3722
|
return result || [];
|
|
@@ -3732,7 +3724,7 @@ Redis.prototype.sunion = async function(keys) {
|
|
|
3732
3724
|
this._recycleConnection(connection);
|
|
3733
3725
|
}
|
|
3734
3726
|
} catch (err) {
|
|
3735
|
-
|
|
3727
|
+
this.logger('error', `获取集合并集失败:`, err);
|
|
3736
3728
|
return [];
|
|
3737
3729
|
}
|
|
3738
3730
|
};
|
|
@@ -3742,11 +3734,11 @@ Redis.prototype.sunion = async function(keys) {
|
|
|
3742
3734
|
* @param {Array} keys 键数组
|
|
3743
3735
|
* @return {Promise<Array>} 差集成员数组
|
|
3744
3736
|
*/
|
|
3745
|
-
Redis.prototype.sdiff = async function(keys) {
|
|
3737
|
+
Redis.prototype.sdiff = async function (keys) {
|
|
3746
3738
|
try {
|
|
3747
3739
|
const connection = await this._getConnection();
|
|
3748
3740
|
try {
|
|
3749
|
-
const prefixedKeys = keys.map(key => this.
|
|
3741
|
+
const prefixedKeys = keys.map(key => this._addPrefix(key));
|
|
3750
3742
|
// 使用Redis v4正确的方法
|
|
3751
3743
|
const result = await connection.sDiff(...prefixedKeys);
|
|
3752
3744
|
return result || [];
|
|
@@ -3754,7 +3746,7 @@ Redis.prototype.sdiff = async function(keys) {
|
|
|
3754
3746
|
this._recycleConnection(connection);
|
|
3755
3747
|
}
|
|
3756
3748
|
} catch (err) {
|
|
3757
|
-
|
|
3749
|
+
this.logger('error', `获取集合差集失败:`, err);
|
|
3758
3750
|
return [];
|
|
3759
3751
|
}
|
|
3760
3752
|
};
|
|
@@ -3768,19 +3760,19 @@ Redis.prototype.sdiff = async function(keys) {
|
|
|
3768
3760
|
* @param {String} member 成员
|
|
3769
3761
|
* @return {Promise<Boolean>} 是否成功
|
|
3770
3762
|
*/
|
|
3771
|
-
Redis.prototype.zadd = async function(key, score, member) {
|
|
3763
|
+
Redis.prototype.zadd = async function (key, score, member) {
|
|
3772
3764
|
try {
|
|
3773
3765
|
// 触发前置事件
|
|
3774
|
-
const
|
|
3766
|
+
const ctx = {
|
|
3775
3767
|
key,
|
|
3776
3768
|
score,
|
|
3777
3769
|
member,
|
|
3778
3770
|
cancel: false
|
|
3779
3771
|
};
|
|
3780
|
-
this.emit('
|
|
3772
|
+
this.emit('zadd:before', ctx);
|
|
3781
3773
|
|
|
3782
|
-
if (
|
|
3783
|
-
|
|
3774
|
+
if (ctx.cancel) {
|
|
3775
|
+
this.logger('debug', `zadd操作被事件处理器取消 [${key}]`);
|
|
3784
3776
|
return false;
|
|
3785
3777
|
}
|
|
3786
3778
|
|
|
@@ -3788,18 +3780,18 @@ Redis.prototype.zadd = async function(key, score, member) {
|
|
|
3788
3780
|
key: finalKey,
|
|
3789
3781
|
score: finalScore,
|
|
3790
3782
|
member: finalMember
|
|
3791
|
-
} =
|
|
3783
|
+
} = ctx;
|
|
3792
3784
|
|
|
3793
3785
|
const connection = await this._getConnection();
|
|
3794
3786
|
try {
|
|
3795
|
-
const prefixedKey = this.
|
|
3787
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
3796
3788
|
const result = await connection.zAdd(prefixedKey, {
|
|
3797
3789
|
score: finalScore,
|
|
3798
3790
|
value: finalMember
|
|
3799
3791
|
});
|
|
3800
3792
|
|
|
3801
3793
|
// 触发后置事件
|
|
3802
|
-
this.emit('
|
|
3794
|
+
this.emit('zadd:after', {
|
|
3803
3795
|
key: finalKey,
|
|
3804
3796
|
score: finalScore,
|
|
3805
3797
|
member: finalMember,
|
|
@@ -3810,8 +3802,8 @@ Redis.prototype.zadd = async function(key, score, member) {
|
|
|
3810
3802
|
this._recycleConnection(connection);
|
|
3811
3803
|
}
|
|
3812
3804
|
} catch (err) {
|
|
3813
|
-
|
|
3814
|
-
this.emit('
|
|
3805
|
+
this.logger('error', `添加有序集合成员失败 [${key}]:`, err);
|
|
3806
|
+
this.emit('zadd:error', {
|
|
3815
3807
|
key,
|
|
3816
3808
|
score,
|
|
3817
3809
|
member,
|
|
@@ -3827,41 +3819,41 @@ Redis.prototype.zadd = async function(key, score, member) {
|
|
|
3827
3819
|
* @param {String|Array} members 成员或成员数组
|
|
3828
3820
|
* @return {Promise<Number>} 移除的成员数量
|
|
3829
3821
|
*/
|
|
3830
|
-
Redis.prototype.zrem = async function(key, members) {
|
|
3822
|
+
Redis.prototype.zrem = async function (key, members) {
|
|
3831
3823
|
try {
|
|
3832
3824
|
// 触发前置事件
|
|
3833
|
-
const
|
|
3825
|
+
const ctx = {
|
|
3834
3826
|
key,
|
|
3835
3827
|
members: Array.isArray(members) ? members : [members],
|
|
3836
3828
|
cancel: false
|
|
3837
3829
|
};
|
|
3838
|
-
this.emit('
|
|
3830
|
+
this.emit('zrem:before', ctx);
|
|
3839
3831
|
|
|
3840
|
-
if (
|
|
3841
|
-
|
|
3832
|
+
if (ctx.cancel) {
|
|
3833
|
+
this.logger('debug', `zrem操作被事件处理器取消 [${key}]`);
|
|
3842
3834
|
return 0;
|
|
3843
3835
|
}
|
|
3844
3836
|
|
|
3845
3837
|
const {
|
|
3846
3838
|
key: finalKey,
|
|
3847
3839
|
members: finalMembers
|
|
3848
|
-
} =
|
|
3840
|
+
} = ctx;
|
|
3849
3841
|
|
|
3850
3842
|
const connection = await this._getConnection();
|
|
3851
3843
|
try {
|
|
3852
3844
|
// 使用正确的Redis客户端Promise API
|
|
3853
|
-
const result = await connection.zRem(this.
|
|
3845
|
+
const result = await connection.zRem(this._addPrefix(finalKey), ...finalMembers);
|
|
3854
3846
|
|
|
3855
3847
|
// 触发后置事件
|
|
3856
|
-
this.emit('
|
|
3848
|
+
this.emit('zrem:after', {
|
|
3857
3849
|
key: finalKey,
|
|
3858
3850
|
members: finalMembers,
|
|
3859
3851
|
result
|
|
3860
3852
|
});
|
|
3861
3853
|
return result;
|
|
3862
3854
|
} catch (err) {
|
|
3863
|
-
|
|
3864
|
-
this.emit('
|
|
3855
|
+
this.logger('error', `移除有序集合成员失败 [${finalKey}]:`, err);
|
|
3856
|
+
this.emit('zrem:error', {
|
|
3865
3857
|
key: finalKey,
|
|
3866
3858
|
members: finalMembers,
|
|
3867
3859
|
error: err
|
|
@@ -3871,8 +3863,8 @@ Redis.prototype.zrem = async function(key, members) {
|
|
|
3871
3863
|
this._recycleConnection(connection);
|
|
3872
3864
|
}
|
|
3873
3865
|
} catch (err) {
|
|
3874
|
-
|
|
3875
|
-
this.emit('
|
|
3866
|
+
this.logger('error', `移除有序集合成员失败 [${key}]:`, err);
|
|
3867
|
+
this.emit('zrem:error', {
|
|
3876
3868
|
key,
|
|
3877
3869
|
members,
|
|
3878
3870
|
error: err
|
|
@@ -3887,18 +3879,18 @@ Redis.prototype.zrem = async function(key, members) {
|
|
|
3887
3879
|
* @param {String} member 成员
|
|
3888
3880
|
* @return {Promise<Number|null>} 分数
|
|
3889
3881
|
*/
|
|
3890
|
-
Redis.prototype.zscore = async function(key, member) {
|
|
3882
|
+
Redis.prototype.zscore = async function (key, member) {
|
|
3891
3883
|
try {
|
|
3892
3884
|
const connection = await this._getConnection();
|
|
3893
3885
|
try {
|
|
3894
|
-
const prefixedKey = this.
|
|
3886
|
+
const prefixedKey = this._addPrefix(key);
|
|
3895
3887
|
const result = await connection.zScore(prefixedKey, member);
|
|
3896
3888
|
return result ? parseFloat(result) : null;
|
|
3897
3889
|
} finally {
|
|
3898
3890
|
this._recycleConnection(connection);
|
|
3899
3891
|
}
|
|
3900
3892
|
} catch (err) {
|
|
3901
|
-
|
|
3893
|
+
this.logger('error', `获取有序集合成员分数失败 [${key}:${member}]:`, err);
|
|
3902
3894
|
return null;
|
|
3903
3895
|
}
|
|
3904
3896
|
};
|
|
@@ -3909,18 +3901,18 @@ Redis.prototype.zscore = async function(key, member) {
|
|
|
3909
3901
|
* @param {String} member 成员
|
|
3910
3902
|
* @return {Promise<Number|null>} 排名
|
|
3911
3903
|
*/
|
|
3912
|
-
Redis.prototype.zrank = async function(key, member) {
|
|
3904
|
+
Redis.prototype.zrank = async function (key, member) {
|
|
3913
3905
|
try {
|
|
3914
3906
|
const connection = await this._getConnection();
|
|
3915
3907
|
try {
|
|
3916
|
-
const prefixedKey = this.
|
|
3908
|
+
const prefixedKey = this._addPrefix(key);
|
|
3917
3909
|
const result = await connection.zRank(prefixedKey, member);
|
|
3918
3910
|
return result;
|
|
3919
3911
|
} finally {
|
|
3920
3912
|
this._recycleConnection(connection);
|
|
3921
3913
|
}
|
|
3922
3914
|
} catch (err) {
|
|
3923
|
-
|
|
3915
|
+
this.logger('error', `获取有序集合成员排名失败 [${key}:${member}]:`, err);
|
|
3924
3916
|
return null;
|
|
3925
3917
|
}
|
|
3926
3918
|
};
|
|
@@ -3933,11 +3925,11 @@ Redis.prototype.zrank = async function(key, member) {
|
|
|
3933
3925
|
* @param {Boolean} withScores 是否返回分数
|
|
3934
3926
|
* @return {Promise<Array>} 成员数组
|
|
3935
3927
|
*/
|
|
3936
|
-
Redis.prototype.zrange = async function(key, start, stop, withScores = false) {
|
|
3928
|
+
Redis.prototype.zrange = async function (key, start, stop, withScores = false) {
|
|
3937
3929
|
try {
|
|
3938
3930
|
const connection = await this._getConnection();
|
|
3939
3931
|
try {
|
|
3940
|
-
const prefixedKey = this.
|
|
3932
|
+
const prefixedKey = this._addPrefix(key);
|
|
3941
3933
|
|
|
3942
3934
|
if (withScores) {
|
|
3943
3935
|
// 对于需要分数的情况,使用更可靠的方法
|
|
@@ -3961,13 +3953,13 @@ Redis.prototype.zrange = async function(key, start, stop, withScores = false) {
|
|
|
3961
3953
|
member,
|
|
3962
3954
|
score: 0
|
|
3963
3955
|
});
|
|
3964
|
-
|
|
3956
|
+
this.logger('error', `获取成员 ${member} 分数失败:`, scoreErr);
|
|
3965
3957
|
}
|
|
3966
3958
|
}
|
|
3967
3959
|
|
|
3968
3960
|
return results;
|
|
3969
3961
|
} catch (err) {
|
|
3970
|
-
|
|
3962
|
+
this.logger('error', `使用备用方法获取有序集合范围失败 [${prefixedKey}]:`, err);
|
|
3971
3963
|
// 回退到简单列表
|
|
3972
3964
|
return [];
|
|
3973
3965
|
}
|
|
@@ -3980,7 +3972,7 @@ Redis.prototype.zrange = async function(key, start, stop, withScores = false) {
|
|
|
3980
3972
|
this._recycleConnection(connection);
|
|
3981
3973
|
}
|
|
3982
3974
|
} catch (err) {
|
|
3983
|
-
|
|
3975
|
+
this.logger('error', `获取有序集合范围成员失败 [${key}]:`, err);
|
|
3984
3976
|
return [];
|
|
3985
3977
|
}
|
|
3986
3978
|
};
|
|
@@ -3990,21 +3982,21 @@ Redis.prototype.zrange = async function(key, start, stop, withScores = false) {
|
|
|
3990
3982
|
* @param {String} key 键
|
|
3991
3983
|
* @return {Promise<Number>} 成员数量
|
|
3992
3984
|
*/
|
|
3993
|
-
Redis.prototype.zcard = async function(key) {
|
|
3985
|
+
Redis.prototype.zcard = async function (key) {
|
|
3994
3986
|
try {
|
|
3995
3987
|
const connection = await this._getConnection();
|
|
3996
3988
|
try {
|
|
3997
3989
|
// 使用正确的Redis客户端Promise API
|
|
3998
|
-
const result = await connection.zCard(this.
|
|
3990
|
+
const result = await connection.zCard(this._addPrefix(key));
|
|
3999
3991
|
return result || 0;
|
|
4000
3992
|
} catch (err) {
|
|
4001
|
-
|
|
3993
|
+
this.logger('error', `获取有序集合成员数量失败 [${key}]:`, err);
|
|
4002
3994
|
return 0;
|
|
4003
3995
|
} finally {
|
|
4004
3996
|
this._recycleConnection(connection);
|
|
4005
3997
|
}
|
|
4006
3998
|
} catch (err) {
|
|
4007
|
-
|
|
3999
|
+
this.logger('error', `获取有序集合成员数量失败 [${key}]:`, err);
|
|
4008
4000
|
return 0;
|
|
4009
4001
|
}
|
|
4010
4002
|
};
|
|
@@ -4017,34 +4009,31 @@ Redis.prototype.zcard = async function(key) {
|
|
|
4017
4009
|
* @param {Number} [seconds=0] 过期时间(秒)
|
|
4018
4010
|
* @return {Promise<Number>} 增加后的分数
|
|
4019
4011
|
*/
|
|
4020
|
-
Redis.prototype.zincrby = async function(key, increment, member, seconds = 0) {
|
|
4012
|
+
Redis.prototype.zincrby = async function (key, increment, member, seconds = 0) {
|
|
4021
4013
|
try {
|
|
4022
4014
|
// 参数验证
|
|
4023
4015
|
if (!key || typeof key !== 'string') {
|
|
4024
|
-
|
|
4025
|
-
return null;
|
|
4016
|
+
throw new TypeError('键必须是非空字符串');
|
|
4026
4017
|
}
|
|
4027
4018
|
if (typeof increment !== 'number' || isNaN(increment)) {
|
|
4028
|
-
|
|
4029
|
-
return null;
|
|
4019
|
+
throw new TypeError('增量必须是有效数字');
|
|
4030
4020
|
}
|
|
4031
4021
|
if (!member || typeof member !== 'string') {
|
|
4032
|
-
|
|
4033
|
-
return null;
|
|
4022
|
+
throw new TypeError('成员必须是非空字符串');
|
|
4034
4023
|
}
|
|
4035
4024
|
|
|
4036
4025
|
// 触发前置事件
|
|
4037
|
-
const
|
|
4026
|
+
const ctx = {
|
|
4038
4027
|
key,
|
|
4039
4028
|
increment,
|
|
4040
4029
|
member,
|
|
4041
4030
|
seconds,
|
|
4042
4031
|
cancel: false
|
|
4043
4032
|
};
|
|
4044
|
-
this.emit('
|
|
4033
|
+
this.emit('zincrby:before', ctx);
|
|
4045
4034
|
|
|
4046
|
-
if (
|
|
4047
|
-
|
|
4035
|
+
if (ctx.cancel) {
|
|
4036
|
+
this.logger('debug', `zincrby操作被事件处理器取消 [${key}]`);
|
|
4048
4037
|
return null;
|
|
4049
4038
|
}
|
|
4050
4039
|
|
|
@@ -4053,11 +4042,11 @@ Redis.prototype.zincrby = async function(key, increment, member, seconds = 0) {
|
|
|
4053
4042
|
increment: finalIncrement,
|
|
4054
4043
|
member: finalMember,
|
|
4055
4044
|
seconds: finalSeconds
|
|
4056
|
-
} =
|
|
4045
|
+
} = ctx;
|
|
4057
4046
|
|
|
4058
4047
|
const connection = await this._getConnection();
|
|
4059
4048
|
try {
|
|
4060
|
-
const prefixedKey = this.
|
|
4049
|
+
const prefixedKey = this._addPrefix(finalKey);
|
|
4061
4050
|
// 使用正确的Redis客户端Promise API
|
|
4062
4051
|
const result = await connection.zIncrBy(prefixedKey, finalIncrement, finalMember);
|
|
4063
4052
|
|
|
@@ -4071,7 +4060,7 @@ Redis.prototype.zincrby = async function(key, increment, member, seconds = 0) {
|
|
|
4071
4060
|
}
|
|
4072
4061
|
|
|
4073
4062
|
// 触发后置事件
|
|
4074
|
-
this.emit('
|
|
4063
|
+
this.emit('zincrby:after', {
|
|
4075
4064
|
key: finalKey,
|
|
4076
4065
|
increment: finalIncrement,
|
|
4077
4066
|
member: finalMember,
|
|
@@ -4080,8 +4069,8 @@ Redis.prototype.zincrby = async function(key, increment, member, seconds = 0) {
|
|
|
4080
4069
|
});
|
|
4081
4070
|
return parseFloat(result);
|
|
4082
4071
|
} catch (err) {
|
|
4083
|
-
|
|
4084
|
-
this.emit('
|
|
4072
|
+
this.logger('error', `增加有序集合成员分数失败 [${finalKey}]:`, err);
|
|
4073
|
+
this.emit('zincrby:error', {
|
|
4085
4074
|
key: finalKey,
|
|
4086
4075
|
increment: finalIncrement,
|
|
4087
4076
|
member: finalMember,
|
|
@@ -4093,8 +4082,8 @@ Redis.prototype.zincrby = async function(key, increment, member, seconds = 0) {
|
|
|
4093
4082
|
this._recycleConnection(connection);
|
|
4094
4083
|
}
|
|
4095
4084
|
} catch (err) {
|
|
4096
|
-
|
|
4097
|
-
this.emit('
|
|
4085
|
+
this.logger('error', `增加有序集合成员分数失败 [${key}]:`, err);
|
|
4086
|
+
this.emit('zincrby:error', {
|
|
4098
4087
|
key,
|
|
4099
4088
|
increment,
|
|
4100
4089
|
member,
|
|
@@ -4106,7 +4095,7 @@ Redis.prototype.zincrby = async function(key, increment, member, seconds = 0) {
|
|
|
4106
4095
|
};
|
|
4107
4096
|
|
|
4108
4097
|
// 创建真实Redis连接的方法
|
|
4109
|
-
Redis.prototype._createConnection = function() {
|
|
4098
|
+
Redis.prototype._createConnection = function () {
|
|
4110
4099
|
return new Promise((resolve, reject) => {
|
|
4111
4100
|
try {
|
|
4112
4101
|
const cg = this.config;
|
|
@@ -4127,19 +4116,19 @@ Redis.prototype._createConnection = function() {
|
|
|
4127
4116
|
|
|
4128
4117
|
// 监听错误事件
|
|
4129
4118
|
connection.on('error', (err) => {
|
|
4130
|
-
|
|
4119
|
+
this.logger('error', `连接 ${connection.id} 错误:`, err);
|
|
4131
4120
|
});
|
|
4132
4121
|
|
|
4133
4122
|
// 连接Redis
|
|
4134
4123
|
connection.connect().then(() => {
|
|
4135
|
-
//
|
|
4124
|
+
// this.logger('debug','新连接已创建并连接:', connection.id);
|
|
4136
4125
|
resolve(connection);
|
|
4137
4126
|
}).catch(err => {
|
|
4138
|
-
|
|
4127
|
+
this.logger('error', '创建连接失败:', err);
|
|
4139
4128
|
reject(err);
|
|
4140
4129
|
});
|
|
4141
4130
|
} catch (error) {
|
|
4142
|
-
|
|
4131
|
+
this.logger('error', '创建连接时发生异常:', error);
|
|
4143
4132
|
reject(error);
|
|
4144
4133
|
}
|
|
4145
4134
|
});
|