mm_redis 1.9.5 → 1.9.7
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 +26 -14
- package/compatibility_table.md +89 -50
- package/index.js +176 -196
- package/package.json +1 -1
- package/test.js +223 -43
- package/verify_compatibility.js +175 -0
package/README.md
CHANGED
|
@@ -7,8 +7,8 @@ mm_redis是一个高效的Redis客户端封装库,提供了全面的Redis功
|
|
|
7
7
|
|
|
8
8
|
## 版本信息
|
|
9
9
|
|
|
10
|
-
- **当前版本**: 1.9.
|
|
11
|
-
- **更新日期**: 2024-12-
|
|
10
|
+
- **当前版本**: 1.9.6
|
|
11
|
+
- **更新日期**: 2024-12-21
|
|
12
12
|
- **作者**: 邱文武
|
|
13
13
|
- **NPM**: [https://www.npmjs.com/package/mm_redis](https://www.npmjs.com/package/mm_redis)
|
|
14
14
|
|
|
@@ -74,6 +74,15 @@ redis.setConfig('./config.json');
|
|
|
74
74
|
```
|
|
75
75
|
## 变更日志
|
|
76
76
|
|
|
77
|
+
### v1.9.5 (2024-12-21)
|
|
78
|
+
- 修复hmset和hgetall方法的兼容性问题,确保与Redis客户端v5兼容
|
|
79
|
+
- 移除已废弃的hexists、hkeys和hvals方法,优化API设计
|
|
80
|
+
- 优化mget和mset方法的实现,确保与Redis v5 API完全兼容
|
|
81
|
+
- 更新测试脚本,移除对已废弃方法的调用
|
|
82
|
+
- 更新兼容性表格,确保文档与实际API一致
|
|
83
|
+
- 修复原生Redis API调用中的错误,提升代码稳定性
|
|
84
|
+
- 优化连接池管理,修复潜在的内存泄漏问题
|
|
85
|
+
|
|
77
86
|
### v1.9.4 (2024-12-20)
|
|
78
87
|
- 优化了配置引入方式,支持对象配置和文件路径配置两种方式
|
|
79
88
|
- 改进了setConfig方法的实现,使用Object.assign替代原来的合并方式
|
|
@@ -149,15 +158,6 @@ const name = await redis.hget('user:profile:1', 'name');
|
|
|
149
158
|
const profile = await redis.hgetall('user:profile:1');
|
|
150
159
|
$.log.debug('[Redis] 用户资料:', profile);
|
|
151
160
|
|
|
152
|
-
// 获取哈希的所有字段名
|
|
153
|
-
const fields = await redis.hkeys('user:profile:1');
|
|
154
|
-
|
|
155
|
-
// 获取哈希的所有字段值
|
|
156
|
-
const values = await redis.hvals('user:profile:1');
|
|
157
|
-
|
|
158
|
-
// 判断哈希字段是否存在
|
|
159
|
-
const hasEmail = await redis.hexists('user:profile:1', 'email');
|
|
160
|
-
|
|
161
161
|
// 获取哈希字段数量
|
|
162
162
|
const fieldCount = await redis.hlen('user:profile:1');
|
|
163
163
|
|
|
@@ -335,10 +335,7 @@ redis.on('set_error', (data) => {
|
|
|
335
335
|
- `hmset(key, obj)`: 批量设置哈希字段
|
|
336
336
|
- `hget(key, field)`: 获取哈希字段值
|
|
337
337
|
- `hgetall(key)`: 获取哈希的所有字段和值
|
|
338
|
-
- `hkeys(key)`: 获取哈希的所有字段名
|
|
339
|
-
- `hvals(key)`: 获取哈希的所有字段值
|
|
340
338
|
- `hdel(key, fields)`: 删除哈希字段
|
|
341
|
-
- `hexists(key, field)`: 判断哈希字段是否存在
|
|
342
339
|
- `hlen(key)`: 获取哈希字段数量
|
|
343
340
|
|
|
344
341
|
### 批量操作
|
|
@@ -415,6 +412,21 @@ redis.on('set_error', (data) => {
|
|
|
415
412
|
|
|
416
413
|
## 版本更新
|
|
417
414
|
|
|
415
|
+
### 1.9.5 (2024-12-21)
|
|
416
|
+
- 修复hmset和hgetall方法的兼容性问题,确保与Redis客户端v5兼容
|
|
417
|
+
- 移除已废弃的hexists、hkeys和hvals方法,优化API设计
|
|
418
|
+
- 优化mget和mset方法的实现,确保与Redis v5 API完全兼容
|
|
419
|
+
- 更新测试脚本,移除对已废弃方法的调用
|
|
420
|
+
- 更新兼容性表格,确保文档与实际API一致
|
|
421
|
+
- 修复原生Redis API调用中的错误,提升代码稳定性
|
|
422
|
+
- 优化连接池管理,修复潜在的内存泄漏问题
|
|
423
|
+
|
|
424
|
+
### 1.9.4 (2024-12-20)
|
|
425
|
+
- 优化了配置引入方式,支持对象配置和文件路径配置两种方式
|
|
426
|
+
- 改进了setConfig方法的实现,使用Object.assign替代原来的合并方式
|
|
427
|
+
- 修复了连接池相关的警告信息
|
|
428
|
+
- 增强了错误处理机制
|
|
429
|
+
|
|
418
430
|
### 1.9.0 (2024-11-20)
|
|
419
431
|
- 适配Redis v4 API,确保与最新版Redis客户端兼容
|
|
420
432
|
- 重写pipeline方法,使用Redis v4推荐的实现方式
|
package/compatibility_table.md
CHANGED
|
@@ -1,64 +1,103 @@
|
|
|
1
|
-
|
|
2
|
-
# 三种缓存方式方法兼容性对比表格
|
|
1
|
+
# 四种缓存方式方法兼容性对比表格
|
|
3
2
|
|
|
4
3
|
## 核心缓存方法
|
|
5
4
|
|
|
6
|
-
| 方法名 | Redis | MongoDB | CacheBase | 状态说明 |
|
|
7
|
-
|
|
8
|
-
| set | ✅ | ✅ |
|
|
9
|
-
| get | ✅ | ✅ | ✅ |
|
|
10
|
-
| del | ✅ | ✅ |
|
|
11
|
-
| has |
|
|
12
|
-
| clear |
|
|
13
|
-
| keys | ✅ | ✅ | ✅ |
|
|
14
|
-
| ttl |
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
5
|
+
| 方法名 | Redis | MongoDB | CacheBase | Memory | 状态说明 |
|
|
6
|
+
|-------|-------|---------|-----------|--------|----------|
|
|
7
|
+
| set | ✅ | ✅ | ⚠️ | ⚠️ | Redis和MongoDB正常工作,CacheBase和Memory行为不一致 |
|
|
8
|
+
| get | ✅ | ✅ | ✅ | ✅ | 所有方式均正常工作 |
|
|
9
|
+
| del | ✅ | ✅ | ⚠️ | ⚠️ | Redis和MongoDB正常工作,CacheBase和Memory行为不一致 |
|
|
10
|
+
| has | ✅ | ✅ | ✅ | ✅ | 所有方式都支持 |
|
|
11
|
+
| clear | ✅ | ✅ | ⚠️ | ⚠️ | Redis和MongoDB正常工作,CacheBase和Memory行为不一致 |
|
|
12
|
+
| keys | ✅ | ✅ | ✅ | ✅ | 所有方式都支持 |
|
|
13
|
+
| ttl | ⚠️ | ⚠️ | ⚠️ | ⚠️ | 所有方式行为不一致,需要依赖底层实现 |
|
|
14
|
+
| add | ✅ | ✅ | ✅ | ✅ | 所有方式均正常工作 |
|
|
15
|
+
| addInt | ✅ | ❌ | ❌ | ❌ | 仅Redis支持 |
|
|
16
|
+
| addStr | ✅ | ❌ | ❌ | ❌ | 仅Redis支持 |
|
|
17
|
+
| sort | ✅ | ✅ | ❌ | ❌ | Redis和MongoDB支持,其他方式不支持 |
|
|
18
|
+
| exists | ✅ | ✅ | ⚠️ | ⚠️ | Redis和MongoDB正常工作,CacheBase和Memory行为不一致 |
|
|
19
|
+
| incrby | ✅ | ❌ | ❌ | ❌ | 仅Redis支持 |
|
|
20
|
+
| decrby | ✅ | ❌ | ❌ | ❌ | 仅Redis支持 |
|
|
21
|
+
| addFloat | ✅ | ❌ | ❌ | ❌ | 仅Redis支持 |
|
|
20
22
|
|
|
21
23
|
## Redis兼容方法 - 哈希表操作
|
|
22
24
|
|
|
23
|
-
| 方法名 | Redis | MongoDB | CacheBase | 状态说明 |
|
|
24
|
-
|
|
25
|
-
| hset | ✅ | ✅ |
|
|
26
|
-
| hget | ✅ | ✅ | ✅ |
|
|
27
|
-
| hgetall | ✅ | ✅ | ✅ |
|
|
28
|
-
| hdel | ✅ | ✅ | ✅ |
|
|
29
|
-
|
|
|
30
|
-
|
|
|
31
|
-
|
|
|
25
|
+
| 方法名 | Redis | MongoDB | CacheBase | Memory | 状态说明 |
|
|
26
|
+
|-------|-------|---------|-----------|--------|----------|
|
|
27
|
+
| hset | ✅ | ✅ | ⚠️ | ⚠️ | Redis和MongoDB正常工作,CacheBase和Memory行为不一致 |
|
|
28
|
+
| hget | ✅ | ✅ | ✅ | ✅ | 所有方式均正常工作 |
|
|
29
|
+
| hgetall | ✅ | ✅ | ✅ | ✅ | 所有方式都支持 |
|
|
30
|
+
| hdel | ✅ | ✅ | ✅ | ✅ | 所有方式都支持 |
|
|
31
|
+
| hmset | ✅ | ✅ | ❌ | ❌ | Redis和MongoDB支持,其他方式不支持 |
|
|
32
|
+
| hmget | ❌ | ✅ | ❌ | ❌ | 仅MongoDB支持 |
|
|
33
|
+
| hlen | ✅ | ✅ | ❌ | ❌ | Redis和MongoDB支持,其他方式不支持 |
|
|
34
|
+
|
|
35
|
+
## Redis兼容方法 - 其他常用命令
|
|
36
|
+
|
|
37
|
+
| 方法名 | Redis | MongoDB | CacheBase | Memory | 状态说明 |
|
|
38
|
+
|-------|-------|---------|-----------|--------|----------|
|
|
39
|
+
| expire | ✅ | ✅ | ✅ | ✅ | 所有方式都支持 |
|
|
40
|
+
| incr | ✅ | ✅ | ✅ | ✅ | 所有方式都支持 |
|
|
41
|
+
| decr | ✅ | ❌ | ❌ | ❌ | 仅Redis支持 |
|
|
42
|
+
| mget | ✅ | ✅ | ❌ | ❌ | Redis和MongoDB支持,其他方式不支持 |
|
|
43
|
+
| mset | ✅ | ✅ | ❌ | ❌ | Redis和MongoDB支持,其他方式不支持 |
|
|
44
|
+
| pexpire | ❌ | ❌ | ❌ | ❌ | 所有方式都不支持 |
|
|
45
|
+
| persist | ✅ | ❌ | ✅ | ✅ | Redis、CacheBase和Memory支持,MongoDB不支持 |
|
|
46
|
+
| strlen | ✅ | ❌ | ✅ | ❌ | Redis和CacheBase支持,其他方式不支持 |
|
|
47
|
+
| type | ❌ | ❌ | ❌ | ❌ | 所有方式都不支持 |
|
|
48
|
+
| rename | ❌ | ❌ | ❌ | ❌ | 所有方式都不支持 |
|
|
32
49
|
|
|
33
50
|
## Redis兼容方法 - 集合操作
|
|
34
51
|
|
|
35
|
-
| 方法名 | Redis | MongoDB | CacheBase | 状态说明 |
|
|
36
|
-
|
|
37
|
-
| sadd | ✅ | ❌ | ❌ | Redis
|
|
38
|
-
| srem | ✅ | ❌ | ❌ | Redis
|
|
39
|
-
| sismember | ✅ | ❌ | ❌ | Redis
|
|
40
|
-
| smembers | ✅ | ❌ | ❌ | Redis
|
|
41
|
-
| scard | ✅ | ❌ | ❌ | Redis原生支持,CacheBase未实现 |
|
|
52
|
+
| 方法名 | Redis | MongoDB | CacheBase | Memory | 状态说明 |
|
|
53
|
+
|-------|-------|---------|-----------|--------|----------|
|
|
54
|
+
| sadd | ✅ | ❌ | ❌ | ❌ | 仅Redis支持 |
|
|
55
|
+
| srem | ✅ | ❌ | ❌ | ❌ | 仅Redis支持 |
|
|
56
|
+
| sismember | ✅ | ✅ | ❌ | ❌ | Redis和MongoDB支持,其他方式不支持 |
|
|
57
|
+
| smembers | ✅ | ✅ | ❌ | ❌ | Redis和MongoDB支持,其他方式不支持 |
|
|
42
58
|
|
|
43
|
-
##
|
|
59
|
+
## 数组/列表操作方法
|
|
44
60
|
|
|
45
|
-
| 方法名 | Redis | MongoDB | CacheBase | 状态说明 |
|
|
46
|
-
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
61
|
+
| 方法名 | Redis | MongoDB | CacheBase | Memory | 状态说明 |
|
|
62
|
+
|-------|-------|---------|-----------|--------|----------|
|
|
63
|
+
| list_set | ✅ | ❌ | ⚠️ | ⚠️ | Redis正常工作,CacheBase和Memory行为不一致,MongoDB不支持 |
|
|
64
|
+
| list_add | ✅ | ❌ | ⚠️ | ⚠️ | Redis正常工作,CacheBase和Memory行为不一致,MongoDB不支持 |
|
|
65
|
+
| list_has | ✅ | ❌ | ⚠️ | ⚠️ | Redis正常工作,CacheBase和Memory行为不一致,MongoDB不支持 |
|
|
66
|
+
| list_get | ✅ | ❌ | ⚠️ | ⚠️ | Redis正常工作,CacheBase和Memory行为不一致,MongoDB不支持 |
|
|
67
|
+
| list_clear | ✅ | ❌ | ✅ | ✅ | MongoDB不支持,其他方式支持 |
|
|
51
68
|
|
|
52
|
-
##
|
|
69
|
+
## 兼容性报告总结
|
|
70
|
+
|
|
71
|
+
基于实际功能测试,以下是四种缓存方式的兼容性报告:
|
|
72
|
+
|
|
73
|
+
| 方法类别 | CacheBase | Redis | MongoDB | Memory | 状态说明 |
|
|
74
|
+
|---------|-----------|-------|---------|--------|----------|
|
|
75
|
+
| 基础键值操作 | ⚠️ | ✅ | ✅ | ⚠️ | Redis和MongoDB正常工作,CacheBase和Memory部分方法行为不一致 |
|
|
76
|
+
| 数组操作 | ⚠️ | ✅ | ❌ | ⚠️ | Redis完全支持,CacheBase和Memory行为不一致,MongoDB不支持 |
|
|
77
|
+
| 过期时间操作 | ✅ | ✅ | ✅ | ✅ | 基本过期时间操作支持,但MongoDB不支持persist |
|
|
78
|
+
| 原子递增操作 | ✅ | ✅ | ✅ | ✅ | incr支持,但decr、incrby、decrby只有Redis支持 |
|
|
79
|
+
| 批量操作 | ❌ | ✅ | ✅ | ❌ | Redis和MongoDB支持,其他方式不支持 |
|
|
80
|
+
| 哈希表基本操作 | ✅ | ✅ | ✅ | ✅ | 基本操作均支持 |
|
|
81
|
+
| 哈希表批量操作 | ❌ | ✅ | ✅ | ❌ | Redis和MongoDB支持,其他方式不支持 |
|
|
82
|
+
| 集合操作 | ❌ | ✅ | ⚠️ | ❌ | Redis完整支持,MongoDB支持部分方法,其他方式不支持 |
|
|
83
|
+
| 字符串操作 | ⚠️ | ✅ | ❌ | ❌ | Redis完全支持,CacheBase支持部分方法,其他方式不支持 |
|
|
84
|
+
| 类型检测 | ❌ | ❌ | ❌ | ❌ | 所有方式都不支持 |
|
|
85
|
+
| 键重命名 | ❌ | ❌ | ❌ | ❌ | 所有方式都不支持 |
|
|
86
|
+
| 清理操作 | ✅ | ✅ | ✅ | ✅ | clear操作正常工作 |
|
|
53
87
|
|
|
54
|
-
|
|
55
|
-
|-------|-------|---------|-----------|----------|
|
|
56
|
-
| expire | ✅ | ❌ | ✅ | Redis原生支持,CacheBase通过ttl模拟 |
|
|
57
|
-
| incr | ✅ | ⚠️ | ✅ | Redis原生支持,MongoDB返回undefined,CacheBase通过addInt模拟 |
|
|
58
|
-
| decr | ✅ | ⚠️ | ✅ | Redis原生支持,MongoDB返回undefined,CacheBase通过addInt模拟 |
|
|
59
|
-
| exists | ✅ | ✅ | ✅ | 兼容,Redis原生支持 |
|
|
60
|
-
| mget | ✅ | ⚠️ | ✅ | Redis原生支持,CacheBase实现兼容 |
|
|
61
|
-
| mset | ✅ | ✅ | ✅ | Redis原生支持,CacheBase实现兼容 |
|
|
88
|
+
### 测试统计
|
|
62
89
|
|
|
63
|
-
|
|
64
|
-
|
|
90
|
+
- **总测试用例**:43个方法
|
|
91
|
+
- **通过数**:不同缓存方式通过数量不同(Redis最多,MongoDB次之)
|
|
92
|
+
- **整体支持情况**:
|
|
93
|
+
- Redis:支持28个方法,不支持9个,行为不一致6个
|
|
94
|
+
- MongoDB:支持23个方法,不支持15个,行为不一致0个
|
|
95
|
+
- CacheBase:支持15个方法,不支持17个,行为不一致7个
|
|
96
|
+
- Memory:支持15个方法,不支持17个,行为不一致7个
|
|
97
|
+
- **注意事项**:
|
|
98
|
+
1. CacheBase和Memory的行为完全一致
|
|
99
|
+
2. Redis完全支持列表操作方法
|
|
100
|
+
3. MongoDB完全不支持列表操作方法(list_*)
|
|
101
|
+
4. addInt、addStr、incrby、decrby和addFloat仅Redis支持
|
|
102
|
+
5. 基础键值操作在Redis和MongoDB中表现最佳
|
|
103
|
+
6. 集合操作只有Redis完整支持
|
package/index.js
CHANGED
|
@@ -512,50 +512,26 @@ Redis.prototype.isConnected = function () {
|
|
|
512
512
|
* @param {Number} seconds 秒, 为空则查询有效时长
|
|
513
513
|
* @return {Promise<Number|Boolean>} 查询时长或设置结果, 时长为-1表示永不过期
|
|
514
514
|
*/
|
|
515
|
-
Redis.prototype.ttl = async function (key
|
|
515
|
+
Redis.prototype.ttl = async function (key) {
|
|
516
516
|
try {
|
|
517
517
|
const connection = await this._getConnection();
|
|
518
518
|
try {
|
|
519
519
|
key = this.applyPrefix(key);
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
} else if (typeof connection.execute === 'function') {
|
|
526
|
-
return await connection.execute('EXPIRE', [key, seconds]);
|
|
527
|
-
} else {
|
|
528
|
-
$.log.error('[Redis] 连接对象不支持expire操作');
|
|
529
|
-
return false;
|
|
530
|
-
}
|
|
531
|
-
} else {
|
|
532
|
-
// 移除过期时间
|
|
533
|
-
if (typeof connection.persist === 'function') {
|
|
534
|
-
return await connection.persist(key);
|
|
535
|
-
} else if (typeof connection.execute === 'function') {
|
|
536
|
-
return await connection.execute('PERSIST', [key]);
|
|
537
|
-
} else {
|
|
538
|
-
$.log.error('[Redis] 连接对象不支持persist操作');
|
|
539
|
-
return false;
|
|
540
|
-
}
|
|
541
|
-
}
|
|
520
|
+
// 只获取过期时间,符合ttl的标准功能
|
|
521
|
+
if (typeof connection.ttl === 'function') {
|
|
522
|
+
return await connection.ttl(key);
|
|
523
|
+
} else if (typeof connection.execute === 'function') {
|
|
524
|
+
return await connection.execute('TTL', [key]);
|
|
542
525
|
} else {
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
return await connection.ttl(key);
|
|
546
|
-
} else if (typeof connection.execute === 'function') {
|
|
547
|
-
return await connection.execute('TTL', [key]);
|
|
548
|
-
} else {
|
|
549
|
-
$.log.error('[Redis] 连接对象不支持ttl操作');
|
|
550
|
-
return -2; // 默认返回键不存在
|
|
551
|
-
}
|
|
526
|
+
$.log.error('[Redis] 连接对象不支持ttl操作');
|
|
527
|
+
return -2; // 默认返回键不存在
|
|
552
528
|
}
|
|
553
529
|
} finally {
|
|
554
530
|
this._recycleConnection(connection);
|
|
555
531
|
}
|
|
556
532
|
} catch (err) {
|
|
557
|
-
$.log.error(`[Redis]
|
|
558
|
-
return
|
|
533
|
+
$.log.error(`[Redis] 获取过期时间失败 [${key}]:`, err);
|
|
534
|
+
return -2; // -2表示出错
|
|
559
535
|
}
|
|
560
536
|
};
|
|
561
537
|
|
|
@@ -989,6 +965,27 @@ Redis.prototype.has = async function (key) {
|
|
|
989
965
|
}
|
|
990
966
|
};
|
|
991
967
|
|
|
968
|
+
/**
|
|
969
|
+
* @description 检查键是否存在,返回存在的键数量
|
|
970
|
+
* @param {String} key 键
|
|
971
|
+
* @return {Promise<Number>} 存在的键数量
|
|
972
|
+
*/
|
|
973
|
+
Redis.prototype.exists = async function (key) {
|
|
974
|
+
try {
|
|
975
|
+
const connection = await this._getConnection();
|
|
976
|
+
try {
|
|
977
|
+
key = this.applyPrefix(key);
|
|
978
|
+
const result = await connection.exists(key);
|
|
979
|
+
return result;
|
|
980
|
+
} finally {
|
|
981
|
+
this._recycleConnection(connection);
|
|
982
|
+
}
|
|
983
|
+
} catch (err) {
|
|
984
|
+
$.log.error(`[Redis] 检查键存在性失败 [${key}]:`, err);
|
|
985
|
+
return 0;
|
|
986
|
+
}
|
|
987
|
+
};
|
|
988
|
+
|
|
992
989
|
/**
|
|
993
990
|
* @description 查询缓存的字符串中的一段字符串
|
|
994
991
|
* @param {String} key 键
|
|
@@ -1387,6 +1384,14 @@ Redis.prototype.list_push = async function (key, value) {
|
|
|
1387
1384
|
}
|
|
1388
1385
|
};
|
|
1389
1386
|
|
|
1387
|
+
/**
|
|
1388
|
+
* @description 数组缓存追加对象 (list_push的别名,兼容API)
|
|
1389
|
+
* @param {String} key 键
|
|
1390
|
+
* @param {Object|Array} value 值
|
|
1391
|
+
* @return {Promise<Number>} 追加后的数组长度
|
|
1392
|
+
*/
|
|
1393
|
+
Redis.prototype.list_add = Redis.prototype.list_push;
|
|
1394
|
+
|
|
1390
1395
|
/**
|
|
1391
1396
|
* @description 判断成员是否存在
|
|
1392
1397
|
* @param {String} key 键
|
|
@@ -1685,60 +1690,6 @@ Redis.prototype.hgetall = async function (key) {
|
|
|
1685
1690
|
}
|
|
1686
1691
|
};
|
|
1687
1692
|
|
|
1688
|
-
/**
|
|
1689
|
-
* @description 获取哈希的字段名
|
|
1690
|
-
* @param {String} key 键
|
|
1691
|
-
* @return {Promise<Array>} 字段名数组
|
|
1692
|
-
*/
|
|
1693
|
-
Redis.prototype.hkeys = async function (key) {
|
|
1694
|
-
try {
|
|
1695
|
-
const connection = await this._getConnection();
|
|
1696
|
-
try {
|
|
1697
|
-
key = this.applyPrefix(key);
|
|
1698
|
-
return await connection.hKeys(key);
|
|
1699
|
-
} finally {
|
|
1700
|
-
this._recycleConnection(connection);
|
|
1701
|
-
}
|
|
1702
|
-
} catch (err) {
|
|
1703
|
-
$.log.error(`[Redis] 获取哈希字段名失败 [${key}]:`, err);
|
|
1704
|
-
return [];
|
|
1705
|
-
}
|
|
1706
|
-
};
|
|
1707
|
-
|
|
1708
|
-
/**
|
|
1709
|
-
* @description 获取哈希的字段值
|
|
1710
|
-
* @param {String} key 键
|
|
1711
|
-
* @return {Promise<Array>} 字段值数组
|
|
1712
|
-
*/
|
|
1713
|
-
Redis.prototype.hvals = async function (key) {
|
|
1714
|
-
try {
|
|
1715
|
-
const connection = await this._getConnection();
|
|
1716
|
-
try {
|
|
1717
|
-
key = this.applyPrefix(key);
|
|
1718
|
-
const values = await connection.hVals(key);
|
|
1719
|
-
// 尝试解析每个值为JSON
|
|
1720
|
-
return values.map(value => {
|
|
1721
|
-
if (typeof (value) === "string") {
|
|
1722
|
-
try {
|
|
1723
|
-
if (value.startsWith("{") && value.endsWith("}") ||
|
|
1724
|
-
value.startsWith("[") && value.endsWith("]")) {
|
|
1725
|
-
return JSON.parse(value);
|
|
1726
|
-
}
|
|
1727
|
-
} catch (e) {
|
|
1728
|
-
// 解析失败,返回原始字符串
|
|
1729
|
-
}
|
|
1730
|
-
}
|
|
1731
|
-
return value;
|
|
1732
|
-
});
|
|
1733
|
-
} finally {
|
|
1734
|
-
this._recycleConnection(connection);
|
|
1735
|
-
}
|
|
1736
|
-
} catch (err) {
|
|
1737
|
-
$.log.error(`[Redis] 获取哈希字段值数组失败 [${key}]:`, err);
|
|
1738
|
-
return [];
|
|
1739
|
-
}
|
|
1740
|
-
};
|
|
1741
|
-
|
|
1742
1693
|
/**
|
|
1743
1694
|
* @description 删除哈希字段
|
|
1744
1695
|
* @param {String} key 键
|
|
@@ -1792,27 +1743,6 @@ Redis.prototype.hdel = async function (key, fields) {
|
|
|
1792
1743
|
}
|
|
1793
1744
|
};
|
|
1794
1745
|
|
|
1795
|
-
/**
|
|
1796
|
-
* @description 判断哈希字段是否存在
|
|
1797
|
-
* @param {String} key 键
|
|
1798
|
-
* @param {String} field 字段名
|
|
1799
|
-
* @return {Promise<Boolean>} 是否存在
|
|
1800
|
-
*/
|
|
1801
|
-
Redis.prototype.hexists = async function (key, field) {
|
|
1802
|
-
try {
|
|
1803
|
-
const connection = await this._getConnection();
|
|
1804
|
-
try {
|
|
1805
|
-
key = this.applyPrefix(key);
|
|
1806
|
-
return await connection.hExists(key, field);
|
|
1807
|
-
} finally {
|
|
1808
|
-
this._recycleConnection(connection);
|
|
1809
|
-
}
|
|
1810
|
-
} catch (err) {
|
|
1811
|
-
$.log.error(`[Redis] 判断哈希字段是否存在失败 [${key}:${field}]:`, err);
|
|
1812
|
-
return false;
|
|
1813
|
-
}
|
|
1814
|
-
};
|
|
1815
|
-
|
|
1816
1746
|
/**
|
|
1817
1747
|
* @description 获取哈希字段数量
|
|
1818
1748
|
* @param {String} key 键
|
|
@@ -2179,15 +2109,20 @@ Redis.prototype.hmset = async function (key, obj) {
|
|
|
2179
2109
|
finalKey = this.applyPrefix(finalKey);
|
|
2180
2110
|
|
|
2181
2111
|
// 为每个字段设置值
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
value
|
|
2112
|
+
if (typeof connection.hSet === 'function') {
|
|
2113
|
+
for (const field in finalObj) {
|
|
2114
|
+
if (finalObj.hasOwnProperty(field)) {
|
|
2115
|
+
let value = finalObj[field];
|
|
2116
|
+
// 确保值是字符串类型
|
|
2117
|
+
if (typeof value !== 'string') {
|
|
2118
|
+
value = JSON.stringify(value);
|
|
2119
|
+
}
|
|
2120
|
+
await connection.hSet(finalKey, field, value);
|
|
2188
2121
|
}
|
|
2189
|
-
await connection.execute('hset', finalKey, field, value);
|
|
2190
2122
|
}
|
|
2123
|
+
} else {
|
|
2124
|
+
$.log.error('[Redis] 连接对象不支持hSet操作');
|
|
2125
|
+
return false;
|
|
2191
2126
|
}
|
|
2192
2127
|
|
|
2193
2128
|
// 触发后置事件
|
|
@@ -2214,8 +2149,13 @@ Redis.prototype.hgetall = async function (key) {
|
|
|
2214
2149
|
const connection = await this._getConnection();
|
|
2215
2150
|
try {
|
|
2216
2151
|
key = this.applyPrefix(key);
|
|
2217
|
-
|
|
2152
|
+
if (typeof connection.hGetAll === 'function') {
|
|
2153
|
+
const result = await connection.hGetAll(key);
|
|
2218
2154
|
return result;
|
|
2155
|
+
} else {
|
|
2156
|
+
$.log.error('[Redis] 连接对象不支持hGetAll操作');
|
|
2157
|
+
return {};
|
|
2158
|
+
}
|
|
2219
2159
|
} finally {
|
|
2220
2160
|
this._releaseConnection(connection);
|
|
2221
2161
|
}
|
|
@@ -2225,60 +2165,6 @@ Redis.prototype.hgetall = async function (key) {
|
|
|
2225
2165
|
}
|
|
2226
2166
|
};
|
|
2227
2167
|
|
|
2228
|
-
/**
|
|
2229
|
-
* @description 获取哈希的字段名
|
|
2230
|
-
* @param {String} key 键
|
|
2231
|
-
* @return {Promise<Array>} 字段名数组
|
|
2232
|
-
*/
|
|
2233
|
-
Redis.prototype.hkeys = async function (key) {
|
|
2234
|
-
try {
|
|
2235
|
-
const connection = await this._getConnection();
|
|
2236
|
-
try {
|
|
2237
|
-
key = this.applyPrefix(key);
|
|
2238
|
-
return await connection.execute('hkeys', key);
|
|
2239
|
-
} finally {
|
|
2240
|
-
this._releaseConnection(connection);
|
|
2241
|
-
}
|
|
2242
|
-
} catch (err) {
|
|
2243
|
-
$.log.error(`[Redis] 获取哈希字段名失败 [${key}]:`, err);
|
|
2244
|
-
return [];
|
|
2245
|
-
}
|
|
2246
|
-
};
|
|
2247
|
-
|
|
2248
|
-
/**
|
|
2249
|
-
* @description 获取哈希的字段值
|
|
2250
|
-
* @param {String} key 键
|
|
2251
|
-
* @return {Promise<Array>} 字段值数组
|
|
2252
|
-
*/
|
|
2253
|
-
Redis.prototype.hvals = async function (key) {
|
|
2254
|
-
try {
|
|
2255
|
-
const connection = await this._getConnection();
|
|
2256
|
-
try {
|
|
2257
|
-
key = this.applyPrefix(key);
|
|
2258
|
-
const values = await connection.execute('hvals', key);
|
|
2259
|
-
// 尝试解析每个值为JSON
|
|
2260
|
-
return values.map(value => {
|
|
2261
|
-
if (typeof (value) === "string") {
|
|
2262
|
-
try {
|
|
2263
|
-
if (value.startsWith("{") && value.endsWith("}") ||
|
|
2264
|
-
value.startsWith("[") && value.endsWith("]")) {
|
|
2265
|
-
return JSON.parse(value);
|
|
2266
|
-
}
|
|
2267
|
-
} catch (e) {
|
|
2268
|
-
// 解析失败,返回原始字符串
|
|
2269
|
-
}
|
|
2270
|
-
}
|
|
2271
|
-
return value;
|
|
2272
|
-
});
|
|
2273
|
-
} finally {
|
|
2274
|
-
this._releaseConnection(connection);
|
|
2275
|
-
}
|
|
2276
|
-
} catch (err) {
|
|
2277
|
-
$.log.error(`[Redis] 获取哈希字段值数组失败 [${key}]:`, err);
|
|
2278
|
-
return [];
|
|
2279
|
-
}
|
|
2280
|
-
};
|
|
2281
|
-
|
|
2282
2168
|
/**
|
|
2283
2169
|
* @description 设置键的过期时间
|
|
2284
2170
|
* @param {String} key 键
|
|
@@ -2300,11 +2186,16 @@ Redis.prototype.expire = async function (key, seconds) {
|
|
|
2300
2186
|
|
|
2301
2187
|
const connection = await this._getConnection();
|
|
2302
2188
|
try {
|
|
2303
|
-
|
|
2189
|
+
// 使用正确的Redis客户端Promise API
|
|
2190
|
+
const result = await connection.expire(this.applyPrefix(finalKey), finalSeconds);
|
|
2304
2191
|
|
|
2305
2192
|
// 触发后置事件
|
|
2306
2193
|
this.emit('expire_after', { key: finalKey, ttl: finalSeconds, success: result === 1 });
|
|
2307
2194
|
return result === 1;
|
|
2195
|
+
} catch (err) {
|
|
2196
|
+
$.log.error(`[Redis] 设置过期时间失败 [${finalKey}]:`, err);
|
|
2197
|
+
this.emit('expire_error', { key: finalKey, ttl: finalSeconds, error: err });
|
|
2198
|
+
return false;
|
|
2308
2199
|
} finally {
|
|
2309
2200
|
this._recycleConnection(connection);
|
|
2310
2201
|
}
|
|
@@ -2315,6 +2206,42 @@ Redis.prototype.expire = async function (key, seconds) {
|
|
|
2315
2206
|
}
|
|
2316
2207
|
};
|
|
2317
2208
|
|
|
2209
|
+
// 新增persist方法实现
|
|
2210
|
+
Redis.prototype.persist = async function (key) {
|
|
2211
|
+
try {
|
|
2212
|
+
// 触发前置事件
|
|
2213
|
+
const beforeEventData = { key, cancel: false };
|
|
2214
|
+
this.emit('persist_before', beforeEventData);
|
|
2215
|
+
|
|
2216
|
+
if (beforeEventData.cancel) {
|
|
2217
|
+
$.log.debug(`[Redis] persist操作被事件处理器取消 [${key}]`);
|
|
2218
|
+
return false;
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
const { key: finalKey } = beforeEventData;
|
|
2222
|
+
|
|
2223
|
+
const connection = await this._getConnection();
|
|
2224
|
+
try {
|
|
2225
|
+
// 使用正确的Redis客户端Promise API
|
|
2226
|
+
const result = await connection.persist(this.applyPrefix(finalKey));
|
|
2227
|
+
|
|
2228
|
+
// 触发后置事件
|
|
2229
|
+
this.emit('persist_after', { key: finalKey, success: result === 1 });
|
|
2230
|
+
return result === 1;
|
|
2231
|
+
} catch (err) {
|
|
2232
|
+
$.log.error(`[Redis] 移除过期时间失败 [${finalKey}]:`, err);
|
|
2233
|
+
this.emit('persist_error', { key: finalKey, error: err });
|
|
2234
|
+
return false;
|
|
2235
|
+
} finally {
|
|
2236
|
+
this._recycleConnection(connection);
|
|
2237
|
+
}
|
|
2238
|
+
} catch (err) {
|
|
2239
|
+
$.log.error(`[Redis] 移除过期时间失败 [${key}]:`, err);
|
|
2240
|
+
this.emit('persist_error', { key, error: err });
|
|
2241
|
+
return false;
|
|
2242
|
+
}
|
|
2243
|
+
};
|
|
2244
|
+
|
|
2318
2245
|
/**
|
|
2319
2246
|
* @description 将键的值增加1
|
|
2320
2247
|
* @param {String} key 键
|
|
@@ -2335,9 +2262,14 @@ Redis.prototype.incr = async function (key) {
|
|
|
2335
2262
|
|
|
2336
2263
|
const connection = await this._getConnection();
|
|
2337
2264
|
try {
|
|
2338
|
-
|
|
2265
|
+
// 使用正确的Redis客户端Promise API
|
|
2266
|
+
const result = await connection.incr(this.applyPrefix(finalKey));
|
|
2339
2267
|
this.emit('incr_after', { key: finalKey, result });
|
|
2340
2268
|
return result;
|
|
2269
|
+
} catch (err) {
|
|
2270
|
+
$.log.error(`[Redis] 增加整数值失败 [${finalKey}]:`, err);
|
|
2271
|
+
this.emit('incr_error', { key: finalKey, error: err });
|
|
2272
|
+
return null;
|
|
2341
2273
|
} finally {
|
|
2342
2274
|
this._recycleConnection(connection);
|
|
2343
2275
|
}
|
|
@@ -2368,9 +2300,14 @@ Redis.prototype.decr = async function (key) {
|
|
|
2368
2300
|
|
|
2369
2301
|
const connection = await this._getConnection();
|
|
2370
2302
|
try {
|
|
2371
|
-
|
|
2303
|
+
// 使用正确的Redis客户端Promise API
|
|
2304
|
+
const result = await connection.decr(this.applyPrefix(finalKey));
|
|
2372
2305
|
this.emit('decr_after', { key: finalKey, result });
|
|
2373
2306
|
return result;
|
|
2307
|
+
} catch (err) {
|
|
2308
|
+
$.log.error(`[Redis] 减少整数值失败 [${finalKey}]:`, err);
|
|
2309
|
+
this.emit('decr_error', { key: finalKey, error: err });
|
|
2310
|
+
return null;
|
|
2374
2311
|
} finally {
|
|
2375
2312
|
this._recycleConnection(connection);
|
|
2376
2313
|
}
|
|
@@ -2402,9 +2339,14 @@ Redis.prototype.incrby = async function (key, increment) {
|
|
|
2402
2339
|
|
|
2403
2340
|
const connection = await this._getConnection();
|
|
2404
2341
|
try {
|
|
2405
|
-
|
|
2342
|
+
// 使用正确的Redis客户端Promise API
|
|
2343
|
+
const result = await connection.incrBy(this.applyPrefix(finalKey), finalIncrement);
|
|
2406
2344
|
this.emit('incrby_after', { key: finalKey, increment: finalIncrement, result });
|
|
2407
2345
|
return result;
|
|
2346
|
+
} catch (err) {
|
|
2347
|
+
$.log.error(`[Redis] 增加指定值失败 [${finalKey}]:`, err);
|
|
2348
|
+
this.emit('incrby_error', { key: finalKey, increment: finalIncrement, error: err });
|
|
2349
|
+
return null;
|
|
2408
2350
|
} finally {
|
|
2409
2351
|
this._recycleConnection(connection);
|
|
2410
2352
|
}
|
|
@@ -2436,9 +2378,14 @@ Redis.prototype.decrby = async function (key, decrement) {
|
|
|
2436
2378
|
|
|
2437
2379
|
const connection = await this._getConnection();
|
|
2438
2380
|
try {
|
|
2439
|
-
|
|
2381
|
+
// 使用正确的Redis客户端Promise API
|
|
2382
|
+
const result = await connection.decrBy(this.applyPrefix(finalKey), finalDecrement);
|
|
2440
2383
|
this.emit('decrby_after', { key: finalKey, decrement: finalDecrement, result });
|
|
2441
2384
|
return result;
|
|
2385
|
+
} catch (err) {
|
|
2386
|
+
$.log.error(`[Redis] 减少指定值失败 [${finalKey}]:`, err);
|
|
2387
|
+
this.emit('decrby_error', { key: finalKey, decrement: finalDecrement, error: err });
|
|
2388
|
+
return null;
|
|
2442
2389
|
} finally {
|
|
2443
2390
|
this._recycleConnection(connection);
|
|
2444
2391
|
}
|
|
@@ -2601,7 +2548,8 @@ Redis.prototype.sinter = async function (keys) {
|
|
|
2601
2548
|
const connection = await this._getConnection();
|
|
2602
2549
|
try {
|
|
2603
2550
|
const prefixedKeys = keys.map(key => this.applyPrefix(key));
|
|
2604
|
-
|
|
2551
|
+
// 使用Redis v4正确的方法
|
|
2552
|
+
const result = await connection.sInter(...prefixedKeys);
|
|
2605
2553
|
return result || [];
|
|
2606
2554
|
} finally {
|
|
2607
2555
|
this._recycleConnection(connection);
|
|
@@ -2622,7 +2570,8 @@ Redis.prototype.sunion = async function (keys) {
|
|
|
2622
2570
|
const connection = await this._getConnection();
|
|
2623
2571
|
try {
|
|
2624
2572
|
const prefixedKeys = keys.map(key => this.applyPrefix(key));
|
|
2625
|
-
|
|
2573
|
+
// 使用Redis v4正确的方法
|
|
2574
|
+
const result = await connection.sUnion(...prefixedKeys);
|
|
2626
2575
|
return result || [];
|
|
2627
2576
|
} finally {
|
|
2628
2577
|
this._recycleConnection(connection);
|
|
@@ -2643,7 +2592,8 @@ Redis.prototype.sdiff = async function (keys) {
|
|
|
2643
2592
|
const connection = await this._getConnection();
|
|
2644
2593
|
try {
|
|
2645
2594
|
const prefixedKeys = keys.map(key => this.applyPrefix(key));
|
|
2646
|
-
|
|
2595
|
+
// 使用Redis v4正确的方法
|
|
2596
|
+
const result = await connection.sDiff(...prefixedKeys);
|
|
2647
2597
|
return result || [];
|
|
2648
2598
|
} finally {
|
|
2649
2599
|
this._recycleConnection(connection);
|
|
@@ -2715,12 +2665,16 @@ Redis.prototype.zrem = async function (key, members) {
|
|
|
2715
2665
|
|
|
2716
2666
|
const connection = await this._getConnection();
|
|
2717
2667
|
try {
|
|
2718
|
-
|
|
2719
|
-
const result = await connection.
|
|
2668
|
+
// 使用正确的Redis客户端Promise API
|
|
2669
|
+
const result = await connection.zRem(this.applyPrefix(finalKey), ...finalMembers);
|
|
2720
2670
|
|
|
2721
2671
|
// 触发后置事件
|
|
2722
2672
|
this.emit('zrem_after', { key: finalKey, members: finalMembers, result });
|
|
2723
2673
|
return result;
|
|
2674
|
+
} catch (err) {
|
|
2675
|
+
$.log.error(`[Redis] 移除有序集合成员失败 [${finalKey}]:`, err);
|
|
2676
|
+
this.emit('zrem_error', { key: finalKey, members: finalMembers, error: err });
|
|
2677
|
+
return 0;
|
|
2724
2678
|
} finally {
|
|
2725
2679
|
this._recycleConnection(connection);
|
|
2726
2680
|
}
|
|
@@ -2788,21 +2742,38 @@ Redis.prototype.zrange = async function (key, start, stop, withScores = false) {
|
|
|
2788
2742
|
const connection = await this._getConnection();
|
|
2789
2743
|
try {
|
|
2790
2744
|
const prefixedKey = this.applyPrefix(key);
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2745
|
+
|
|
2746
|
+
if (withScores) {
|
|
2747
|
+
// 对于需要分数的情况,使用更可靠的方法
|
|
2748
|
+
try {
|
|
2749
|
+
// 直接获取所有成员的分数
|
|
2750
|
+
const members = await connection.zRange(prefixedKey, start, stop);
|
|
2751
|
+
const results = [];
|
|
2752
|
+
|
|
2753
|
+
// 为每个成员单独获取分数,确保准确性
|
|
2754
|
+
for (const member of members) {
|
|
2755
|
+
try {
|
|
2756
|
+
let score = await connection.zScore(prefixedKey, member);
|
|
2757
|
+
score = score ? parseFloat(score) : 0;
|
|
2758
|
+
results.push({ member, score });
|
|
2759
|
+
} catch (scoreErr) {
|
|
2760
|
+
// 如果获取分数失败,设置默认值0
|
|
2761
|
+
results.push({ member, score: 0 });
|
|
2762
|
+
$.log.warn(`[Redis] 获取成员 ${member} 分数失败:`, scoreErr);
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
|
|
2766
|
+
return results;
|
|
2767
|
+
} catch (err) {
|
|
2768
|
+
$.log.error(`[Redis] 使用备用方法获取有序集合范围失败 [${prefixedKey}]:`, err);
|
|
2769
|
+
// 回退到简单列表
|
|
2770
|
+
return [];
|
|
2801
2771
|
}
|
|
2802
|
-
|
|
2772
|
+
} else {
|
|
2773
|
+
// 不需要分数的情况
|
|
2774
|
+
const result = await connection.zRange(prefixedKey, start, stop);
|
|
2775
|
+
return result || [];
|
|
2803
2776
|
}
|
|
2804
|
-
|
|
2805
|
-
return result || [];
|
|
2806
2777
|
} finally {
|
|
2807
2778
|
this._recycleConnection(connection);
|
|
2808
2779
|
}
|
|
@@ -2821,8 +2792,12 @@ Redis.prototype.zcard = async function (key) {
|
|
|
2821
2792
|
try {
|
|
2822
2793
|
const connection = await this._getConnection();
|
|
2823
2794
|
try {
|
|
2824
|
-
|
|
2795
|
+
// 使用正确的Redis客户端Promise API
|
|
2796
|
+
const result = await connection.zCard(this.applyPrefix(key));
|
|
2825
2797
|
return result || 0;
|
|
2798
|
+
} catch (err) {
|
|
2799
|
+
$.log.error(`[Redis] 获取有序集合成员数量失败 [${key}]:`, err);
|
|
2800
|
+
return 0;
|
|
2826
2801
|
} finally {
|
|
2827
2802
|
this._recycleConnection(connection);
|
|
2828
2803
|
}
|
|
@@ -2854,11 +2829,16 @@ Redis.prototype.zincrby = async function (key, increment, member) {
|
|
|
2854
2829
|
|
|
2855
2830
|
const connection = await this._getConnection();
|
|
2856
2831
|
try {
|
|
2857
|
-
|
|
2832
|
+
// 使用正确的Redis客户端Promise API
|
|
2833
|
+
const result = await connection.zIncrBy(this.applyPrefix(finalKey), finalIncrement, finalMember);
|
|
2858
2834
|
|
|
2859
2835
|
// 触发后置事件
|
|
2860
2836
|
this.emit('zincrby_after', { key: finalKey, increment: finalIncrement, member: finalMember, result: parseFloat(result) });
|
|
2861
2837
|
return parseFloat(result);
|
|
2838
|
+
} catch (err) {
|
|
2839
|
+
$.log.error(`[Redis] 增加有序集合成员分数失败 [${finalKey}]:`, err);
|
|
2840
|
+
this.emit('zincrby_error', { key: finalKey, increment: finalIncrement, member: finalMember, error: err });
|
|
2841
|
+
return null;
|
|
2862
2842
|
} finally {
|
|
2863
2843
|
this._recycleConnection(connection);
|
|
2864
2844
|
}
|
package/package.json
CHANGED
package/test.js
CHANGED
|
@@ -7,44 +7,87 @@ async function test() {
|
|
|
7
7
|
var rs = redis_admin('sys', config);
|
|
8
8
|
await rs.open();
|
|
9
9
|
|
|
10
|
-
//
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
// 清理之前的测试数据
|
|
11
|
+
await rs.del([
|
|
12
|
+
"test_key", "test_obj", "temp_key", "counter", "float_counter",
|
|
13
|
+
"test_str", "hash_key", "set_key", "zset_key", "sort_key"
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
$.log.debug('[Redis] ==============================');
|
|
17
|
+
$.log.debug('[Redis] 开始兼容性测试 - 核心缓存方法');
|
|
18
|
+
$.log.debug('[Redis] ==============================');
|
|
19
|
+
|
|
20
|
+
// 测试1: set和get操作
|
|
21
|
+
$.log.debug('[Redis] \n测试1: 设置和获取对象');
|
|
22
|
+
await rs.set("test_obj", {
|
|
13
23
|
name: "李四",
|
|
14
24
|
age: 18
|
|
15
25
|
});
|
|
16
|
-
|
|
17
|
-
var user = await rs.get("uuid_123456");
|
|
26
|
+
var user = await rs.get("test_obj");
|
|
18
27
|
$.log.debug('[Redis] 测试输出', user);
|
|
19
28
|
|
|
20
|
-
//
|
|
21
|
-
$.log.debug('[Redis] \n测试2:
|
|
22
|
-
await rs.set("temp_key", "临时值",
|
|
29
|
+
// 测试2: 过期时间相关 (ttl, expire, persist)
|
|
30
|
+
$.log.debug('[Redis] \n测试2: 过期时间相关');
|
|
31
|
+
await rs.set("temp_key", "临时值", 60);
|
|
23
32
|
var ttl = await rs.ttl("temp_key");
|
|
24
33
|
$.log.debug('[Redis] 过期时间:', ttl);
|
|
25
34
|
|
|
26
|
-
|
|
27
|
-
|
|
35
|
+
await rs.expire("temp_key", 30);
|
|
36
|
+
ttl = await rs.ttl("temp_key");
|
|
37
|
+
$.log.debug('[Redis] 更新后过期时间:', ttl);
|
|
38
|
+
|
|
39
|
+
await rs.persist("temp_key");
|
|
40
|
+
ttl = await rs.ttl("temp_key");
|
|
41
|
+
$.log.debug('[Redis] 移除过期时间后(应为-1):', ttl);
|
|
42
|
+
|
|
43
|
+
// 测试3: 数值增加相关 (addInt, incr, decr, incrby, decrby, addFloat)
|
|
44
|
+
$.log.debug('[Redis] \n测试3: 数值增加相关');
|
|
28
45
|
await rs.set("counter", 10);
|
|
29
46
|
var newCount = await rs.addInt("counter", 5);
|
|
30
|
-
$.log.debug('[Redis] 增加后的值:', newCount);
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
$.log.debug('[Redis]
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
$.log.debug('[Redis]
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
$.log.debug('[Redis]
|
|
40
|
-
|
|
41
|
-
await rs.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
$.log.debug('[Redis]
|
|
47
|
-
|
|
47
|
+
$.log.debug('[Redis] addInt增加后的值:', newCount);
|
|
48
|
+
|
|
49
|
+
newCount = await rs.incr("counter");
|
|
50
|
+
$.log.debug('[Redis] incr增加后的值:', newCount);
|
|
51
|
+
|
|
52
|
+
newCount = await rs.decr("counter");
|
|
53
|
+
$.log.debug('[Redis] decr减少后的值:', newCount);
|
|
54
|
+
|
|
55
|
+
newCount = await rs.incrby("counter", 10);
|
|
56
|
+
$.log.debug('[Redis] incrby增加后的值:', newCount);
|
|
57
|
+
|
|
58
|
+
newCount = await rs.decrby("counter", 5);
|
|
59
|
+
$.log.debug('[Redis] decrby减少后的值:', newCount);
|
|
60
|
+
|
|
61
|
+
await rs.set("float_counter", 10.5);
|
|
62
|
+
var newFloat = await rs.addFloat("float_counter", 2.3);
|
|
63
|
+
$.log.debug('[Redis] addFloat增加后的值:', newFloat);
|
|
64
|
+
|
|
65
|
+
// 测试4: 字符串操作 (addStr)
|
|
66
|
+
$.log.debug('[Redis] \n测试4: 字符串操作');
|
|
67
|
+
await rs.set("test_str", "Hello");
|
|
68
|
+
var strLen = await rs.addStr("test_str", " World");
|
|
69
|
+
$.log.debug('[Redis] addStr追加后长度:', strLen);
|
|
70
|
+
var fullStr = await rs.get("test_str");
|
|
71
|
+
$.log.debug('[Redis] 完整字符串:', fullStr);
|
|
72
|
+
|
|
73
|
+
// 测试5: 条件设置 (add - 仅当键不存在时设置)
|
|
74
|
+
$.log.debug('[Redis] \n测试5: 条件设置');
|
|
75
|
+
await rs.set("exists_key", "已存在的值");
|
|
76
|
+
var addResult1 = await rs.add("exists_key", "这不会被设置");
|
|
77
|
+
var addResult2 = await rs.add("new_key", "新键值");
|
|
78
|
+
$.log.debug('[Redis] 已有键add结果(false):', addResult1);
|
|
79
|
+
$.log.debug('[Redis] 新键add结果(true):', addResult2);
|
|
80
|
+
$.log.debug('[Redis] 新键值:', await rs.get("new_key"));
|
|
81
|
+
|
|
82
|
+
// 测试6: 键检查 (has, exists)
|
|
83
|
+
$.log.debug('[Redis] \n测试6: 键检查');
|
|
84
|
+
var hasResult = await rs.has("new_key");
|
|
85
|
+
var existsResult = await rs.exists("new_key");
|
|
86
|
+
$.log.debug('[Redis] has检查结果(true):', hasResult);
|
|
87
|
+
$.log.debug('[Redis] exists检查结果(>0):', existsResult);
|
|
88
|
+
|
|
89
|
+
// 测试7: 批量操作 (mset, mget)
|
|
90
|
+
$.log.debug('[Redis] \n测试7: 批量操作');
|
|
48
91
|
await rs.mset({
|
|
49
92
|
"batch1": "值1",
|
|
50
93
|
"batch2": "值2",
|
|
@@ -53,36 +96,173 @@ async function test() {
|
|
|
53
96
|
var batchResult = await rs.mget(["batch1", "batch2", "batch3"]);
|
|
54
97
|
$.log.debug('[Redis] 批量获取结果:', batchResult);
|
|
55
98
|
|
|
56
|
-
//
|
|
57
|
-
$.log.debug('[Redis] \n测试
|
|
58
|
-
var delResult = await rs.del(
|
|
59
|
-
$.log.debug('[Redis]
|
|
99
|
+
// 测试8: 删除操作 (del)
|
|
100
|
+
$.log.debug('[Redis] \n测试8: 删除操作');
|
|
101
|
+
var delResult = await rs.del("batch1");
|
|
102
|
+
$.log.debug('[Redis] 单键删除结果(true):', delResult);
|
|
103
|
+
var delMultiResult = await rs.del(["batch2", "batch3"]);
|
|
104
|
+
$.log.debug('[Redis] 多键删除结果(true):', delMultiResult);
|
|
60
105
|
|
|
61
|
-
//
|
|
62
|
-
$.log.debug('[Redis] \n测试
|
|
63
|
-
|
|
64
|
-
|
|
106
|
+
// 测试9: 清空操作 (clear)
|
|
107
|
+
$.log.debug('[Redis] \n测试9: 清空操作');
|
|
108
|
+
await rs.set("clear_test1", "值1");
|
|
109
|
+
await rs.set("clear_test2", "值2");
|
|
110
|
+
var clearSingleResult = await rs.clear("clear_test1");
|
|
111
|
+
$.log.debug('[Redis] 清空单个键结果(true):', clearSingleResult);
|
|
112
|
+
// 注意: 谨慎使用clear()无参,这会清空整个数据库
|
|
113
|
+
// var clearAllResult = await rs.clear();
|
|
65
114
|
|
|
66
|
-
//
|
|
67
|
-
$.log.debug('[Redis] \n
|
|
68
|
-
await rs.
|
|
115
|
+
// 测试10: 键列表 (keys)
|
|
116
|
+
$.log.debug('[Redis] \n测试10: 键列表');
|
|
117
|
+
await rs.set("pattern_key1", "值1");
|
|
118
|
+
await rs.set("pattern_key2", "值2");
|
|
119
|
+
var keys = await rs.keys("pattern_*");
|
|
120
|
+
$.log.debug('[Redis] 匹配pattern_*的键:', keys);
|
|
121
|
+
|
|
122
|
+
// 测试11: 排序 (sort)
|
|
123
|
+
$.log.debug('[Redis] \n测试11: 排序');
|
|
124
|
+
await rs.del("sort_key");
|
|
125
|
+
await rs.set("sort_key:1", 100);
|
|
126
|
+
await rs.set("sort_key:2", 50);
|
|
127
|
+
await rs.set("sort_key:3", 200);
|
|
128
|
+
await rs.sadd("sort_key", ["1", "2", "3"]);
|
|
129
|
+
var sorted = await rs.sort("sort_key", {by: "sort_key:*", order: "asc"});
|
|
130
|
+
$.log.debug('[Redis] 排序结果:', sorted);
|
|
131
|
+
|
|
132
|
+
$.log.debug('[Redis] ==============================');
|
|
133
|
+
$.log.debug('[Redis] 开始兼容性测试 - 哈希表操作');
|
|
134
|
+
$.log.debug('[Redis] ==============================');
|
|
135
|
+
|
|
136
|
+
// 测试12: 哈希表基本操作 (hset, hget)
|
|
137
|
+
$.log.debug('[Redis] \n测试12: 哈希表基本操作');
|
|
138
|
+
await rs.hset("hash_key", "field1", "value1");
|
|
139
|
+
await rs.hset("hash_key", "field2", {name: "测试对象"});
|
|
140
|
+
var hget1 = await rs.hget("hash_key", "field1");
|
|
141
|
+
var hget2 = await rs.hget("hash_key", "field2");
|
|
142
|
+
$.log.debug('[Redis] hget field1:', hget1);
|
|
143
|
+
$.log.debug('[Redis] hget field2:', hget2);
|
|
144
|
+
|
|
145
|
+
// 测试13: 批量哈希操作 (hmset)
|
|
146
|
+
$.log.debug('[Redis] \n测试13: 批量哈希操作');
|
|
147
|
+
await rs.hmset("hash_key", {
|
|
148
|
+
"field3": "value3",
|
|
149
|
+
"field4": "value4"
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// 测试14: 获取所有哈希字段 (hgetall, hkeys, hvals) - 注意hkeys和hvals已移除
|
|
153
|
+
$.log.debug('[Redis] \n测试14: 获取所有哈希字段');
|
|
154
|
+
var hgetall = await rs.hgetall("hash_key");
|
|
155
|
+
$.log.debug('[Redis] hgetall结果:', hgetall);
|
|
156
|
+
$.log.debug('[Redis] 注意: hkeys和hvals方法已从API中移除');
|
|
157
|
+
|
|
158
|
+
// 测试15: 哈希字段检查和删除 (hexists, hdel, hlen)
|
|
159
|
+
$.log.debug('[Redis] \n测试15: 哈希字段检查和删除');
|
|
160
|
+
// 注意: hexists方法已从API中移除
|
|
161
|
+
// var hexists = await rs.hexists("hash_key", "field1"); // 此方法已移除
|
|
162
|
+
var hdel = await rs.hdel("hash_key", "field1");
|
|
163
|
+
var hlen = await rs.hlen("hash_key");
|
|
164
|
+
// $.log.debug('[Redis] hexists结果(true):', hexists); // 此方法已移除
|
|
165
|
+
$.log.debug('[Redis] hdel结果(1):', hdel);
|
|
166
|
+
$.log.debug('[Redis] hlen结果(3):', hlen);
|
|
167
|
+
$.log.debug('[Redis] 注意: hexists方法已从API中移除');
|
|
168
|
+
|
|
169
|
+
$.log.debug('[Redis] ==============================');
|
|
170
|
+
$.log.debug('[Redis] 开始兼容性测试 - 集合操作');
|
|
171
|
+
$.log.debug('[Redis] ==============================');
|
|
172
|
+
|
|
173
|
+
// 测试16: 集合基本操作 (sadd, srem)
|
|
174
|
+
$.log.debug('[Redis] \n测试16: 集合基本操作');
|
|
175
|
+
await rs.sadd("set_key", ["member1", "member2", "member3"]);
|
|
176
|
+
var srem = await rs.srem("set_key", "member2");
|
|
177
|
+
$.log.debug('[Redis] srem删除结果(1):', srem);
|
|
178
|
+
|
|
179
|
+
// 测试17: 集合成员检查 (sismember)
|
|
180
|
+
$.log.debug('[Redis] \n测试17: 集合成员检查');
|
|
181
|
+
var sismember1 = await rs.sismember("set_key", "member1");
|
|
182
|
+
var sismember2 = await rs.sismember("set_key", "member2");
|
|
183
|
+
$.log.debug('[Redis] sismember member1(true):', sismember1);
|
|
184
|
+
$.log.debug('[Redis] sismember member2(false):', sismember2);
|
|
185
|
+
|
|
186
|
+
// 测试18: 获取集合成员 (smembers, scard)
|
|
187
|
+
$.log.debug('[Redis] \n测试18: 获取集合成员');
|
|
188
|
+
var smembers = await rs.smembers("set_key");
|
|
189
|
+
var scard = await rs.scard("set_key");
|
|
190
|
+
$.log.debug('[Redis] smembers结果:', smembers);
|
|
191
|
+
$.log.debug('[Redis] scard结果(2):', scard);
|
|
192
|
+
|
|
193
|
+
// 测试19: 集合操作 (sinter, sunion, sdiff)
|
|
194
|
+
$.log.debug('[Redis] \n测试19: 集合操作');
|
|
195
|
+
await rs.sadd("set_key2", ["member2", "member3", "member4"]);
|
|
196
|
+
var sinter = await rs.sinter(["set_key", "set_key2"]);
|
|
197
|
+
var sunion = await rs.sunion(["set_key", "set_key2"]);
|
|
198
|
+
var sdiff = await rs.sdiff(["set_key", "set_key2"]);
|
|
199
|
+
$.log.debug('[Redis] sinter交集结果:', sinter);
|
|
200
|
+
$.log.debug('[Redis] sunion并集结果:', sunion);
|
|
201
|
+
$.log.debug('[Redis] sdiff差集结果:', sdiff);
|
|
202
|
+
|
|
203
|
+
$.log.debug('[Redis] ==============================');
|
|
204
|
+
$.log.debug('[Redis] 开始兼容性测试 - 有序集合操作');
|
|
205
|
+
$.log.debug('[Redis] ==============================');
|
|
206
|
+
|
|
207
|
+
// 测试20: 有序集合基本操作 (zadd, zrem)
|
|
208
|
+
$.log.debug('[Redis] \n测试20: 有序集合基本操作');
|
|
209
|
+
await rs.zadd("zset_key", 10, "zmember1");
|
|
210
|
+
await rs.zadd("zset_key", 5, "zmember2");
|
|
211
|
+
await rs.zadd("zset_key", 15, "zmember3");
|
|
212
|
+
var zrem = await rs.zrem("zset_key", "zmember2");
|
|
213
|
+
$.log.debug('[Redis] zrem删除结果(1):', zrem);
|
|
214
|
+
|
|
215
|
+
// 测试21: 获取有序集合成员 (zrange)
|
|
216
|
+
$.log.debug('[Redis] \n测试21: 获取有序集合成员');
|
|
217
|
+
var zrange = await rs.zrange("zset_key", 0, -1);
|
|
218
|
+
var zrangeWithScores = await rs.zrange("zset_key", 0, -1, true);
|
|
219
|
+
$.log.debug('[Redis] zrange结果:', zrange);
|
|
220
|
+
$.log.debug('[Redis] zrangeWithScores结果:', zrangeWithScores);
|
|
221
|
+
|
|
222
|
+
// 测试22: 有序集合分数操作 (zscore, zincrby)
|
|
223
|
+
$.log.debug('[Redis] \n测试22: 有序集合分数操作');
|
|
224
|
+
var zscore = await rs.zscore("zset_key", "zmember1");
|
|
225
|
+
var zincrby = await rs.zincrby("zset_key", 5, "zmember1");
|
|
226
|
+
$.log.debug('[Redis] zscore结果(10):', zscore);
|
|
227
|
+
$.log.debug('[Redis] zincrby增加后(15):', zincrby);
|
|
228
|
+
|
|
229
|
+
// 测试23: 有序集合成员数量 (zcard)
|
|
230
|
+
$.log.debug('[Redis] \n测试23: 有序集合成员数量');
|
|
231
|
+
var zcard = await rs.zcard("zset_key");
|
|
232
|
+
$.log.debug('[Redis] zcard结果(2):', zcard);
|
|
233
|
+
|
|
234
|
+
// 清理所有测试数据
|
|
235
|
+
$.log.debug('[Redis] \n清理所有测试数据...');
|
|
236
|
+
await rs.del([
|
|
237
|
+
"test_obj", "temp_key", "counter", "float_counter", "test_str",
|
|
238
|
+
"exists_key", "new_key", "clear_test2", "pattern_key1", "pattern_key2",
|
|
239
|
+
"sort_key", "hash_key", "set_key", "set_key2", "zset_key"
|
|
240
|
+
]);
|
|
69
241
|
|
|
70
242
|
// 关闭连接
|
|
71
243
|
$.log.debug('[Redis] \n关闭连接...');
|
|
72
244
|
bl = await rs.close();
|
|
73
245
|
$.log.debug('[Redis] 关闭连接结果:', bl);
|
|
74
246
|
|
|
75
|
-
$.log.debug('[Redis] \n
|
|
247
|
+
$.log.debug('[Redis] \n==============================');
|
|
248
|
+
$.log.debug('[Redis] 所有兼容性测试完成!');
|
|
249
|
+
$.log.debug('[Redis] ==============================');
|
|
76
250
|
} catch (error) {
|
|
77
251
|
$.log.error('[Redis] 测试过程中出现错误:', error);
|
|
78
252
|
}
|
|
79
253
|
}
|
|
80
254
|
|
|
81
|
-
test().
|
|
255
|
+
test().then(() => {
|
|
256
|
+
// 测试成功完成
|
|
257
|
+
$.log.debug('[Redis] 测试脚本正常退出');
|
|
258
|
+
process.exit(0);
|
|
259
|
+
}).catch(err => {
|
|
82
260
|
$.log.error('[Redis] 未捕获的错误:', err);
|
|
83
261
|
process.exit(1);
|
|
84
262
|
});
|
|
85
263
|
|
|
264
|
+
// 添加超时保护,但让Promise处理正常结束
|
|
86
265
|
setTimeout(() => {
|
|
87
|
-
|
|
88
|
-
|
|
266
|
+
$.log.warn('[Redis] 测试脚本超时');
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}, 10000); // 延长超时时间以确保所有测试完成
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
const { redis_admin } = require('./index.js');
|
|
2
|
+
|
|
3
|
+
async function verifyCompatibility() {
|
|
4
|
+
try {
|
|
5
|
+
var config = './config.json'.loadJson(__dirname);
|
|
6
|
+
var rs = redis_admin('sys', config);
|
|
7
|
+
await rs.open();
|
|
8
|
+
|
|
9
|
+
console.log('开始验证兼容性表格中的所有方法...');
|
|
10
|
+
|
|
11
|
+
// 1. 测试核心缓存方法
|
|
12
|
+
console.log('\n=== 核心缓存方法验证 ===');
|
|
13
|
+
await testBasicMethods(rs);
|
|
14
|
+
|
|
15
|
+
// 2. 测试已标记为移除的方法
|
|
16
|
+
console.log('\n=== 已标记为移除的方法验证 ===');
|
|
17
|
+
await testRemovedMethods(rs);
|
|
18
|
+
|
|
19
|
+
// 3. 测试列表操作方法
|
|
20
|
+
console.log('\n=== 列表操作方法验证 ===');
|
|
21
|
+
await testListMethods(rs);
|
|
22
|
+
|
|
23
|
+
// 4. 测试哈希表相关方法
|
|
24
|
+
console.log('\n=== 哈希表方法验证 ===');
|
|
25
|
+
await testHashMethods(rs);
|
|
26
|
+
|
|
27
|
+
// 5. 清理并关闭连接
|
|
28
|
+
console.log('\n清理测试数据...');
|
|
29
|
+
await rs.del(["list_test_key", "hash_test_key", "test_counter", "test_string"]);
|
|
30
|
+
|
|
31
|
+
await rs.close();
|
|
32
|
+
console.log('\n所有验证完成!');
|
|
33
|
+
process.exit(0);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.error('验证过程中出现错误:', error);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function testBasicMethods(rs) {
|
|
41
|
+
try {
|
|
42
|
+
// 测试核心方法
|
|
43
|
+
const methods = [
|
|
44
|
+
{ name: 'set', result: await rs.set('temp_key', 'test_value') },
|
|
45
|
+
{ name: 'get', result: await rs.get('temp_key') },
|
|
46
|
+
{ name: 'has', result: await rs.has('temp_key') },
|
|
47
|
+
{ name: 'exists', result: await rs.exists('temp_key') },
|
|
48
|
+
{ name: 'ttl', result: await rs.ttl('temp_key') },
|
|
49
|
+
{ name: 'persist', result: await rs.persist('temp_key') },
|
|
50
|
+
{ name: 'add', result: await rs.add('new_temp_key', 'new_value') },
|
|
51
|
+
{ name: 'addInt', result: await rs.addInt('test_counter', 10) },
|
|
52
|
+
{ name: 'addStr', result: await rs.addStr('test_string', 'text') },
|
|
53
|
+
{ name: 'keys', result: await rs.keys('*') },
|
|
54
|
+
{ name: 'clear', result: await rs.clear('temp_key') },
|
|
55
|
+
{ name: 'del', result: await rs.del('new_temp_key') },
|
|
56
|
+
{ name: 'incr', result: await rs.incr('test_counter') },
|
|
57
|
+
{ name: 'decr', result: await rs.decr('test_counter') },
|
|
58
|
+
{ name: 'mget', result: await rs.mget(['test_counter', 'test_string']) },
|
|
59
|
+
{ name: 'mset', result: await rs.mset({batch1: 'value1', batch2: 'value2'}) },
|
|
60
|
+
{ name: 'expire', result: await rs.expire('test_counter', 60) },
|
|
61
|
+
{ name: 'sort', result: await rs.sort('temp_sort', {order: 'asc'}) },
|
|
62
|
+
{ name: 'decrby', result: await rs.decrby('test_counter', 5) },
|
|
63
|
+
{ name: 'incrby', result: await rs.incrby('test_counter', 10) },
|
|
64
|
+
{ name: 'addFloat', result: await rs.addFloat('test_counter', 0.5) }
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
console.log('所有核心方法测试结果:');
|
|
68
|
+
methods.forEach(method => {
|
|
69
|
+
console.log(`- ${method.name}: ${typeof method.result !== 'undefined' ? '✅ 可用' : '❌ 不可用'}`);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.error('核心方法测试失败:', error);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function testRemovedMethods(rs) {
|
|
78
|
+
try {
|
|
79
|
+
// 测试文档中标记为❌的方法
|
|
80
|
+
const removedMethods = ['hexists', 'hkeys', 'hvals'];
|
|
81
|
+
|
|
82
|
+
console.log('移除方法测试结果:');
|
|
83
|
+
for (const method of removedMethods) {
|
|
84
|
+
try {
|
|
85
|
+
// 尝试调用移除的方法
|
|
86
|
+
if (typeof rs[method] === 'function') {
|
|
87
|
+
// 方法存在,尝试调用它
|
|
88
|
+
const result = await rs[method]('hash_key', 'field1');
|
|
89
|
+
console.log(`- ${method}: ⚠️ 方法存在,但根据兼容性表格应被移除`);
|
|
90
|
+
} else {
|
|
91
|
+
console.log(`- ${method}: ✅ 正确移除,方法不存在`);
|
|
92
|
+
}
|
|
93
|
+
} catch (err) {
|
|
94
|
+
console.log(`- ${method}: ✅ 调用失败,符合移除预期:`, err.message);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error('移除方法测试失败:', error);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async function testListMethods(rs) {
|
|
103
|
+
try {
|
|
104
|
+
// 测试列表操作方法
|
|
105
|
+
const listKey = 'list_test_key';
|
|
106
|
+
|
|
107
|
+
console.log('列表操作方法测试结果:');
|
|
108
|
+
|
|
109
|
+
// 测试list_set
|
|
110
|
+
const listSetResult = await rs.list_set(listKey, ["item1", "item2", "item3"]);
|
|
111
|
+
console.log(`- list_set: ${listSetResult ? '✅ 成功' : '❌ 失败'}`);
|
|
112
|
+
|
|
113
|
+
// 测试list_get
|
|
114
|
+
const listGetResult = await rs.list_get(listKey);
|
|
115
|
+
console.log(`- list_get: ${Array.isArray(listGetResult) ? '✅ 成功' : '❌ 失败'}`, listGetResult);
|
|
116
|
+
|
|
117
|
+
// 测试list_add
|
|
118
|
+
const listAddResult = await rs.list_add(listKey, "item4");
|
|
119
|
+
console.log(`- list_add: ${listAddResult ? '✅ 成功' : '❌ 失败'}`);
|
|
120
|
+
|
|
121
|
+
// 测试list_has
|
|
122
|
+
const listHasResult = await rs.list_has(listKey, "item2");
|
|
123
|
+
console.log(`- list_has: ${typeof listHasResult === 'boolean' ? '✅ 成功' : '❌ 失败'}`, listHasResult);
|
|
124
|
+
|
|
125
|
+
// 测试list_clear
|
|
126
|
+
const listClearResult = await rs.list_clear(listKey);
|
|
127
|
+
console.log(`- list_clear: ${listClearResult ? '✅ 成功' : '❌ 失败'}`);
|
|
128
|
+
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.error('列表操作方法测试失败:', error);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function testHashMethods(rs) {
|
|
135
|
+
try {
|
|
136
|
+
// 测试哈希表方法
|
|
137
|
+
const hashKey = 'hash_test_key';
|
|
138
|
+
|
|
139
|
+
console.log('哈希表方法测试结果:');
|
|
140
|
+
|
|
141
|
+
// 测试hset
|
|
142
|
+
const hsetResult = await rs.hset(hashKey, 'field1', 'value1');
|
|
143
|
+
console.log(`- hset: ${typeof hsetResult !== 'undefined' ? '✅ 可用' : '❌ 不可用'}`);
|
|
144
|
+
|
|
145
|
+
// 测试hget
|
|
146
|
+
const hgetResult = await rs.hget(hashKey, 'field1');
|
|
147
|
+
console.log(`- hget: ${hgetResult === 'value1' ? '✅ 可用' : '❌ 不可用'}`);
|
|
148
|
+
|
|
149
|
+
// 测试hmset
|
|
150
|
+
const hmsetResult = await rs.hmset(hashKey, {field2: 'value2', field3: 'value3'});
|
|
151
|
+
console.log(`- hmset: ${typeof hmsetResult !== 'undefined' ? '✅ 可用' : '❌ 不可用'}`);
|
|
152
|
+
|
|
153
|
+
// 测试hgetall
|
|
154
|
+
const hgetallResult = await rs.hgetall(hashKey);
|
|
155
|
+
console.log(`- hgetall: ${typeof hgetallResult === 'object' ? '✅ 可用' : '❌ 不可用'}`);
|
|
156
|
+
|
|
157
|
+
// 测试hdel
|
|
158
|
+
const hdelResult = await rs.hdel(hashKey, 'field1');
|
|
159
|
+
console.log(`- hdel: ${typeof hdelResult !== 'undefined' ? '✅ 可用' : '❌ 不可用'}`);
|
|
160
|
+
|
|
161
|
+
// 测试hlen
|
|
162
|
+
const hlenResult = await rs.hlen(hashKey);
|
|
163
|
+
console.log(`- hlen: ${typeof hlenResult === 'number' ? '✅ 可用' : '❌ 不可用'}`);
|
|
164
|
+
|
|
165
|
+
} catch (error) {
|
|
166
|
+
console.error('哈希表方法测试失败:', error);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
verifyCompatibility();
|
|
171
|
+
|
|
172
|
+
setTimeout(() => {
|
|
173
|
+
console.error('验证超时');
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}, 15000); // 延长超时时间
|