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