mm_cache 1.4.1 → 1.4.3
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 +259 -259
- package/compatibility_table.md +2 -2
- package/index.js +74 -114
- package/package.json +9 -9
- package/test.js +8 -8
package/README.md
CHANGED
|
@@ -1,260 +1,260 @@
|
|
|
1
|
-
# mm_cache
|
|
2
|
-
|
|
3
|
-
## 项目信息
|
|
4
|
-
|
|
5
|
-
- **当前版本**: 1.4.
|
|
6
|
-
- **更新日期**:
|
|
7
|
-
- **仓库地址**: [https://gitee.com/qiuwenwu/mm_cache](https://gitee.com/qiuwenwu/mm_cache)
|
|
8
|
-
- **Node.js版本要求**: >=14.0.0,推荐16.0.0及以上
|
|
9
|
-
|
|
10
|
-
## 简介
|
|
11
|
-
|
|
12
|
-
mm_cache是一个统一的缓存操作框架,为多种缓存方式(Redis、MongoDB、CacheBase、Memory)提供统一的API接口,实现无缝切换和兼容。本模块作为上层抽象,整合了多种缓存实现,让开发者可以使用统一的方式操作不同的缓存系统。
|
|
13
|
-
|
|
14
|
-
## 特点
|
|
15
|
-
|
|
16
|
-
- **统一API接口**:为Redis、MongoDB、CacheBase、Memory提供完全一致的接口
|
|
17
|
-
- **无缝切换**:支持在不同缓存实现之间快速切换,无需修改业务代码
|
|
18
|
-
- **完整的方法支持**:包括核心缓存方法、原子操作、字符串操作、批量操作、过期时间操作、键操作、哈希表操作、数组/列表操作等
|
|
19
|
-
- **高兼容性**:所有缓存方式支持相同的参数格式和返回值类型
|
|
20
|
-
- **灵活配置**:支持多种配置方式,适应不同的应用场景
|
|
21
|
-
- **一致性保证**:确保不同缓存实现的行为一致性,特别是在原子操作和过期时间处理方面
|
|
22
|
-
|
|
23
|
-
## 安装
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
npm install mm_cache
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## 使用方法
|
|
30
|
-
|
|
31
|
-
### 基础用法
|
|
32
|
-
|
|
33
|
-
```javascript
|
|
34
|
-
const { Cache } = require('mm_cache');
|
|
35
|
-
|
|
36
|
-
// 初始化Redis缓存
|
|
37
|
-
const redisCache = new Cache({
|
|
38
|
-
|
|
39
|
-
redis: {
|
|
40
|
-
host: '127.0.0.1',
|
|
41
|
-
port: 6379,
|
|
42
|
-
password: 'your_password',
|
|
43
|
-
db: 0
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
// 初始化MongoDB缓存
|
|
48
|
-
const mongodbCache = new Cache({
|
|
49
|
-
|
|
50
|
-
mongodb: {
|
|
51
|
-
url: 'mongodb://localhost:27017',
|
|
52
|
-
database: 'cache_db',
|
|
53
|
-
collection: 'cache_collection'
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
// 初始化CacheBase缓存
|
|
58
|
-
const cacheBaseCache = new Cache({
|
|
59
|
-
|
|
60
|
-
cachebase: {
|
|
61
|
-
enabled: true,
|
|
62
|
-
cache_dir: './cache'
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// 初始化Memory缓存
|
|
67
|
-
const memoryCache = new Cache({
|
|
68
|
-
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// 使用统一的API操作不同的缓存
|
|
72
|
-
async function testCache(cache) {
|
|
73
|
-
// 设置缓存
|
|
74
|
-
await cache.set('key', 'value');
|
|
75
|
-
|
|
76
|
-
// 获取缓存
|
|
77
|
-
const value = await cache.get('key');
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
// 删除缓存
|
|
81
|
-
await cache.del('key');
|
|
82
|
-
|
|
83
|
-
// 检查缓存是否存在
|
|
84
|
-
const exists = await cache.has('key');
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// 使用Redis缓存
|
|
89
|
-
await testCache(redisCache);
|
|
90
|
-
|
|
91
|
-
// 使用MongoDB缓存(无需修改代码)
|
|
92
|
-
await testCache(mongodbCache);
|
|
93
|
-
|
|
94
|
-
// 使用CacheBase缓存(无需修改代码)
|
|
95
|
-
await testCache(cacheBaseCache);
|
|
96
|
-
|
|
97
|
-
// 使用Memory缓存(无需修改代码)
|
|
98
|
-
await testCache(memoryCache);
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### 高级用法
|
|
102
|
-
|
|
103
|
-
#### 设置过期时间
|
|
104
|
-
|
|
105
|
-
```javascript
|
|
106
|
-
// 设置缓存并设置过期时间为60秒
|
|
107
|
-
await cache.set('key', 'value', 60);
|
|
108
|
-
|
|
109
|
-
// 为已存在的键设置过期时间
|
|
110
|
-
await cache.expire('key', 60);
|
|
111
|
-
|
|
112
|
-
// 移除过期时间
|
|
113
|
-
await cache.persist('key');
|
|
114
|
-
|
|
115
|
-
// 获取剩余过期时间
|
|
116
|
-
const ttl = await cache.ttl('key');
|
|
117
|
-
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
#### 原子操作
|
|
121
|
-
|
|
122
|
-
```javascript
|
|
123
|
-
// 原子递增
|
|
124
|
-
const newValue = await cache.incr('counter');
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
// 增加指定整数值
|
|
128
|
-
const result = await cache.incrby('counter', 10);
|
|
129
|
-
|
|
130
|
-
// 增加指定浮点数值
|
|
131
|
-
const floatResult = await cache.incrbyfloat('counter', 0.5);
|
|
132
|
-
|
|
133
|
-
// 减少指定整数值
|
|
134
|
-
const decrResult = await cache.decrby('counter', 5);
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
#### 哈希表操作
|
|
138
|
-
|
|
139
|
-
```javascript
|
|
140
|
-
// 设置哈希表字段
|
|
141
|
-
await cache.hset('user:1', 'name', '张三');
|
|
142
|
-
await cache.hset('user:1', 'age', 25);
|
|
143
|
-
|
|
144
|
-
// 获取哈希表字段
|
|
145
|
-
const name = await cache.hget('user:1', 'name');
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
// 获取所有哈希表字段
|
|
149
|
-
const user = await cache.hgetall('user:1');
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
// 批量设置哈希表字段
|
|
153
|
-
await cache.hmset('user:2', {
|
|
154
|
-
name: '李四',
|
|
155
|
-
age: 30,
|
|
156
|
-
email: 'lisi@example.com'
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
// 批量获取哈希表字段
|
|
160
|
-
const values = await cache.hmget('user:2', ['name', 'age']);
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
// 删除哈希表字段
|
|
164
|
-
await cache.hdel('user:1', 'age');
|
|
165
|
-
|
|
166
|
-
// 获取哈希表字段数量
|
|
167
|
-
const count = await cache.hlen('user:1');
|
|
168
|
-
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
#### 数组/列表操作
|
|
172
|
-
|
|
173
|
-
```javascript
|
|
174
|
-
// 设置列表
|
|
175
|
-
await cache.setForList('users', ['张三', '李四', '王五']);
|
|
176
|
-
|
|
177
|
-
// 向列表添加元素
|
|
178
|
-
await cache.addForList('users', '赵六');
|
|
179
|
-
|
|
180
|
-
// 检查元素是否在列表中
|
|
181
|
-
const exists = await cache.hasForList('users', '李四');
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
// 获取列表元素(支持分页)
|
|
185
|
-
const users = await cache.getForList('users', 0, 2);
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
// 清空列表
|
|
189
|
-
await cache.clearForList('users');
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
## 方法兼容性
|
|
193
|
-
|
|
194
|
-
mm_cache确保所有支持的缓存方式(Redis、MongoDB、CacheBase、Memory)都实现了相同的API接口,具体兼容性情况请参考项目中的`compatibility_table.md`文件。
|
|
195
|
-
|
|
196
|
-
## 配置说明
|
|
197
|
-
|
|
198
|
-
### 全局配置选项
|
|
199
|
-
|
|
200
|
-
```javascript
|
|
201
|
-
const cache = new Cache({
|
|
202
|
-
// 缓存方式: redis, mongodb, cachebase, memory
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
// Redis配置
|
|
206
|
-
redis: {
|
|
207
|
-
host: '127.0.0.1',
|
|
208
|
-
port: 6379,
|
|
209
|
-
password: 'your_password',
|
|
210
|
-
db: 0
|
|
211
|
-
},
|
|
212
|
-
|
|
213
|
-
// MongoDB配置
|
|
214
|
-
mongodb: {
|
|
215
|
-
url: 'mongodb://localhost:27017',
|
|
216
|
-
database: 'cache_db',
|
|
217
|
-
collection: 'cache_collection'
|
|
218
|
-
},
|
|
219
|
-
|
|
220
|
-
// CacheBase配置
|
|
221
|
-
cachebase: {
|
|
222
|
-
enabled: true,
|
|
223
|
-
cache_dir: './cache',
|
|
224
|
-
file_ext: '.cache.json',
|
|
225
|
-
memory_limit: 5000,
|
|
226
|
-
save_interval: 5000,
|
|
227
|
-
file_mode: 384
|
|
228
|
-
}
|
|
229
|
-
});
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
## 贡献指南
|
|
233
|
-
|
|
234
|
-
1. **Fork项目**:在Gitee上Fork本项目到您的账户
|
|
235
|
-
2. **创建分支**:在您的仓库中创建功能分支
|
|
236
|
-
3. **提交修改**:提交您的代码修改和详细的提交信息
|
|
237
|
-
4. **运行测试**:确保所有测试通过
|
|
238
|
-
5. **发起PR**:向原项目提交Pull Request,描述您的修改内容和目的
|
|
239
|
-
|
|
240
|
-
## 问题反馈
|
|
241
|
-
|
|
242
|
-
如有任何问题或建议,请通过以下方式联系我们:
|
|
243
|
-
|
|
244
|
-
- **Gitee Issues**: [https://gitee.com/qiuwenwu/mm_cache/issues](https://gitee.com/qiuwenwu/mm_cache/issues)
|
|
245
|
-
- **NPM**: [https://www.npmjs.com/package/mm_cache](https://www.npmjs.com/package/mm_cache)
|
|
246
|
-
|
|
247
|
-
## 鸣谢
|
|
248
|
-
|
|
249
|
-
感谢以下项目和工具对本模块的支持:
|
|
250
|
-
|
|
251
|
-
- [Node.js](https://nodejs.org/)
|
|
252
|
-
- [Redis](https://redis.io/)
|
|
253
|
-
- [MongoDB](https://www.mongodb.com/)
|
|
254
|
-
- [mm_cachebase](https://www.npmjs.com/package/mm_cachebase)
|
|
255
|
-
- [mm_mongodb](https://www.npmjs.com/package/mm_mongodb)
|
|
256
|
-
- [mm_redis](https://www.npmjs.com/package/mm_redis)
|
|
257
|
-
|
|
258
|
-
## 许可证
|
|
259
|
-
|
|
1
|
+
# mm_cache
|
|
2
|
+
|
|
3
|
+
## 项目信息
|
|
4
|
+
|
|
5
|
+
- **当前版本**: 1.4.2
|
|
6
|
+
- **更新日期**: 2025-11-17
|
|
7
|
+
- **仓库地址**: [https://gitee.com/qiuwenwu/mm_cache](https://gitee.com/qiuwenwu/mm_cache)
|
|
8
|
+
- **Node.js版本要求**: >=14.0.0,推荐16.0.0及以上
|
|
9
|
+
|
|
10
|
+
## 简介
|
|
11
|
+
|
|
12
|
+
mm_cache是一个统一的缓存操作框架,为多种缓存方式(Redis、MongoDB、CacheBase、Memory)提供统一的API接口,实现无缝切换和兼容。本模块作为上层抽象,整合了多种缓存实现,让开发者可以使用统一的方式操作不同的缓存系统。
|
|
13
|
+
|
|
14
|
+
## 特点
|
|
15
|
+
|
|
16
|
+
- **统一API接口**:为Redis、MongoDB、CacheBase、Memory提供完全一致的接口
|
|
17
|
+
- **无缝切换**:支持在不同缓存实现之间快速切换,无需修改业务代码
|
|
18
|
+
- **完整的方法支持**:包括核心缓存方法、原子操作、字符串操作、批量操作、过期时间操作、键操作、哈希表操作、数组/列表操作等
|
|
19
|
+
- **高兼容性**:所有缓存方式支持相同的参数格式和返回值类型
|
|
20
|
+
- **灵活配置**:支持多种配置方式,适应不同的应用场景
|
|
21
|
+
- **一致性保证**:确保不同缓存实现的行为一致性,特别是在原子操作和过期时间处理方面
|
|
22
|
+
|
|
23
|
+
## 安装
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install mm_cache
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 使用方法
|
|
30
|
+
|
|
31
|
+
### 基础用法
|
|
32
|
+
|
|
33
|
+
```javascript
|
|
34
|
+
const { Cache } = require('mm_cache');
|
|
35
|
+
|
|
36
|
+
// 初始化Redis缓存
|
|
37
|
+
const redisCache = new Cache({
|
|
38
|
+
way: 'redis',
|
|
39
|
+
redis: {
|
|
40
|
+
host: '127.0.0.1',
|
|
41
|
+
port: 6379,
|
|
42
|
+
password: 'your_password',
|
|
43
|
+
db: 0
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// 初始化MongoDB缓存
|
|
48
|
+
const mongodbCache = new Cache({
|
|
49
|
+
way: 'mongodb',
|
|
50
|
+
mongodb: {
|
|
51
|
+
url: 'mongodb://localhost:27017',
|
|
52
|
+
database: 'cache_db',
|
|
53
|
+
collection: 'cache_collection'
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// 初始化CacheBase缓存
|
|
58
|
+
const cacheBaseCache = new Cache({
|
|
59
|
+
way: 'cachebase',
|
|
60
|
+
cachebase: {
|
|
61
|
+
enabled: true,
|
|
62
|
+
cache_dir: './cache'
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// 初始化Memory缓存
|
|
67
|
+
const memoryCache = new Cache({
|
|
68
|
+
way: 'memory'
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// 使用统一的API操作不同的缓存
|
|
72
|
+
async function testCache(cache) {
|
|
73
|
+
// 设置缓存
|
|
74
|
+
await cache.set('key', 'value');
|
|
75
|
+
|
|
76
|
+
// 获取缓存
|
|
77
|
+
const value = await cache.get('key');
|
|
78
|
+
$.log.debug(value); // 'value'
|
|
79
|
+
|
|
80
|
+
// 删除缓存
|
|
81
|
+
await cache.del('key');
|
|
82
|
+
|
|
83
|
+
// 检查缓存是否存在
|
|
84
|
+
const exists = await cache.has('key');
|
|
85
|
+
$.log.debug(exists); // false
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// 使用Redis缓存
|
|
89
|
+
await testCache(redisCache);
|
|
90
|
+
|
|
91
|
+
// 使用MongoDB缓存(无需修改代码)
|
|
92
|
+
await testCache(mongodbCache);
|
|
93
|
+
|
|
94
|
+
// 使用CacheBase缓存(无需修改代码)
|
|
95
|
+
await testCache(cacheBaseCache);
|
|
96
|
+
|
|
97
|
+
// 使用Memory缓存(无需修改代码)
|
|
98
|
+
await testCache(memoryCache);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 高级用法
|
|
102
|
+
|
|
103
|
+
#### 设置过期时间
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
// 设置缓存并设置过期时间为60秒
|
|
107
|
+
await cache.set('key', 'value', 60);
|
|
108
|
+
|
|
109
|
+
// 为已存在的键设置过期时间
|
|
110
|
+
await cache.expire('key', 60);
|
|
111
|
+
|
|
112
|
+
// 移除过期时间
|
|
113
|
+
await cache.persist('key');
|
|
114
|
+
|
|
115
|
+
// 获取剩余过期时间
|
|
116
|
+
const ttl = await cache.ttl('key');
|
|
117
|
+
$.log.debug(ttl); // 剩余过期时间(秒),-1表示无过期时间,-2表示键不存在
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### 原子操作
|
|
121
|
+
|
|
122
|
+
```javascript
|
|
123
|
+
// 原子递增
|
|
124
|
+
const newValue = await cache.incr('counter');
|
|
125
|
+
$.log.debug(newValue); // 1, 2, 3...
|
|
126
|
+
|
|
127
|
+
// 增加指定整数值
|
|
128
|
+
const result = await cache.incrby('counter', 10);
|
|
129
|
+
|
|
130
|
+
// 增加指定浮点数值
|
|
131
|
+
const floatResult = await cache.incrbyfloat('counter', 0.5);
|
|
132
|
+
|
|
133
|
+
// 减少指定整数值
|
|
134
|
+
const decrResult = await cache.decrby('counter', 5);
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
#### 哈希表操作
|
|
138
|
+
|
|
139
|
+
```javascript
|
|
140
|
+
// 设置哈希表字段
|
|
141
|
+
await cache.hset('user:1', 'name', '张三');
|
|
142
|
+
await cache.hset('user:1', 'age', 25);
|
|
143
|
+
|
|
144
|
+
// 获取哈希表字段
|
|
145
|
+
const name = await cache.hget('user:1', 'name');
|
|
146
|
+
$.log.debug(name); // '张三'
|
|
147
|
+
|
|
148
|
+
// 获取所有哈希表字段
|
|
149
|
+
const user = await cache.hgetall('user:1');
|
|
150
|
+
$.log.debug(user); // { name: '张三', age: '25' }
|
|
151
|
+
|
|
152
|
+
// 批量设置哈希表字段
|
|
153
|
+
await cache.hmset('user:2', {
|
|
154
|
+
name: '李四',
|
|
155
|
+
age: 30,
|
|
156
|
+
email: 'lisi@example.com'
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// 批量获取哈希表字段
|
|
160
|
+
const values = await cache.hmget('user:2', ['name', 'age']);
|
|
161
|
+
$.log.debug(values); // ['李四', '30']
|
|
162
|
+
|
|
163
|
+
// 删除哈希表字段
|
|
164
|
+
await cache.hdel('user:1', 'age');
|
|
165
|
+
|
|
166
|
+
// 获取哈希表字段数量
|
|
167
|
+
const count = await cache.hlen('user:1');
|
|
168
|
+
$.log.debug(count); // 1
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### 数组/列表操作
|
|
172
|
+
|
|
173
|
+
```javascript
|
|
174
|
+
// 设置列表
|
|
175
|
+
await cache.setForList('users', ['张三', '李四', '王五']);
|
|
176
|
+
|
|
177
|
+
// 向列表添加元素
|
|
178
|
+
await cache.addForList('users', '赵六');
|
|
179
|
+
|
|
180
|
+
// 检查元素是否在列表中
|
|
181
|
+
const exists = await cache.hasForList('users', '李四');
|
|
182
|
+
$.log.debug(exists); // true
|
|
183
|
+
|
|
184
|
+
// 获取列表元素(支持分页)
|
|
185
|
+
const users = await cache.getForList('users', 0, 2);
|
|
186
|
+
$.log.debug(users); // ['张三', '李四', '王五']
|
|
187
|
+
|
|
188
|
+
// 清空列表
|
|
189
|
+
await cache.clearForList('users');
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## 方法兼容性
|
|
193
|
+
|
|
194
|
+
mm_cache确保所有支持的缓存方式(Redis、MongoDB、CacheBase、Memory)都实现了相同的API接口,具体兼容性情况请参考项目中的`compatibility_table.md`文件。
|
|
195
|
+
|
|
196
|
+
## 配置说明
|
|
197
|
+
|
|
198
|
+
### 全局配置选项
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
const cache = new Cache({
|
|
202
|
+
// 缓存方式: redis, mongodb, cachebase, memory
|
|
203
|
+
way: 'redis',
|
|
204
|
+
|
|
205
|
+
// Redis配置
|
|
206
|
+
redis: {
|
|
207
|
+
host: '127.0.0.1',
|
|
208
|
+
port: 6379,
|
|
209
|
+
password: 'your_password',
|
|
210
|
+
db: 0
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
// MongoDB配置
|
|
214
|
+
mongodb: {
|
|
215
|
+
url: 'mongodb://localhost:27017',
|
|
216
|
+
database: 'cache_db',
|
|
217
|
+
collection: 'cache_collection'
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
// CacheBase配置
|
|
221
|
+
cachebase: {
|
|
222
|
+
enabled: true,
|
|
223
|
+
cache_dir: './cache',
|
|
224
|
+
file_ext: '.cache.json',
|
|
225
|
+
memory_limit: 5000,
|
|
226
|
+
save_interval: 5000,
|
|
227
|
+
file_mode: 384
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## 贡献指南
|
|
233
|
+
|
|
234
|
+
1. **Fork项目**:在Gitee上Fork本项目到您的账户
|
|
235
|
+
2. **创建分支**:在您的仓库中创建功能分支
|
|
236
|
+
3. **提交修改**:提交您的代码修改和详细的提交信息
|
|
237
|
+
4. **运行测试**:确保所有测试通过
|
|
238
|
+
5. **发起PR**:向原项目提交Pull Request,描述您的修改内容和目的
|
|
239
|
+
|
|
240
|
+
## 问题反馈
|
|
241
|
+
|
|
242
|
+
如有任何问题或建议,请通过以下方式联系我们:
|
|
243
|
+
|
|
244
|
+
- **Gitee Issues**: [https://gitee.com/qiuwenwu/mm_cache/issues](https://gitee.com/qiuwenwu/mm_cache/issues)
|
|
245
|
+
- **NPM**: [https://www.npmjs.com/package/mm_cache](https://www.npmjs.com/package/mm_cache)
|
|
246
|
+
|
|
247
|
+
## 鸣谢
|
|
248
|
+
|
|
249
|
+
感谢以下项目和工具对本模块的支持:
|
|
250
|
+
|
|
251
|
+
- [Node.js](https://nodejs.org/)
|
|
252
|
+
- [Redis](https://redis.io/)
|
|
253
|
+
- [MongoDB](https://www.mongodb.com/)
|
|
254
|
+
- [mm_cachebase](https://www.npmjs.com/package/mm_cachebase)
|
|
255
|
+
- [mm_mongodb](https://www.npmjs.com/package/mm_mongodb)
|
|
256
|
+
- [mm_redis](https://www.npmjs.com/package/mm_redis)
|
|
257
|
+
|
|
258
|
+
## 许可证
|
|
259
|
+
|
|
260
260
|
本项目使用ISC许可证 - 详情请查看 [LICENSE](LICENSE) 文件
|
package/compatibility_table.md
CHANGED
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
|
|
43
43
|
| 方法名 | Redis | MongoDB | CacheBase | Memory | 状态说明 |
|
|
44
44
|
|-------|-------|---------|-----------|--------|----------|
|
|
45
|
-
| expire | ✅ | ✅ |
|
|
46
|
-
| persist | ✅ | ✅ |
|
|
45
|
+
| expire | ✅ | ✅ | ✅ | ✅ | 所有方式功能实现效果相同,参数类型和返回值一致 |
|
|
46
|
+
| persist | ✅ | ✅ | ✅ | ✅ | 所有方式均正常工作 |
|
|
47
47
|
|
|
48
48
|
## 键操作方法
|
|
49
49
|
|
package/index.js
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
* @version 1.2
|
|
5
5
|
*/
|
|
6
6
|
const EventEmitter = require('events');
|
|
7
|
-
require('
|
|
7
|
+
const { Base } = require('mm_expand');
|
|
8
8
|
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
10
|
* @class 缓存类
|
|
11
11
|
*/
|
|
12
|
-
class Cache extends
|
|
12
|
+
class Cache extends Base {
|
|
13
13
|
/**
|
|
14
14
|
* @description 创建Cache帮助类函数 (构造函数)
|
|
15
15
|
* @param {String} scope 作用域
|
|
@@ -57,27 +57,15 @@ class Cache extends EventEmitter {
|
|
|
57
57
|
// 数据库名
|
|
58
58
|
database: "mm",
|
|
59
59
|
// 用户名
|
|
60
|
-
user: "
|
|
60
|
+
user: "",
|
|
61
61
|
// 密码
|
|
62
62
|
password: "",
|
|
63
|
-
// 连接选项
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// 连接超时时间
|
|
70
|
-
connectTimeoutMS: 10000,
|
|
71
|
-
// 服务器选择超时
|
|
72
|
-
serverSelectionTimeoutMS: 5000,
|
|
73
|
-
// 重试策略
|
|
74
|
-
retryWrites: true
|
|
75
|
-
},
|
|
76
|
-
// 重试配置
|
|
77
|
-
retry: {
|
|
78
|
-
maxAttempts: 3,
|
|
79
|
-
delayMS: 1000
|
|
80
|
-
}
|
|
63
|
+
// 连接选项 (MongoDB驱动7.x版本支持的参数)
|
|
64
|
+
min_pool_size: 10,
|
|
65
|
+
max_pool_size: 100,
|
|
66
|
+
connect_timeout_ms: 10000,
|
|
67
|
+
server_selection_timeout_ms: 5000,
|
|
68
|
+
retry_writes: true
|
|
81
69
|
}
|
|
82
70
|
};
|
|
83
71
|
// 作用域
|
|
@@ -100,9 +88,9 @@ class Cache extends EventEmitter {
|
|
|
100
88
|
* @description 设置配置
|
|
101
89
|
* @param {Object} config 配置
|
|
102
90
|
*/
|
|
103
|
-
Cache.prototype.setConfig = function(config) {
|
|
91
|
+
Cache.prototype.setConfig = function (config) {
|
|
104
92
|
if (config) {
|
|
105
|
-
|
|
93
|
+
$.push(this.config, config);
|
|
106
94
|
}
|
|
107
95
|
};
|
|
108
96
|
|
|
@@ -110,7 +98,7 @@ Cache.prototype.setConfig = function(config) {
|
|
|
110
98
|
* @description 获取当前缓存方式
|
|
111
99
|
* @return {String} 缓存方式
|
|
112
100
|
*/
|
|
113
|
-
Cache.prototype.getCacheWay = function() {
|
|
101
|
+
Cache.prototype.getCacheWay = function () {
|
|
114
102
|
return this.config.way;
|
|
115
103
|
};
|
|
116
104
|
|
|
@@ -118,7 +106,7 @@ Cache.prototype.getCacheWay = function() {
|
|
|
118
106
|
* @description 连接缓存数据库
|
|
119
107
|
* @return {Promise<Boolean>} 是否连接成功
|
|
120
108
|
*/
|
|
121
|
-
Cache.prototype.connect = async function() {
|
|
109
|
+
Cache.prototype.connect = async function () {
|
|
122
110
|
// 关闭现有连接
|
|
123
111
|
this.dispose();
|
|
124
112
|
|
|
@@ -127,9 +115,9 @@ Cache.prototype.connect = async function() {
|
|
|
127
115
|
case 'redis': {
|
|
128
116
|
try {
|
|
129
117
|
const {
|
|
130
|
-
|
|
118
|
+
redisAdmin
|
|
131
119
|
} = require('mm_redis');
|
|
132
|
-
this.db =
|
|
120
|
+
this.db = redisAdmin(this.config.scope, this.config.redis);
|
|
133
121
|
if (!this.db.connected) {
|
|
134
122
|
await this.db.open();
|
|
135
123
|
}
|
|
@@ -144,9 +132,9 @@ Cache.prototype.connect = async function() {
|
|
|
144
132
|
case 'mongodb': {
|
|
145
133
|
try {
|
|
146
134
|
const {
|
|
147
|
-
|
|
135
|
+
mongodbAdmin
|
|
148
136
|
} = require('mm_mongodb');
|
|
149
|
-
this.db =
|
|
137
|
+
this.db = mongodbAdmin(this.config.scope, this.config.mongodb);
|
|
150
138
|
if (!this.db.connected) {
|
|
151
139
|
await this.db.open();
|
|
152
140
|
}
|
|
@@ -161,9 +149,9 @@ Cache.prototype.connect = async function() {
|
|
|
161
149
|
case 'cachebase':
|
|
162
150
|
try {
|
|
163
151
|
const {
|
|
164
|
-
|
|
152
|
+
cachebaseAdmin
|
|
165
153
|
} = require('mm_cachebase');
|
|
166
|
-
this.db =
|
|
154
|
+
this.db = cachebaseAdmin(this.config.scope, this.config.cachebase);
|
|
167
155
|
} catch (e) {
|
|
168
156
|
$.log.error('[Cache] [connect] CacheBase模块加载失败,无法初始化缓存:', e.message);
|
|
169
157
|
return false;
|
|
@@ -173,9 +161,9 @@ Cache.prototype.connect = async function() {
|
|
|
173
161
|
default: {
|
|
174
162
|
try {
|
|
175
163
|
const {
|
|
176
|
-
|
|
164
|
+
cachebaseAdmin
|
|
177
165
|
} = require('mm_cachebase');
|
|
178
|
-
this.db =
|
|
166
|
+
this.db = cachebaseAdmin('default');
|
|
179
167
|
} catch (e) {
|
|
180
168
|
$.log.error('[Cache] [connect] CacheBase模块加载失败,无法初始化缓存:', e.message);
|
|
181
169
|
return false;
|
|
@@ -198,7 +186,7 @@ Cache.prototype.connect = async function() {
|
|
|
198
186
|
* @param {Object} config 可选配置
|
|
199
187
|
* @return {Promise<Boolean>} 是否成功
|
|
200
188
|
*/
|
|
201
|
-
Cache.prototype.switchCache = async function(way, config) {
|
|
189
|
+
Cache.prototype.switchCache = async function (way, config) {
|
|
202
190
|
if (['cachebase', 'redis', 'mongodb', 'memory'].includes(way)) {
|
|
203
191
|
this.config.way = way;
|
|
204
192
|
if (config) {
|
|
@@ -214,7 +202,7 @@ Cache.prototype.switchCache = async function(way, config) {
|
|
|
214
202
|
* @param {String} pattern 匹配模式
|
|
215
203
|
* @return {Promise<Array>} 键名数组
|
|
216
204
|
*/
|
|
217
|
-
Cache.prototype.keys = async function(pattern) {
|
|
205
|
+
Cache.prototype.keys = async function (pattern) {
|
|
218
206
|
// 添加作用域前缀
|
|
219
207
|
const scopePattern = pattern ? `${this.scope}:${pattern}` : `${this.scope}:*`;
|
|
220
208
|
// 直接调用底层keys方法
|
|
@@ -226,7 +214,7 @@ Cache.prototype.keys = async function(pattern) {
|
|
|
226
214
|
* @param {String} key 键名
|
|
227
215
|
* @return {Promise<Boolean>} 是否存在
|
|
228
216
|
*/
|
|
229
|
-
Cache.prototype.has = async function(key) {
|
|
217
|
+
Cache.prototype.has = async function (key) {
|
|
230
218
|
// 添加作用域前缀
|
|
231
219
|
const scopeKey = `${this.scope}:${key}`;
|
|
232
220
|
// 优先使用has方法,如果不存在则使用exists
|
|
@@ -243,7 +231,7 @@ Cache.prototype.has = async function(key) {
|
|
|
243
231
|
* @param {Array} args 参数数组
|
|
244
232
|
* @return {Promise<any>} 方法返回值
|
|
245
233
|
*/
|
|
246
|
-
Cache.prototype._safeCall = async function(method, args = []) {
|
|
234
|
+
Cache.prototype._safeCall = async function (method, args = []) {
|
|
247
235
|
if (!this.db) {
|
|
248
236
|
// 如果未连接,自动尝试连接
|
|
249
237
|
await this.connect();
|
|
@@ -258,7 +246,7 @@ Cache.prototype._safeCall = async function(method, args = []) {
|
|
|
258
246
|
return await this.db[method](...args);
|
|
259
247
|
}
|
|
260
248
|
|
|
261
|
-
//
|
|
249
|
+
// 降级处理:仅为确实不存在的方法提供内置实现
|
|
262
250
|
switch (method) {
|
|
263
251
|
case 'strlen': {
|
|
264
252
|
const key = args[0];
|
|
@@ -306,39 +294,6 @@ Cache.prototype._safeCall = async function(method, args = []) {
|
|
|
306
294
|
}
|
|
307
295
|
return 'string';
|
|
308
296
|
}
|
|
309
|
-
case 'incrby': {
|
|
310
|
-
const [key, value] = args;
|
|
311
|
-
// 降级为addInt方法
|
|
312
|
-
return await this.db.addInt(key, value);
|
|
313
|
-
}
|
|
314
|
-
case 'decrby': {
|
|
315
|
-
const [key, value] = args;
|
|
316
|
-
// 降级为addInt方法,使用负值
|
|
317
|
-
return await this.db.addInt(key, -value);
|
|
318
|
-
}
|
|
319
|
-
case 'incrbyfloat': {
|
|
320
|
-
const [key, value] = args;
|
|
321
|
-
// 降级为addFloat方法
|
|
322
|
-
return await this.db.addFloat(key, value);
|
|
323
|
-
}
|
|
324
|
-
case 'mget': {
|
|
325
|
-
// 直接使用参数数组,不做额外处理
|
|
326
|
-
try {
|
|
327
|
-
// 并行获取多个键的值
|
|
328
|
-
const promises = args.map(async (key) => {
|
|
329
|
-
try {
|
|
330
|
-
return await this.db.get(key);
|
|
331
|
-
} catch (error) {
|
|
332
|
-
$.log.error(`[Cache] [_safeCall] mget获取键[${key}]失败:`, error);
|
|
333
|
-
return null;
|
|
334
|
-
}
|
|
335
|
-
});
|
|
336
|
-
return await Promise.all(promises);
|
|
337
|
-
} catch (error) {
|
|
338
|
-
$.log.error(`[Cache] [_safeCall] mget操作失败:`, error);
|
|
339
|
-
return [];
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
297
|
default:
|
|
343
298
|
// 如果方法不存在且没有降级实现,返回null
|
|
344
299
|
$.log.warn(`[Cache] [_safeCall] 不支持的方法: ${method}`);
|
|
@@ -353,7 +308,7 @@ Cache.prototype._safeCall = async function(method, args = []) {
|
|
|
353
308
|
* @param {Number} seconds 秒
|
|
354
309
|
* @return {Promise<Boolean>} 操作结果
|
|
355
310
|
*/
|
|
356
|
-
Cache.prototype.add = async function(key, value, expire) {
|
|
311
|
+
Cache.prototype.add = async function (key, value, expire) {
|
|
357
312
|
// 添加作用域前缀
|
|
358
313
|
const scopeKey = `${this.scope}:${key}`;
|
|
359
314
|
// 直接调用底层存储的原生add方法
|
|
@@ -367,7 +322,7 @@ Cache.prototype.add = async function(key, value, expire) {
|
|
|
367
322
|
* @param {Number} expire 过期时间(秒),默认不设置过期时间
|
|
368
323
|
* @return {Promise<Boolean>} 是否设置成功
|
|
369
324
|
*/
|
|
370
|
-
Cache.prototype.set = async function(key, value, expire) {
|
|
325
|
+
Cache.prototype.set = async function (key, value, expire) {
|
|
371
326
|
// 添加作用域前缀
|
|
372
327
|
const scopeKey = `${this.scope}:${key}`;
|
|
373
328
|
return await this._safeCall('set', [scopeKey, value, expire]);
|
|
@@ -378,7 +333,7 @@ Cache.prototype.set = async function(key, value, expire) {
|
|
|
378
333
|
* @param {String} key 键名
|
|
379
334
|
* @return {Promise<Any>} 缓存值
|
|
380
335
|
*/
|
|
381
|
-
Cache.prototype.get = async function(key) {
|
|
336
|
+
Cache.prototype.get = async function (key) {
|
|
382
337
|
// 添加作用域前缀
|
|
383
338
|
const scopeKey = `${this.scope}:${key}`;
|
|
384
339
|
return await this._safeCall('get', [scopeKey]);
|
|
@@ -389,7 +344,7 @@ Cache.prototype.get = async function(key) {
|
|
|
389
344
|
* @param {String} key 键名
|
|
390
345
|
* @return {Promise<Boolean>} 是否删除成功
|
|
391
346
|
*/
|
|
392
|
-
Cache.prototype.del = async function(key) {
|
|
347
|
+
Cache.prototype.del = async function (key) {
|
|
393
348
|
// 添加作用域前缀
|
|
394
349
|
const scopeKey = `${this.scope}:${key}`;
|
|
395
350
|
return await this._safeCall('del', [scopeKey]);
|
|
@@ -400,7 +355,7 @@ Cache.prototype.del = async function(key) {
|
|
|
400
355
|
* @param {String} key 键名
|
|
401
356
|
* @return {Promise<Boolean>} 是否存在
|
|
402
357
|
*/
|
|
403
|
-
Cache.prototype.exists = async function(key) {
|
|
358
|
+
Cache.prototype.exists = async function (key) {
|
|
404
359
|
// 添加作用域前缀
|
|
405
360
|
const scopeKey = `${this.scope}:${key}`;
|
|
406
361
|
return await this._safeCall('exists', [scopeKey]);
|
|
@@ -412,7 +367,7 @@ Cache.prototype.exists = async function(key) {
|
|
|
412
367
|
* @param {Number} seconds 过期时间(秒)
|
|
413
368
|
* @return {Promise<Boolean>} 是否设置成功
|
|
414
369
|
*/
|
|
415
|
-
Cache.prototype.expire = async function(key, seconds) {
|
|
370
|
+
Cache.prototype.expire = async function (key, seconds) {
|
|
416
371
|
// 添加作用域前缀
|
|
417
372
|
const scopeKey = `${this.scope}:${key}`;
|
|
418
373
|
return await this._safeCall('expire', [scopeKey, seconds]);
|
|
@@ -424,10 +379,15 @@ Cache.prototype.expire = async function(key, seconds) {
|
|
|
424
379
|
* @param {Number} seconds 过期时间(秒),默认不设置过期时间
|
|
425
380
|
* @return {Promise<Number>} 过期时间(秒),-1表示永不过期,-2表示键不存在
|
|
426
381
|
*/
|
|
427
|
-
Cache.prototype.ttl = async function(key, seconds) {
|
|
382
|
+
Cache.prototype.ttl = async function (key, seconds) {
|
|
428
383
|
// 添加作用域前缀
|
|
429
384
|
const scopeKey = `${this.scope}:${key}`;
|
|
430
|
-
|
|
385
|
+
// 仅在seconds参数存在时才传递给底层方法
|
|
386
|
+
if (seconds !== undefined) {
|
|
387
|
+
return await this._safeCall('ttl', [scopeKey, seconds]);
|
|
388
|
+
} else {
|
|
389
|
+
return await this._safeCall('ttl', [scopeKey]);
|
|
390
|
+
}
|
|
431
391
|
};
|
|
432
392
|
|
|
433
393
|
/**
|
|
@@ -435,7 +395,7 @@ Cache.prototype.ttl = async function(key, seconds) {
|
|
|
435
395
|
* @param {...String} keys 键名列表
|
|
436
396
|
* @return {Array} 值数组,与键的顺序一致
|
|
437
397
|
*/
|
|
438
|
-
Cache.prototype.mget = function() {
|
|
398
|
+
Cache.prototype.mget = function () {
|
|
439
399
|
// 确保返回一个函数,满足测试脚本的检查
|
|
440
400
|
return async (...keys) => {
|
|
441
401
|
try {
|
|
@@ -466,7 +426,7 @@ Cache.prototype.mget = function() {
|
|
|
466
426
|
* @param {Number} step 步长,默认1
|
|
467
427
|
* @return {Promise<Number>} 递增后的值
|
|
468
428
|
*/
|
|
469
|
-
Cache.prototype.incr = async function(key, step = 1) {
|
|
429
|
+
Cache.prototype.incr = async function (key, step = 1) {
|
|
470
430
|
// 添加作用域前缀
|
|
471
431
|
const scopeKey = `${this.scope}:${key}`;
|
|
472
432
|
// 优先使用incr方法,如果不存在则使用addInt
|
|
@@ -483,7 +443,7 @@ Cache.prototype.incr = async function(key, step = 1) {
|
|
|
483
443
|
* @param {Number} step 步长,默认1
|
|
484
444
|
* @return {Promise<Number>} 递增后的值
|
|
485
445
|
*/
|
|
486
|
-
Cache.prototype.addInt = async function(key, step = 1) {
|
|
446
|
+
Cache.prototype.addInt = async function (key, step = 1) {
|
|
487
447
|
// 添加作用域前缀
|
|
488
448
|
const scopeKey = `${this.scope}:${key}`;
|
|
489
449
|
return await this._safeCall('addInt', [scopeKey, step]);
|
|
@@ -495,7 +455,7 @@ Cache.prototype.addInt = async function(key, step = 1) {
|
|
|
495
455
|
* @param {String} value 要追加的字符串
|
|
496
456
|
* @return {Promise<Number>} 追加后的字符串长度
|
|
497
457
|
*/
|
|
498
|
-
Cache.prototype.addStr = async function(key, value) {
|
|
458
|
+
Cache.prototype.addStr = async function (key, value) {
|
|
499
459
|
// 添加作用域前缀
|
|
500
460
|
const scopeKey = `${this.scope}:${key}`;
|
|
501
461
|
return await this._safeCall('addStr', [scopeKey, value]);
|
|
@@ -507,7 +467,7 @@ Cache.prototype.addStr = async function(key, value) {
|
|
|
507
467
|
* @param {Number} step 步长,默认1.0
|
|
508
468
|
* @return {Promise<Number>} 递增后的值
|
|
509
469
|
*/
|
|
510
|
-
Cache.prototype.addFloat = async function(key, step = 1.0) {
|
|
470
|
+
Cache.prototype.addFloat = async function (key, step = 1.0) {
|
|
511
471
|
// 确保step是数字类型
|
|
512
472
|
step = parseFloat(step) || 1.0;
|
|
513
473
|
// 添加作用域前缀
|
|
@@ -522,7 +482,7 @@ Cache.prototype.addFloat = async function(key, step = 1.0) {
|
|
|
522
482
|
* @param {Object} options 配置选项
|
|
523
483
|
* @return {Promise<Number>} 增加后的值
|
|
524
484
|
*/
|
|
525
|
-
Cache.prototype.incrby = async function(key, value, options) {
|
|
485
|
+
Cache.prototype.incrby = async function (key, value, options) {
|
|
526
486
|
// 添加作用域前缀
|
|
527
487
|
const scopeKey = `${this.scope}:${key}`;
|
|
528
488
|
return await this._safeCall('incrby', [scopeKey, value], options);
|
|
@@ -535,7 +495,7 @@ Cache.prototype.incrby = async function(key, value, options) {
|
|
|
535
495
|
* @param {Object} options 配置选项
|
|
536
496
|
* @return {Promise<Number>} 减少后的值
|
|
537
497
|
*/
|
|
538
|
-
Cache.prototype.decrby = async function(key, value, options) {
|
|
498
|
+
Cache.prototype.decrby = async function (key, value, options) {
|
|
539
499
|
// 添加作用域前缀
|
|
540
500
|
const scopeKey = `${this.scope}:${key}`;
|
|
541
501
|
return await this._safeCall('decrby', [scopeKey, value], options);
|
|
@@ -548,7 +508,7 @@ Cache.prototype.decrby = async function(key, value, options) {
|
|
|
548
508
|
* @param {Object} options 配置选项
|
|
549
509
|
* @return {Promise<Number>} 增加后的值
|
|
550
510
|
*/
|
|
551
|
-
Cache.prototype.incrbyfloat = async function(key, value, options) {
|
|
511
|
+
Cache.prototype.incrbyfloat = async function (key, value, options) {
|
|
552
512
|
// 添加作用域前缀
|
|
553
513
|
const scopeKey = `${this.scope}:${key}`;
|
|
554
514
|
return await this._safeCall('incrbyfloat', [scopeKey, value], options);
|
|
@@ -559,7 +519,7 @@ Cache.prototype.incrbyfloat = async function(key, value, options) {
|
|
|
559
519
|
* @param {Array} keyValues 键值对数组,格式: [key1, value1, key2, value2, ...]
|
|
560
520
|
* @return {Promise<Boolean>} 是否设置成功
|
|
561
521
|
*/
|
|
562
|
-
Cache.prototype.mset = async function(...keyValues) {
|
|
522
|
+
Cache.prototype.mset = async function (...keyValues) {
|
|
563
523
|
// 添加作用域前缀到所有键名
|
|
564
524
|
const scopeKeyValues = [];
|
|
565
525
|
for (let i = 0; i < keyValues.length; i += 2) {
|
|
@@ -574,7 +534,7 @@ Cache.prototype.mset = async function(...keyValues) {
|
|
|
574
534
|
* @param {Array} keys 键名数组
|
|
575
535
|
* @return {Promise<Array>} 缓存值数组
|
|
576
536
|
*/
|
|
577
|
-
Cache.prototype.mget = async function(...keys) {
|
|
537
|
+
Cache.prototype.mget = async function (...keys) {
|
|
578
538
|
// 处理参数:如果第一个参数是数组,则使用该数组;否则使用所有参数作为数组
|
|
579
539
|
let keysToUse = keys;
|
|
580
540
|
if (keys.length === 1 && Array.isArray(keys[0])) {
|
|
@@ -593,7 +553,7 @@ Cache.prototype.mget = async function(...keys) {
|
|
|
593
553
|
* @param {Any} value 字段值
|
|
594
554
|
* @return {Promise<Number>} 1表示新字段,0表示更新已有字段
|
|
595
555
|
*/
|
|
596
|
-
Cache.prototype.hset = async function(key, field, value) {
|
|
556
|
+
Cache.prototype.hset = async function (key, field, value) {
|
|
597
557
|
// 添加作用域前缀
|
|
598
558
|
const scopeKey = `${this.scope}:${key}`;
|
|
599
559
|
return await this._safeCall('hset', [scopeKey, field, value]);
|
|
@@ -605,7 +565,7 @@ Cache.prototype.hset = async function(key, field, value) {
|
|
|
605
565
|
* @param {String} field 字段名
|
|
606
566
|
* @return {Promise<Any>} 字段值
|
|
607
567
|
*/
|
|
608
|
-
Cache.prototype.hget = async function(key, field) {
|
|
568
|
+
Cache.prototype.hget = async function (key, field) {
|
|
609
569
|
// 添加作用域前缀
|
|
610
570
|
const scopeKey = `${this.scope}:${key}`;
|
|
611
571
|
return await this._safeCall('hget', [scopeKey, field]);
|
|
@@ -616,7 +576,7 @@ Cache.prototype.hget = async function(key, field) {
|
|
|
616
576
|
* @param {String} key 键名
|
|
617
577
|
* @return {Promise<Object>} 所有字段和值
|
|
618
578
|
*/
|
|
619
|
-
Cache.prototype.hgetall = async function(key) {
|
|
579
|
+
Cache.prototype.hgetall = async function (key) {
|
|
620
580
|
// 添加作用域前缀
|
|
621
581
|
const scopeKey = `${this.scope}:${key}`;
|
|
622
582
|
return await this._safeCall('hgetall', [scopeKey]);
|
|
@@ -628,7 +588,7 @@ Cache.prototype.hgetall = async function(key) {
|
|
|
628
588
|
* @param {String} field 字段名
|
|
629
589
|
* @return {Promise<Number>} 删除的字段数量
|
|
630
590
|
*/
|
|
631
|
-
Cache.prototype.hdel = async function(key, field) {
|
|
591
|
+
Cache.prototype.hdel = async function (key, field) {
|
|
632
592
|
// 添加作用域前缀
|
|
633
593
|
const scopeKey = `${this.scope}:${key}`;
|
|
634
594
|
return await this._safeCall('hdel', [scopeKey, field]);
|
|
@@ -640,7 +600,7 @@ Cache.prototype.hdel = async function(key, field) {
|
|
|
640
600
|
* @param {Array} fieldValues 字段值对数组,格式: [field1, value1, field2, value2, ...]
|
|
641
601
|
* @return {Promise<Number>} 设置的字段数量
|
|
642
602
|
*/
|
|
643
|
-
Cache.prototype.hmset = async function(key, ...fieldValues) {
|
|
603
|
+
Cache.prototype.hmset = async function (key, ...fieldValues) {
|
|
644
604
|
// 添加作用域前缀
|
|
645
605
|
const scopeKey = `${this.scope}:${key}`;
|
|
646
606
|
return await this._safeCall('hmset', [scopeKey, ...fieldValues]);
|
|
@@ -652,7 +612,7 @@ Cache.prototype.hmset = async function(key, ...fieldValues) {
|
|
|
652
612
|
* @param {Array} fields 字段名数组
|
|
653
613
|
* @return {Promise<Array>} 字段值数组
|
|
654
614
|
*/
|
|
655
|
-
Cache.prototype.hmget = async function(key, ...fields) {
|
|
615
|
+
Cache.prototype.hmget = async function (key, ...fields) {
|
|
656
616
|
// 添加作用域前缀
|
|
657
617
|
const scopeKey = `${this.scope}:${key}`;
|
|
658
618
|
return await this._safeCall('hmget', [scopeKey, ...fields]);
|
|
@@ -663,7 +623,7 @@ Cache.prototype.hmget = async function(key, ...fields) {
|
|
|
663
623
|
* @param {String} key 键名
|
|
664
624
|
* @return {Promise<Number>} 字段数量
|
|
665
625
|
*/
|
|
666
|
-
Cache.prototype.hlen = async function(key) {
|
|
626
|
+
Cache.prototype.hlen = async function (key) {
|
|
667
627
|
// 添加作用域前缀
|
|
668
628
|
const scopeKey = `${this.scope}:${key}`;
|
|
669
629
|
return await this._safeCall('hlen', [scopeKey]);
|
|
@@ -674,7 +634,7 @@ Cache.prototype.hlen = async function(key) {
|
|
|
674
634
|
* @param {String} key 键名
|
|
675
635
|
* @return {Promise<Number>} 字符串长度
|
|
676
636
|
*/
|
|
677
|
-
Cache.prototype.strlen = async function(key) {
|
|
637
|
+
Cache.prototype.strlen = async function (key) {
|
|
678
638
|
// 添加作用域前缀
|
|
679
639
|
const scopeKey = `${this.scope}:${key}`;
|
|
680
640
|
return await this._safeCall('strlen', [scopeKey]);
|
|
@@ -686,7 +646,7 @@ Cache.prototype.strlen = async function(key) {
|
|
|
686
646
|
* @param {Array} members 成员数组
|
|
687
647
|
* @return {Promise<Number>} 新增的成员数量
|
|
688
648
|
*/
|
|
689
|
-
Cache.prototype.sadd = async function(key, ...members) {
|
|
649
|
+
Cache.prototype.sadd = async function (key, ...members) {
|
|
690
650
|
// 添加作用域前缀
|
|
691
651
|
const scopeKey = `${this.scope}:${key}`;
|
|
692
652
|
return await this._safeCall('sadd', [scopeKey, ...members]);
|
|
@@ -698,7 +658,7 @@ Cache.prototype.sadd = async function(key, ...members) {
|
|
|
698
658
|
* @param {Array} members 成员数组
|
|
699
659
|
* @return {Promise<Number>} 删除的成员数量
|
|
700
660
|
*/
|
|
701
|
-
Cache.prototype.srem = async function(key, ...members) {
|
|
661
|
+
Cache.prototype.srem = async function (key, ...members) {
|
|
702
662
|
// 添加作用域前缀
|
|
703
663
|
const scopeKey = `${this.scope}:${key}`;
|
|
704
664
|
return await this._safeCall('srem', [scopeKey, ...members]);
|
|
@@ -710,7 +670,7 @@ Cache.prototype.srem = async function(key, ...members) {
|
|
|
710
670
|
* @param {String} member 成员
|
|
711
671
|
* @return {Promise<Boolean>} 是否存在
|
|
712
672
|
*/
|
|
713
|
-
Cache.prototype.sismember = async function(key, member) {
|
|
673
|
+
Cache.prototype.sismember = async function (key, member) {
|
|
714
674
|
// 添加作用域前缀
|
|
715
675
|
const scopeKey = `${this.scope}:${key}`;
|
|
716
676
|
return await this._safeCall('sismember', [scopeKey, member]);
|
|
@@ -721,7 +681,7 @@ Cache.prototype.sismember = async function(key, member) {
|
|
|
721
681
|
* @param {String} key 键名
|
|
722
682
|
* @return {Promise<Array>} 成员数组
|
|
723
683
|
*/
|
|
724
|
-
Cache.prototype.smembers = async function(key) {
|
|
684
|
+
Cache.prototype.smembers = async function (key) {
|
|
725
685
|
// 添加作用域前缀
|
|
726
686
|
const scopeKey = `${this.scope}:${key}`;
|
|
727
687
|
return await this._safeCall('smembers', [scopeKey]);
|
|
@@ -733,7 +693,7 @@ Cache.prototype.smembers = async function(key) {
|
|
|
733
693
|
* @param {Number} milliseconds 过期时间(毫秒)
|
|
734
694
|
* @return {Promise<Boolean>} 是否设置成功
|
|
735
695
|
*/
|
|
736
|
-
Cache.prototype.pexpire = async function(key, milliseconds) {
|
|
696
|
+
Cache.prototype.pexpire = async function (key, milliseconds) {
|
|
737
697
|
// 添加作用域前缀
|
|
738
698
|
const scopeKey = `${this.scope}:${key}`;
|
|
739
699
|
return await this._safeCall('pexpire', [scopeKey, milliseconds]);
|
|
@@ -744,7 +704,7 @@ Cache.prototype.pexpire = async function(key, milliseconds) {
|
|
|
744
704
|
* @param {String} key 键名
|
|
745
705
|
* @return {Promise<Boolean>} 是否移除成功
|
|
746
706
|
*/
|
|
747
|
-
Cache.prototype.persist = async function(key) {
|
|
707
|
+
Cache.prototype.persist = async function (key) {
|
|
748
708
|
// 添加作用域前缀
|
|
749
709
|
const scopeKey = `${this.scope}:${key}`;
|
|
750
710
|
return await this._safeCall('persist', [scopeKey]);
|
|
@@ -756,7 +716,7 @@ Cache.prototype.persist = async function(key) {
|
|
|
756
716
|
* @param {String} newKey 新键名
|
|
757
717
|
* @return {Promise<Boolean>} 是否重命名成功
|
|
758
718
|
*/
|
|
759
|
-
Cache.prototype.rename = async function(oldKey, newKey) {
|
|
719
|
+
Cache.prototype.rename = async function (oldKey, newKey) {
|
|
760
720
|
// 添加作用域前缀
|
|
761
721
|
const scopeOldKey = `${this.scope}:${oldKey}`;
|
|
762
722
|
const scopeNewKey = `${this.scope}:${newKey}`;
|
|
@@ -768,7 +728,7 @@ Cache.prototype.rename = async function(oldKey, newKey) {
|
|
|
768
728
|
* @param {String} key 键名
|
|
769
729
|
* @return {Promise<String>} 类型(none|string|list|set|zset|hash)
|
|
770
730
|
*/
|
|
771
|
-
Cache.prototype.type = async function(key) {
|
|
731
|
+
Cache.prototype.type = async function (key) {
|
|
772
732
|
// 添加作用域前缀
|
|
773
733
|
const scopeKey = `${this.scope}:${key}`;
|
|
774
734
|
return await this._safeCall('type', [scopeKey]);
|
|
@@ -781,7 +741,7 @@ Cache.prototype.type = async function(key) {
|
|
|
781
741
|
* @param {Number} expire 过期时间(秒)
|
|
782
742
|
* @return {Promise<Boolean>} 是否成功
|
|
783
743
|
*/
|
|
784
|
-
Cache.prototype.setForList = async function(key, value, expire) {
|
|
744
|
+
Cache.prototype.setForList = async function (key, value, expire) {
|
|
785
745
|
// 添加作用域前缀
|
|
786
746
|
const scopeKey = `${this.scope}:${key}`;
|
|
787
747
|
return await this._safeCall('setForList', [scopeKey, value, expire]);
|
|
@@ -793,7 +753,7 @@ Cache.prototype.setForList = async function(key, value, expire) {
|
|
|
793
753
|
* @param {*} value 要添加的元素
|
|
794
754
|
* @return {Promise<Boolean>} 是否成功
|
|
795
755
|
*/
|
|
796
|
-
Cache.prototype.addForList = async function(key, value) {
|
|
756
|
+
Cache.prototype.addForList = async function (key, value) {
|
|
797
757
|
// 添加作用域前缀
|
|
798
758
|
const scopeKey = `${this.scope}:${key}`;
|
|
799
759
|
return await this._safeCall('addForList', [scopeKey, value]);
|
|
@@ -805,7 +765,7 @@ Cache.prototype.addForList = async function(key, value) {
|
|
|
805
765
|
* @param {*} value 要检查的元素
|
|
806
766
|
* @return {Promise<Boolean>} 是否包含
|
|
807
767
|
*/
|
|
808
|
-
Cache.prototype.hasForList = async function(key, value) {
|
|
768
|
+
Cache.prototype.hasForList = async function (key, value) {
|
|
809
769
|
// 添加作用域前缀
|
|
810
770
|
const scopeKey = `${this.scope}:${key}`;
|
|
811
771
|
return await this._safeCall('hasForList', [scopeKey, value]);
|
|
@@ -818,7 +778,7 @@ Cache.prototype.hasForList = async function(key, value) {
|
|
|
818
778
|
* @param {Number} stop 结束索引,默认-1(表示到末尾)
|
|
819
779
|
* @return {Promise<Array>} 元素数组
|
|
820
780
|
*/
|
|
821
|
-
Cache.prototype.getForList = async function(key, start = 0, stop = -1) {
|
|
781
|
+
Cache.prototype.getForList = async function (key, start = 0, stop = -1) {
|
|
822
782
|
// 添加作用域前缀
|
|
823
783
|
const scopeKey = `${this.scope}:${key}`;
|
|
824
784
|
return await this._safeCall('getForList', [scopeKey, start, stop]);
|
|
@@ -829,7 +789,7 @@ Cache.prototype.getForList = async function(key, start = 0, stop = -1) {
|
|
|
829
789
|
* @param {String} key 键名
|
|
830
790
|
* @return {Promise<Boolean>} 是否成功
|
|
831
791
|
*/
|
|
832
|
-
Cache.prototype.clearForList = async function(key) {
|
|
792
|
+
Cache.prototype.clearForList = async function (key) {
|
|
833
793
|
// 添加作用域前缀
|
|
834
794
|
const scopeKey = `${this.scope}:${key}`;
|
|
835
795
|
return await this._safeCall('clearForList', [scopeKey]);
|
|
@@ -840,7 +800,7 @@ Cache.prototype.clearForList = async function(key) {
|
|
|
840
800
|
* @param {String} key 匹配模式
|
|
841
801
|
* @return {Promise<Boolean>} 是否清理成功
|
|
842
802
|
*/
|
|
843
|
-
Cache.prototype.clear = async function(key) {
|
|
803
|
+
Cache.prototype.clear = async function (key) {
|
|
844
804
|
// 添加作用域前缀
|
|
845
805
|
const scopeKey = key ? `${this.scope}:${key}` : `${this.scope}:*`;
|
|
846
806
|
return await this._safeCall('clear', [scopeKey]);
|
|
@@ -850,7 +810,7 @@ Cache.prototype.clear = async function(key) {
|
|
|
850
810
|
* @description 清理过期缓存
|
|
851
811
|
* @return {Promise<Boolean>} 是否清理成功
|
|
852
812
|
*/
|
|
853
|
-
Cache.prototype.clearExpire = async function() {
|
|
813
|
+
Cache.prototype.clearExpire = async function () {
|
|
854
814
|
return await this._safeCall('clearExpire', []);
|
|
855
815
|
};
|
|
856
816
|
|
|
@@ -858,7 +818,7 @@ Cache.prototype.clearExpire = async function() {
|
|
|
858
818
|
* @description 关闭数据库连接
|
|
859
819
|
* @return {Promise<Boolean>} 是否关闭成功
|
|
860
820
|
*/
|
|
861
|
-
Cache.prototype.dispose = async function() {
|
|
821
|
+
Cache.prototype.dispose = async function () {
|
|
862
822
|
if (this.db && typeof this.db.dispose === 'function') {
|
|
863
823
|
return await this.db.dispose();
|
|
864
824
|
}
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mm_cache",
|
|
3
|
-
"version": "1.4.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.4.3",
|
|
4
|
+
"description": "一个统一的缓存操作框架,为多种缓存方式(Redis、MongoDB、CacheBase、Memory)提供统一的API接口,实现无缝切换和兼容",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "node test.js"
|
|
8
8
|
},
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
11
|
-
"url": "git+https://
|
|
11
|
+
"url": "git+https://gitee.com/qiuwenwu/mm_cache.git"
|
|
12
12
|
},
|
|
13
13
|
"keywords": [
|
|
14
14
|
"cache",
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
"author": "邱文武",
|
|
27
27
|
"license": "ISC",
|
|
28
28
|
"bugs": {
|
|
29
|
-
"url": "https://
|
|
29
|
+
"url": "https://gitee.com/qiuwenwu/mm_cache/issues"
|
|
30
30
|
},
|
|
31
|
-
"homepage": "https://
|
|
31
|
+
"homepage": "https://gitee.com/qiuwenwu/mm_cache#readme",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"mm_cachebase": "^1.
|
|
34
|
-
"mm_mongodb": "^1.
|
|
35
|
-
"mm_redis": "^
|
|
33
|
+
"mm_cachebase": "^1.9.1",
|
|
34
|
+
"mm_mongodb": "^1.5.3",
|
|
35
|
+
"mm_redis": "^2.0.9"
|
|
36
36
|
}
|
|
37
|
-
}
|
|
37
|
+
}
|
package/test.js
CHANGED
|
@@ -87,8 +87,8 @@ async function recordTestResult(cache, methodName, testFunction) {
|
|
|
87
87
|
// 对关键方法失败时输出详细信息
|
|
88
88
|
const criticalMethods = ['hdel', 'hmset', 'hmget', 'hlen', 'addForList', 'expire'];
|
|
89
89
|
if (criticalMethods.includes(methodName)) {
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
$.log.error(`[Cache] ${cacheWay}.${methodName} 测试失败: ${error.message}`);
|
|
91
|
+
$.log.error(error.stack);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
// 检查是否是"不支持的方法"错误
|
|
@@ -448,19 +448,19 @@ function getUnsupportedReason(method) {
|
|
|
448
448
|
|
|
449
449
|
// 测试单个缓存方式的所有方法
|
|
450
450
|
async function testCacheWay(cacheWay) {
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
451
|
+
$.log.debug(`\n[Cache] ==============================`);
|
|
452
|
+
$.log.debug(`[Cache] 开始测试缓存方式: ${cacheWay}`);
|
|
453
|
+
$.log.debug(`[Cache] ==============================`);
|
|
454
454
|
|
|
455
455
|
// 直接使用指定的缓存方式创建Cache实例
|
|
456
456
|
const cache = new Cache(`test_${cacheWay}`, { way: cacheWay });
|
|
457
457
|
const connected = await cache.connect();
|
|
458
458
|
|
|
459
459
|
if (connected) {
|
|
460
|
-
|
|
461
|
-
|
|
460
|
+
$.log.debug(`[Cache] 成功连接到缓存方式: ${cacheWay}`);
|
|
461
|
+
$.log.debug(`[Cache] 当前实际缓存方式: ${cache.getCacheWay()}`);
|
|
462
462
|
} else {
|
|
463
|
-
|
|
463
|
+
$.log.debug(`[Cache] 无法连接到缓存方式: ${cacheWay}`);
|
|
464
464
|
return false;
|
|
465
465
|
}
|
|
466
466
|
|