mm_cachebase 1.4.6 → 1.6.0
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/LICENSE +21 -0
- package/README.md +219 -714
- package/compatibility_table.md +63 -0
- package/index.js +802 -1995
- package/package.json +41 -35
- package/test.js +471 -68
package/index.js
CHANGED
|
@@ -1,2132 +1,939 @@
|
|
|
1
|
-
require('mm_logs');
|
|
2
1
|
const EventEmitter = require('events');
|
|
2
|
+
require('mm_logs');
|
|
3
3
|
|
|
4
|
-
// 简化版的CacheBase类,只包含事件触发核心功能
|
|
5
4
|
class CacheBase extends EventEmitter {
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* 构造函数,初始化缓存
|
|
7
|
+
* @param {Object} options - 配置选项
|
|
8
|
+
*/
|
|
9
|
+
constructor(options = {}) {
|
|
7
10
|
super();
|
|
11
|
+
// 配置选项
|
|
12
|
+
this.options = options;
|
|
13
|
+
// 日志实例
|
|
14
|
+
this.log = options.log || $;
|
|
15
|
+
// 数据存储对象
|
|
8
16
|
this.data = {};
|
|
9
|
-
|
|
10
|
-
this.list = [];
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
// 执行实际操作
|
|
32
|
-
this.data[key] = { value, expire: 0 };
|
|
33
|
-
|
|
34
|
-
// 如果键不存在于列表中,添加到列表
|
|
35
|
-
if (!this.list.includes(key)) {
|
|
36
|
-
this.list.push(key);
|
|
17
|
+
// 键列表,用于存储所有的键名
|
|
18
|
+
this.list = [];
|
|
19
|
+
// 为了兼容旧版本,提供dict属性指向data
|
|
20
|
+
this.dict = this.data;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 检查键是否过期
|
|
25
|
+
* @private
|
|
26
|
+
* @param {string} key - 键名
|
|
27
|
+
* @returns {boolean} - 是否已过期
|
|
28
|
+
*/
|
|
29
|
+
_checkExpire(key) {
|
|
30
|
+
if (this.data.hasOwnProperty(key)) {
|
|
31
|
+
const item = this.data[key];
|
|
32
|
+
if (item && typeof item === 'object' && item.expire > 0) {
|
|
33
|
+
// 检查是否过期
|
|
34
|
+
if (Date.now() > item.expire) {
|
|
35
|
+
// 删除过期键
|
|
36
|
+
this.del(key);
|
|
37
|
+
return true;
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
-
// 触发后置事件
|
|
40
|
-
this.emit('set_after', {
|
|
41
|
-
key,
|
|
42
|
-
value,
|
|
43
|
-
result: 1
|
|
44
|
-
});
|
|
45
|
-
resolve(1);
|
|
46
|
-
} catch (error) {
|
|
47
|
-
// 触发错误事件
|
|
48
|
-
this.emit('set_error', {
|
|
49
|
-
key,
|
|
50
|
-
value,
|
|
51
|
-
error
|
|
52
|
-
});
|
|
53
|
-
$.log.error('[cachebase] set操作失败:', error);
|
|
54
|
-
resolve(null);
|
|
55
39
|
}
|
|
56
|
-
}
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
57
42
|
}
|
|
58
43
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
71
|
-
if (beforeEventData.cancel) {
|
|
72
|
-
resolve(0);
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// 检查键是否存在
|
|
77
|
-
const exists = key in this.data;
|
|
78
|
-
|
|
79
|
-
// 执行删除操作
|
|
80
|
-
if (exists) {
|
|
81
|
-
delete this.data[key];
|
|
82
|
-
// 从列表中移除
|
|
83
|
-
const index = this.list.indexOf(key);
|
|
84
|
-
if (index > -1) {
|
|
85
|
-
this.list.splice(index, 1);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// 触发后置事件
|
|
90
|
-
this.emit('del_after', {
|
|
91
|
-
key,
|
|
92
|
-
result: exists ? 1 : 0
|
|
93
|
-
});
|
|
94
|
-
resolve(exists ? 1 : 0);
|
|
95
|
-
} catch (error) {
|
|
96
|
-
// 触发错误事件
|
|
97
|
-
this.emit('del_error', {
|
|
98
|
-
key,
|
|
99
|
-
error
|
|
100
|
-
});
|
|
101
|
-
$.log.error('[cachebase] del操作失败:', error);
|
|
102
|
-
resolve(0);
|
|
44
|
+
/**
|
|
45
|
+
* 设置键的过期时间
|
|
46
|
+
* @private
|
|
47
|
+
* @param {string} key - 键名
|
|
48
|
+
* @param {number} seconds - 过期时间(秒)
|
|
49
|
+
*/
|
|
50
|
+
_setExpire(key, seconds) {
|
|
51
|
+
if (this.data.hasOwnProperty(key)) {
|
|
52
|
+
const item = this.data[key];
|
|
53
|
+
if (item && typeof item === 'object') {
|
|
54
|
+
item.expire = seconds > 0 ? Date.now() + seconds * 1000 : 0;
|
|
103
55
|
}
|
|
104
|
-
}
|
|
56
|
+
}
|
|
105
57
|
}
|
|
106
58
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
// 执行实际操作
|
|
125
|
-
const obj = this.data[key];
|
|
126
|
-
let result = null;
|
|
127
|
-
if (obj) {
|
|
128
|
-
result = obj.value;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// 触发后置事件
|
|
132
|
-
this.emit('get_after', {
|
|
133
|
-
key,
|
|
134
|
-
result
|
|
135
|
-
});
|
|
136
|
-
resolve(result);
|
|
137
|
-
} catch (error) {
|
|
138
|
-
// 触发错误事件
|
|
139
|
-
this.emit('get_error', {
|
|
140
|
-
key,
|
|
141
|
-
error
|
|
142
|
-
});
|
|
143
|
-
$.log.error('[cachebase] get操作失败:', error);
|
|
144
|
-
resolve(null);
|
|
59
|
+
/**
|
|
60
|
+
* 设置键值
|
|
61
|
+
* @param {string} key - 键名
|
|
62
|
+
* @param {*} value - 键值
|
|
63
|
+
* @param {number} expire - 过期时间(秒),0表示永不过期
|
|
64
|
+
* @returns {Promise<string>} - 返回'OK'
|
|
65
|
+
*/
|
|
66
|
+
async set(key, value, expire = 0) {
|
|
67
|
+
try {
|
|
68
|
+
this.emit('set_before', { key, value, expire });
|
|
69
|
+
|
|
70
|
+
// 设置值和过期时间
|
|
71
|
+
this.data[key] = { value, expire: expire > 0 ? Date.now() + expire * 1000 : 0 };
|
|
72
|
+
|
|
73
|
+
// 如果键不存在于列表中,添加到列表
|
|
74
|
+
if (!this.list.includes(key)) {
|
|
75
|
+
this.list.push(key);
|
|
145
76
|
}
|
|
146
|
-
|
|
77
|
+
|
|
78
|
+
this.emit('set_after', { key, value, expire, result: 'OK' });
|
|
79
|
+
return 'OK';
|
|
80
|
+
} catch (error) {
|
|
81
|
+
this.emit('set_error', { key, value, expire, error });
|
|
82
|
+
this.log.error('[cachebase] set操作失败:', error);
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
147
85
|
}
|
|
148
86
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
this.emit('hset_before', beforeEventData);
|
|
160
|
-
|
|
161
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
162
|
-
if (beforeEventData.cancel) {
|
|
163
|
-
resolve(0);
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// 确保哈希表存在
|
|
168
|
-
if (!this.data[key]) {
|
|
169
|
-
this.data[key] = { value: {}, expire: 0 };
|
|
170
|
-
// 添加到列表
|
|
171
|
-
if (!this.list.includes(key)) {
|
|
172
|
-
this.list.push(key);
|
|
173
|
-
}
|
|
174
|
-
} else if (typeof this.data[key].value !== 'object') {
|
|
175
|
-
this.data[key].value = {};
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// 记录是否是新字段
|
|
179
|
-
const isNewField = !this.data[key].value.hasOwnProperty(field);
|
|
180
|
-
|
|
181
|
-
// 设置字段值
|
|
182
|
-
this.data[key].value[field] = value;
|
|
183
|
-
|
|
184
|
-
// 触发后置事件
|
|
185
|
-
this.emit('hset_after', {
|
|
186
|
-
key,
|
|
187
|
-
value: { field, value },
|
|
188
|
-
result: isNewField ? 1 : 0
|
|
189
|
-
});
|
|
190
|
-
resolve(isNewField ? 1 : 0);
|
|
191
|
-
} catch (error) {
|
|
192
|
-
// 触发错误事件
|
|
193
|
-
this.emit('hset_error', {
|
|
194
|
-
key,
|
|
195
|
-
value: { field, value },
|
|
196
|
-
error
|
|
197
|
-
});
|
|
198
|
-
$.log.error('[cachebase] hset操作失败:', error);
|
|
199
|
-
resolve(0);
|
|
87
|
+
/**
|
|
88
|
+
* 获取键值
|
|
89
|
+
* @param {string} key - 键名
|
|
90
|
+
* @returns {Promise<*>} - 返回键值,不存在返回undefined
|
|
91
|
+
*/
|
|
92
|
+
async get(key) {
|
|
93
|
+
try {
|
|
94
|
+
// 检查键是否存在
|
|
95
|
+
if (!this.data.hasOwnProperty(key)) {
|
|
96
|
+
return undefined;
|
|
200
97
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
value: { values },
|
|
212
|
-
cancel: false
|
|
213
|
-
};
|
|
214
|
-
this.emit('lpush_before', beforeEventData);
|
|
215
|
-
|
|
216
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
217
|
-
if (beforeEventData.cancel) {
|
|
218
|
-
resolve(0);
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// 确保列表存在
|
|
223
|
-
if (!this.data[key]) {
|
|
224
|
-
this.data[key] = { value: [], expire: 0 };
|
|
225
|
-
// 添加到列表
|
|
226
|
-
if (!this.list.includes(key)) {
|
|
227
|
-
this.list.push(key);
|
|
228
|
-
}
|
|
229
|
-
} else if (!Array.isArray(this.data[key].value)) {
|
|
230
|
-
this.data[key].value = [];
|
|
98
|
+
|
|
99
|
+
const item = this.data[key];
|
|
100
|
+
|
|
101
|
+
// 检查是否过期
|
|
102
|
+
if (item.expire > 0 && Date.now() > item.expire) {
|
|
103
|
+
// 删除过期键
|
|
104
|
+
delete this.data[key];
|
|
105
|
+
const index = this.list.indexOf(key);
|
|
106
|
+
if (index !== -1) {
|
|
107
|
+
this.list.splice(index, 1);
|
|
231
108
|
}
|
|
232
|
-
|
|
233
|
-
// 将值添加到列表头部
|
|
234
|
-
this.data[key].value.unshift(...values);
|
|
235
|
-
|
|
236
|
-
// 触发后置事件
|
|
237
|
-
this.emit('lpush_after', {
|
|
238
|
-
key,
|
|
239
|
-
value: { values },
|
|
240
|
-
result: this.data[key].value.length
|
|
241
|
-
});
|
|
242
|
-
resolve(this.data[key].value.length);
|
|
243
|
-
} catch (error) {
|
|
244
|
-
// 触发错误事件
|
|
245
|
-
this.emit('lpush_error', {
|
|
246
|
-
key,
|
|
247
|
-
value: { values },
|
|
248
|
-
error
|
|
249
|
-
});
|
|
250
|
-
$.log.error('[cachebase] lpush操作失败:', error);
|
|
251
|
-
resolve(0);
|
|
109
|
+
return undefined;
|
|
252
110
|
}
|
|
253
|
-
|
|
111
|
+
|
|
112
|
+
return item.value;
|
|
113
|
+
} catch (error) {
|
|
114
|
+
this.log.error('[cachebase] get操作失败:', error);
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
254
117
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// 确保集合存在
|
|
275
|
-
if (!this.data[key]) {
|
|
276
|
-
this.data[key] = { value: new Set(), expire: 0 };
|
|
277
|
-
// 添加到列表
|
|
278
|
-
if (!this.list.includes(key)) {
|
|
279
|
-
this.list.push(key);
|
|
280
|
-
}
|
|
281
|
-
} else if (!(this.data[key].value instanceof Set)) {
|
|
282
|
-
this.data[key].value = new Set();
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* 删除键
|
|
121
|
+
* @param {string} key - 键名
|
|
122
|
+
* @returns {Promise<number>} - 返回删除的键数量
|
|
123
|
+
*/
|
|
124
|
+
async del(key) {
|
|
125
|
+
try {
|
|
126
|
+
this.emit('del_before', { key });
|
|
127
|
+
|
|
128
|
+
// 检查键是否存在
|
|
129
|
+
let deleted = 0;
|
|
130
|
+
if (this.data.hasOwnProperty(key)) {
|
|
131
|
+
delete this.data[key];
|
|
132
|
+
const index = this.list.indexOf(key);
|
|
133
|
+
if (index !== -1) {
|
|
134
|
+
this.list.splice(index, 1);
|
|
283
135
|
}
|
|
284
|
-
|
|
285
|
-
// 记录添加前的大小
|
|
286
|
-
const beforeSize = this.data[key].value.size;
|
|
287
|
-
|
|
288
|
-
// 添加成员
|
|
289
|
-
members.forEach(member => {
|
|
290
|
-
this.data[key].value.add(member);
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
// 计算新增的成员数
|
|
294
|
-
const addedCount = this.data[key].value.size - beforeSize;
|
|
295
|
-
|
|
296
|
-
// 触发后置事件
|
|
297
|
-
this.emit('sadd_after', {
|
|
298
|
-
key,
|
|
299
|
-
value: { members },
|
|
300
|
-
result: addedCount
|
|
301
|
-
});
|
|
302
|
-
resolve(addedCount);
|
|
303
|
-
} catch (error) {
|
|
304
|
-
// 触发错误事件
|
|
305
|
-
this.emit('sadd_error', {
|
|
306
|
-
key,
|
|
307
|
-
value: { members },
|
|
308
|
-
error
|
|
309
|
-
});
|
|
310
|
-
$.log.error('[cachebase] sadd操作失败:', error);
|
|
311
|
-
resolve(0);
|
|
136
|
+
deleted = 1;
|
|
312
137
|
}
|
|
313
|
-
|
|
138
|
+
|
|
139
|
+
this.emit('del_after', { key, result: deleted });
|
|
140
|
+
return deleted;
|
|
141
|
+
} catch (error) {
|
|
142
|
+
this.emit('del_error', { key, error });
|
|
143
|
+
this.log.error('[cachebase] del操作失败:', error);
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
314
146
|
}
|
|
315
147
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
if (!this.data[key]) {
|
|
336
|
-
this.data[key] = { value: { members: {}, sorted: [] }, expire: 0 };
|
|
337
|
-
// 添加到列表
|
|
338
|
-
if (!this.list.includes(key)) {
|
|
339
|
-
this.list.push(key);
|
|
148
|
+
/**
|
|
149
|
+
* 检查键是否存在
|
|
150
|
+
* @param {string|Array<string>} key - 键名或键名数组
|
|
151
|
+
* @returns {Promise<number>} - 返回存在的键数量
|
|
152
|
+
*/
|
|
153
|
+
async exists(key) {
|
|
154
|
+
try {
|
|
155
|
+
let existsCount = 0;
|
|
156
|
+
|
|
157
|
+
// 检查输入类型并处理
|
|
158
|
+
if (Array.isArray(key)) {
|
|
159
|
+
// 处理多键检查
|
|
160
|
+
for (const k of key) {
|
|
161
|
+
if (this.data.hasOwnProperty(k)) {
|
|
162
|
+
// 检查是否过期
|
|
163
|
+
const item = this.data[k];
|
|
164
|
+
if (!(item.expire > 0 && Date.now() > item.expire)) {
|
|
165
|
+
existsCount++;
|
|
166
|
+
}
|
|
340
167
|
}
|
|
341
|
-
} else if (!this.data[key].value || !this.data[key].value.members) {
|
|
342
|
-
this.data[key].value = { members: {}, sorted: [] };
|
|
343
168
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
// 如果成员不存在,则计数增加
|
|
353
|
-
if (!this.data[key].value.members.hasOwnProperty(member)) {
|
|
354
|
-
addedCount++;
|
|
169
|
+
} else {
|
|
170
|
+
// 处理单键检查
|
|
171
|
+
if (this.data.hasOwnProperty(key)) {
|
|
172
|
+
// 检查是否过期
|
|
173
|
+
const item = this.data[key];
|
|
174
|
+
if (!(item.expire > 0 && Date.now() > item.expire)) {
|
|
175
|
+
existsCount = 1;
|
|
355
176
|
}
|
|
356
|
-
|
|
357
|
-
// 设置成员分数
|
|
358
|
-
this.data[key].value.members[member] = score;
|
|
359
177
|
}
|
|
360
|
-
|
|
361
|
-
// 更新排序
|
|
362
|
-
this.data[key].value.sorted = Object.entries(this.data[key].value.members)
|
|
363
|
-
.sort((a, b) => a[1] - b[1])
|
|
364
|
-
.map(entry => entry[0]);
|
|
365
|
-
|
|
366
|
-
// 触发后置事件
|
|
367
|
-
this.emit('zadd_after', {
|
|
368
|
-
key,
|
|
369
|
-
value: { args },
|
|
370
|
-
result: addedCount
|
|
371
|
-
});
|
|
372
|
-
resolve(addedCount);
|
|
373
|
-
} catch (error) {
|
|
374
|
-
// 触发错误事件
|
|
375
|
-
this.emit('zadd_error', {
|
|
376
|
-
key,
|
|
377
|
-
value: { args },
|
|
378
|
-
error
|
|
379
|
-
});
|
|
380
|
-
$.log.error('[cachebase] zadd操作失败:', error);
|
|
381
|
-
resolve(0);
|
|
382
178
|
}
|
|
383
|
-
|
|
179
|
+
|
|
180
|
+
return existsCount;
|
|
181
|
+
} catch (error) {
|
|
182
|
+
this.log.error('[cachebase] exists操作失败:', error);
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
384
185
|
}
|
|
385
186
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
// 执行实际操作
|
|
411
|
-
for (let i = 0; i < args.length; i += 2) {
|
|
412
|
-
const key = args[i];
|
|
413
|
-
const value = args[i + 1];
|
|
414
|
-
this.data[key] = { value, expire: 0 };
|
|
415
|
-
// 添加到列表
|
|
416
|
-
if (!this.list.includes(key)) {
|
|
417
|
-
this.list.push(key);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// 触发后置事件
|
|
422
|
-
this.emit('mset_after', {
|
|
423
|
-
value: { args },
|
|
424
|
-
result: 'OK'
|
|
425
|
-
});
|
|
426
|
-
resolve('OK');
|
|
427
|
-
} catch (error) {
|
|
428
|
-
// 触发错误事件
|
|
429
|
-
this.emit('mset_error', {
|
|
430
|
-
value: { args },
|
|
431
|
-
error
|
|
432
|
-
});
|
|
433
|
-
$.log.error('[cachebase] mset操作失败:', error);
|
|
434
|
-
resolve('ERR');
|
|
187
|
+
/**
|
|
188
|
+
* 设置哈希表字段
|
|
189
|
+
* @param {string} key - 键名
|
|
190
|
+
* @param {string} field - 字段名
|
|
191
|
+
* @param {*} value - 字段值
|
|
192
|
+
* @returns {Promise<number>} - 返回1表示新建字段,0表示更新字段
|
|
193
|
+
*/
|
|
194
|
+
async hset(key, field, value) {
|
|
195
|
+
try {
|
|
196
|
+
this.emit('hset_before', { key, field, value });
|
|
197
|
+
|
|
198
|
+
// 初始化哈希表
|
|
199
|
+
if (!this.data.hasOwnProperty(key)) {
|
|
200
|
+
this.data[key] = { value: {}, expire: 0 };
|
|
201
|
+
this.list.push(key);
|
|
202
|
+
} else if (this.data[key].expire > 0 && Date.now() > this.data[key].expire) {
|
|
203
|
+
// 键已过期,重新初始化
|
|
204
|
+
this.data[key] = { value: {}, expire: 0 };
|
|
205
|
+
} else if (typeof this.data[key].value !== 'object') {
|
|
206
|
+
// 类型错误
|
|
207
|
+
throw new Error(`[cachebase] 键 ${key} 不是哈希表类型`);
|
|
435
208
|
}
|
|
436
|
-
|
|
209
|
+
|
|
210
|
+
// 检查字段是否存在
|
|
211
|
+
const isNewField = !this.data[key].value.hasOwnProperty(field);
|
|
212
|
+
this.data[key].value[field] = value;
|
|
213
|
+
|
|
214
|
+
const result = isNewField ? 1 : 0;
|
|
215
|
+
this.emit('hset_after', { key, field, value, result });
|
|
216
|
+
return result;
|
|
217
|
+
} catch (error) {
|
|
218
|
+
this.emit('hset_error', { key, field, value, error });
|
|
219
|
+
this.log.error('[cachebase] hset操作失败:', error);
|
|
220
|
+
throw error;
|
|
221
|
+
}
|
|
437
222
|
}
|
|
438
223
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
if (beforeEventData.cancel) {
|
|
453
|
-
resolve(0);
|
|
454
|
-
return;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
// 获取当前值或默认为0
|
|
458
|
-
let currentValue = 0;
|
|
459
|
-
if (this.data[key] && typeof this.data[key].value === 'number') {
|
|
460
|
-
currentValue = this.data[key].value;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
// 执行加法
|
|
464
|
-
const result = currentValue + parseFloat(value);
|
|
465
|
-
|
|
466
|
-
// 保存结果
|
|
467
|
-
this.data[key] = { value: result, expire: 0 };
|
|
468
|
-
// 添加到列表
|
|
469
|
-
if (!this.list.includes(key)) {
|
|
470
|
-
this.list.push(key);
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
// 触发后置事件
|
|
474
|
-
this.emit('addFloat_after', {
|
|
475
|
-
key,
|
|
476
|
-
value: parseFloat(value),
|
|
477
|
-
result
|
|
478
|
-
});
|
|
479
|
-
resolve(result);
|
|
480
|
-
} catch (error) {
|
|
481
|
-
// 触发错误事件
|
|
482
|
-
this.emit('addFloat_error', {
|
|
483
|
-
key,
|
|
484
|
-
value: parseFloat(value),
|
|
485
|
-
error
|
|
486
|
-
});
|
|
487
|
-
$.log.error('[cachebase] addFloat操作失败:', error);
|
|
488
|
-
resolve(0);
|
|
224
|
+
/**
|
|
225
|
+
* 获取哈希表字段
|
|
226
|
+
* @param {string} key - 键名
|
|
227
|
+
* @param {string} field - 字段名
|
|
228
|
+
* @returns {Promise<*>} - 返回字段值,不存在返回undefined
|
|
229
|
+
*/
|
|
230
|
+
async hget(key, field) {
|
|
231
|
+
try {
|
|
232
|
+
// 检查键是否存在且未过期
|
|
233
|
+
if (!this.data.hasOwnProperty(key) ||
|
|
234
|
+
(this.data[key].expire > 0 && Date.now() > this.data[key].expire) ||
|
|
235
|
+
typeof this.data[key].value !== 'object') {
|
|
236
|
+
return undefined;
|
|
489
237
|
}
|
|
490
|
-
|
|
238
|
+
|
|
239
|
+
return this.data[key].value[field];
|
|
240
|
+
} catch (error) {
|
|
241
|
+
this.log.error('[cachebase] hget操作失败:', error);
|
|
242
|
+
throw error;
|
|
243
|
+
}
|
|
491
244
|
}
|
|
492
245
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
506
|
-
if (beforeEventData.cancel) {
|
|
507
|
-
resolve(0);
|
|
508
|
-
return;
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
// 获取当前值或默认为空字符串
|
|
512
|
-
let currentValue = '';
|
|
513
|
-
if (this.data[key] && typeof this.data[key].value === 'string') {
|
|
514
|
-
currentValue = this.data[key].value;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
// 执行字符串拼接
|
|
518
|
-
const result = currentValue + value;
|
|
519
|
-
|
|
520
|
-
// 保存结果
|
|
521
|
-
this.data[key] = { value: result, expire: 0 };
|
|
522
|
-
// 添加到列表
|
|
523
|
-
if (!this.list.includes(key)) {
|
|
524
|
-
this.list.push(key);
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
// 触发后置事件
|
|
528
|
-
this.emit('addStr_after', {
|
|
529
|
-
key,
|
|
530
|
-
value: String(value),
|
|
531
|
-
result
|
|
532
|
-
});
|
|
533
|
-
resolve(result);
|
|
534
|
-
} catch (error) {
|
|
535
|
-
// 触发错误事件
|
|
536
|
-
this.emit('addStr_error', {
|
|
537
|
-
key,
|
|
538
|
-
value: String(value),
|
|
539
|
-
error
|
|
540
|
-
});
|
|
541
|
-
$.log.error('[cachebase] addStr操作失败:', error);
|
|
542
|
-
resolve(0);
|
|
246
|
+
/**
|
|
247
|
+
* 获取哈希表所有字段
|
|
248
|
+
* @param {string} key - 键名
|
|
249
|
+
* @returns {Promise<Object>} - 返回哈希表对象,不存在或不是哈希表返回{}
|
|
250
|
+
*/
|
|
251
|
+
async hgetall(key) {
|
|
252
|
+
try {
|
|
253
|
+
// 检查键是否存在且未过期
|
|
254
|
+
if (!this.data.hasOwnProperty(key) ||
|
|
255
|
+
(this.data[key].expire > 0 && Date.now() > this.data[key].expire) ||
|
|
256
|
+
typeof this.data[key].value !== 'object') {
|
|
257
|
+
return {};
|
|
543
258
|
}
|
|
544
|
-
|
|
259
|
+
|
|
260
|
+
// 返回哈希表的副本
|
|
261
|
+
return { ...this.data[key].value };
|
|
262
|
+
} catch (error) {
|
|
263
|
+
this.log.error('[cachebase] hgetall操作失败:', error);
|
|
264
|
+
throw error;
|
|
265
|
+
}
|
|
545
266
|
}
|
|
546
267
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
// 获取当前值或默认为0
|
|
566
|
-
let currentValue = 0;
|
|
567
|
-
if (this.data[key] && typeof this.data[key].value === 'number') {
|
|
568
|
-
currentValue = this.data[key].value;
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
// 执行整数加法
|
|
572
|
-
const result = currentValue + parseInt(value, 10);
|
|
573
|
-
|
|
574
|
-
// 保存结果
|
|
575
|
-
this.data[key] = { value: result, expire: 0 };
|
|
576
|
-
// 添加到列表
|
|
577
|
-
if (!this.list.includes(key)) {
|
|
578
|
-
this.list.push(key);
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
// 触发后置事件
|
|
582
|
-
this.emit('add_after', {
|
|
583
|
-
key,
|
|
584
|
-
value: parseInt(value, 10),
|
|
585
|
-
result
|
|
586
|
-
});
|
|
587
|
-
resolve(result);
|
|
588
|
-
} catch (error) {
|
|
589
|
-
// 触发错误事件
|
|
590
|
-
this.emit('add_error', {
|
|
591
|
-
key,
|
|
592
|
-
value: parseInt(value, 10),
|
|
593
|
-
error
|
|
594
|
-
});
|
|
595
|
-
$.log.error('[cachebase] add操作失败:', error);
|
|
596
|
-
resolve(0);
|
|
268
|
+
/**
|
|
269
|
+
* 删除哈希表字段
|
|
270
|
+
* @param {string} key - 键名
|
|
271
|
+
* @param {string} field - 字段名
|
|
272
|
+
* @returns {Promise<number>} - 返回删除的字段数量
|
|
273
|
+
*/
|
|
274
|
+
async hdel(key, field) {
|
|
275
|
+
try {
|
|
276
|
+
this.emit('hdel_before', { key, field });
|
|
277
|
+
|
|
278
|
+
// 检查键是否存在且未过期
|
|
279
|
+
if (!this.data.hasOwnProperty(key) ||
|
|
280
|
+
(this.data[key].expire > 0 && Date.now() > this.data[key].expire) ||
|
|
281
|
+
typeof this.data[key].value !== 'object' ||
|
|
282
|
+
!this.data[key].value.hasOwnProperty(field)) {
|
|
283
|
+
this.emit('hdel_after', { key, field, result: 0 });
|
|
284
|
+
return 0;
|
|
597
285
|
}
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
//
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
};
|
|
611
|
-
this.emit('list_set_before', beforeEventData);
|
|
612
|
-
|
|
613
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
614
|
-
if (beforeEventData.cancel) {
|
|
615
|
-
resolve(0);
|
|
616
|
-
return;
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
// 确保值是数组
|
|
620
|
-
if (!Array.isArray(value)) {
|
|
621
|
-
this.emit('list_set_error', {
|
|
622
|
-
key,
|
|
623
|
-
value,
|
|
624
|
-
error: new Error('值必须是数组')
|
|
625
|
-
});
|
|
626
|
-
resolve(0);
|
|
627
|
-
return;
|
|
628
|
-
}
|
|
629
|
-
|
|
630
|
-
// 设置数组
|
|
631
|
-
this.data[key] = { value, expire: 0 };
|
|
632
|
-
// 添加到列表
|
|
633
|
-
if (!this.list.includes(key)) {
|
|
634
|
-
this.list.push(key);
|
|
286
|
+
|
|
287
|
+
// 删除字段
|
|
288
|
+
delete this.data[key].value[field];
|
|
289
|
+
|
|
290
|
+
// 检查哈希表是否为空
|
|
291
|
+
const hashKeys = Object.keys(this.data[key].value);
|
|
292
|
+
if (hashKeys.length === 0) {
|
|
293
|
+
// 删除空哈希表
|
|
294
|
+
delete this.data[key];
|
|
295
|
+
const index = this.list.indexOf(key);
|
|
296
|
+
if (index !== -1) {
|
|
297
|
+
this.list.splice(index, 1);
|
|
635
298
|
}
|
|
636
|
-
|
|
637
|
-
// 触发后置事件
|
|
638
|
-
this.emit('list_set_after', {
|
|
639
|
-
key,
|
|
640
|
-
value,
|
|
641
|
-
result: 1
|
|
642
|
-
});
|
|
643
|
-
resolve(1);
|
|
644
|
-
} catch (error) {
|
|
645
|
-
// 触发错误事件
|
|
646
|
-
this.emit('list_set_error', {
|
|
647
|
-
key,
|
|
648
|
-
value,
|
|
649
|
-
error
|
|
650
|
-
});
|
|
651
|
-
$.log.error('[cachebase] list_set操作失败:', error);
|
|
652
|
-
resolve(0);
|
|
653
299
|
}
|
|
654
|
-
|
|
300
|
+
|
|
301
|
+
this.emit('hdel_after', { key, field, result: 1 });
|
|
302
|
+
return 1;
|
|
303
|
+
} catch (error) {
|
|
304
|
+
this.emit('hdel_error', { key, field, error });
|
|
305
|
+
this.log.error('[cachebase] hdel操作失败:', error);
|
|
306
|
+
throw error;
|
|
307
|
+
}
|
|
655
308
|
}
|
|
656
309
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
// 确保列表存在
|
|
676
|
-
if (!this.data[key]) {
|
|
677
|
-
this.data[key] = { value: [], expire: 0 };
|
|
678
|
-
// 添加到列表
|
|
310
|
+
/**
|
|
311
|
+
* 批量设置键值
|
|
312
|
+
* @param {Object} keyValues - 键值对对象
|
|
313
|
+
* @returns {Promise<string>} - 返回'OK'
|
|
314
|
+
*/
|
|
315
|
+
async mset(keyValues) {
|
|
316
|
+
try {
|
|
317
|
+
this.emit('mset_before', { keyValues });
|
|
318
|
+
|
|
319
|
+
if (typeof keyValues !== 'object' || keyValues === null) {
|
|
320
|
+
throw new Error('[cachebase] mset参数必须是对象');
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// 批量设置键值
|
|
324
|
+
for (const key in keyValues) {
|
|
325
|
+
if (keyValues.hasOwnProperty(key)) {
|
|
326
|
+
this.data[key] = { value: keyValues[key], expire: 0 };
|
|
679
327
|
if (!this.list.includes(key)) {
|
|
680
328
|
this.list.push(key);
|
|
681
329
|
}
|
|
682
|
-
} else if (!Array.isArray(this.data[key].value)) {
|
|
683
|
-
this.data[key].value = [];
|
|
684
330
|
}
|
|
685
|
-
|
|
686
|
-
// 添加元素到列表末尾
|
|
687
|
-
this.data[key].value.push(value);
|
|
688
|
-
|
|
689
|
-
// 触发后置事件
|
|
690
|
-
this.emit('list_add_after', {
|
|
691
|
-
key,
|
|
692
|
-
value,
|
|
693
|
-
result: this.data[key].value.length
|
|
694
|
-
});
|
|
695
|
-
resolve(this.data[key].value.length);
|
|
696
|
-
} catch (error) {
|
|
697
|
-
// 触发错误事件
|
|
698
|
-
this.emit('list_add_error', {
|
|
699
|
-
key,
|
|
700
|
-
value,
|
|
701
|
-
error
|
|
702
|
-
});
|
|
703
|
-
$.log.error('[cachebase] list_add操作失败:', error);
|
|
704
|
-
resolve(0);
|
|
705
331
|
}
|
|
706
|
-
|
|
332
|
+
|
|
333
|
+
this.emit('mset_after', { keyValues, result: 'OK' });
|
|
334
|
+
return 'OK';
|
|
335
|
+
} catch (error) {
|
|
336
|
+
this.emit('mset_error', { keyValues, error });
|
|
337
|
+
this.log.error('[cachebase] mset操作失败:', error);
|
|
338
|
+
throw error;
|
|
339
|
+
}
|
|
707
340
|
}
|
|
708
341
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
// 如果提供了新值且是数组,则替换
|
|
729
|
-
if (newValue && Array.isArray(newValue)) {
|
|
730
|
-
this.data[key].value = newValue;
|
|
342
|
+
/**
|
|
343
|
+
* 批量获取键值
|
|
344
|
+
* @param {Array<string>} keys - 键名数组
|
|
345
|
+
* @returns {Promise<Array>} - 返回值数组
|
|
346
|
+
*/
|
|
347
|
+
async mget(keys) {
|
|
348
|
+
try {
|
|
349
|
+
if (!Array.isArray(keys)) {
|
|
350
|
+
throw new Error('[cachebase] mget参数必须是数组');
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// 批量获取键值
|
|
354
|
+
const results = [];
|
|
355
|
+
for (const key of keys) {
|
|
356
|
+
if (this.data.hasOwnProperty(key)) {
|
|
357
|
+
// 检查是否过期
|
|
358
|
+
const item = this.data[key];
|
|
359
|
+
if (item.expire === 0 || Date.now() <= item.expire) {
|
|
360
|
+
results.push(item.value);
|
|
731
361
|
} else {
|
|
732
|
-
//
|
|
733
|
-
this.data[key]
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
this.emit('list_clear_after', {
|
|
738
|
-
key,
|
|
739
|
-
result: 1
|
|
740
|
-
});
|
|
741
|
-
resolve(1);
|
|
742
|
-
} else {
|
|
743
|
-
// 键不存在或值不是数组,如果提供了新值,则设置
|
|
744
|
-
if (newValue && Array.isArray(newValue)) {
|
|
745
|
-
this.data[key] = { value: newValue, expire: 0 };
|
|
746
|
-
// 添加到列表
|
|
747
|
-
if (!this.list.includes(key)) {
|
|
748
|
-
this.list.push(key);
|
|
362
|
+
// 删除过期键
|
|
363
|
+
delete this.data[key];
|
|
364
|
+
const index = this.list.indexOf(key);
|
|
365
|
+
if (index !== -1) {
|
|
366
|
+
this.list.splice(index, 1);
|
|
749
367
|
}
|
|
750
|
-
|
|
751
|
-
key,
|
|
752
|
-
result: 1
|
|
753
|
-
});
|
|
754
|
-
resolve(1);
|
|
755
|
-
} else {
|
|
756
|
-
this.emit('list_clear_after', {
|
|
757
|
-
key,
|
|
758
|
-
result: 0
|
|
759
|
-
});
|
|
760
|
-
resolve(0);
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
} catch (error) {
|
|
764
|
-
// 触发错误事件
|
|
765
|
-
this.emit('list_clear_error', {
|
|
766
|
-
key,
|
|
767
|
-
error
|
|
768
|
-
});
|
|
769
|
-
$.log.error('[cachebase] list_clear操作失败:', error);
|
|
770
|
-
resolve(0);
|
|
771
|
-
}
|
|
772
|
-
});
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
// 仅当键不存在时设置值方法
|
|
776
|
-
async setnx(key, value) {
|
|
777
|
-
return new Promise((resolve) => {
|
|
778
|
-
try {
|
|
779
|
-
// 触发前置事件
|
|
780
|
-
const beforeEventData = {
|
|
781
|
-
key,
|
|
782
|
-
value,
|
|
783
|
-
cancel: false
|
|
784
|
-
};
|
|
785
|
-
this.emit('setnx_before', beforeEventData);
|
|
786
|
-
|
|
787
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
788
|
-
if (beforeEventData.cancel) {
|
|
789
|
-
resolve(0);
|
|
790
|
-
return;
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
// 检查键是否不存在
|
|
794
|
-
if (!this.data.hasOwnProperty(key)) {
|
|
795
|
-
// 设置值
|
|
796
|
-
this.data[key] = { value, expire: 0 };
|
|
797
|
-
// 添加到列表
|
|
798
|
-
if (!this.list.includes(key)) {
|
|
799
|
-
this.list.push(key);
|
|
368
|
+
results.push(undefined);
|
|
800
369
|
}
|
|
801
|
-
|
|
802
|
-
// 触发后置事件
|
|
803
|
-
this.emit('setnx_after', {
|
|
804
|
-
key,
|
|
805
|
-
value,
|
|
806
|
-
result: 1
|
|
807
|
-
});
|
|
808
|
-
resolve(1);
|
|
809
370
|
} else {
|
|
810
|
-
|
|
811
|
-
this.emit('setnx_after', {
|
|
812
|
-
key,
|
|
813
|
-
value,
|
|
814
|
-
result: 0
|
|
815
|
-
});
|
|
816
|
-
resolve(0);
|
|
371
|
+
results.push(undefined);
|
|
817
372
|
}
|
|
818
|
-
} catch (error) {
|
|
819
|
-
// 触发错误事件
|
|
820
|
-
this.emit('setnx_error', {
|
|
821
|
-
key,
|
|
822
|
-
value,
|
|
823
|
-
error
|
|
824
|
-
});
|
|
825
|
-
$.log.error('[cachebase] setnx操作失败:', error);
|
|
826
|
-
resolve(0);
|
|
827
373
|
}
|
|
828
|
-
|
|
374
|
+
|
|
375
|
+
return results;
|
|
376
|
+
} catch (error) {
|
|
377
|
+
this.log.error('[cachebase] mget操作失败:', error);
|
|
378
|
+
throw error;
|
|
379
|
+
}
|
|
829
380
|
}
|
|
830
381
|
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
};
|
|
842
|
-
this.emit('setex_before', beforeEventData);
|
|
843
|
-
|
|
844
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
845
|
-
if (beforeEventData.cancel) {
|
|
846
|
-
resolve(0);
|
|
847
|
-
return;
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
// 计算过期时间
|
|
851
|
-
const expireTime = Date.now() + (parseInt(seconds, 10) * 1000);
|
|
852
|
-
|
|
853
|
-
// 设置值和过期时间
|
|
854
|
-
this.data[key] = { value, expire: expireTime };
|
|
855
|
-
// 添加到列表
|
|
856
|
-
if (!this.list.includes(key)) {
|
|
857
|
-
this.list.push(key);
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
// 触发后置事件,使用ttl替代seconds
|
|
861
|
-
this.emit('setex_after', {
|
|
862
|
-
key,
|
|
863
|
-
value,
|
|
864
|
-
ttl: parseInt(seconds, 10),
|
|
865
|
-
result: "OK"
|
|
866
|
-
});
|
|
867
|
-
resolve("OK");
|
|
868
|
-
} catch (error) {
|
|
869
|
-
// 触发错误事件,使用ttl替代seconds
|
|
870
|
-
this.emit('setex_error', {
|
|
871
|
-
key,
|
|
872
|
-
value,
|
|
873
|
-
ttl: parseInt(seconds, 10),
|
|
874
|
-
error
|
|
875
|
-
});
|
|
876
|
-
$.log.error('[cachebase] setex操作失败:', error);
|
|
877
|
-
resolve(0);
|
|
382
|
+
/**
|
|
383
|
+
* 获取键的剩余生存时间
|
|
384
|
+
* @param {string} key - 键名
|
|
385
|
+
* @returns {Promise<number>} - 返回剩余时间(秒),-1表示永不过期,-2表示键不存在
|
|
386
|
+
*/
|
|
387
|
+
async ttl(key) {
|
|
388
|
+
try {
|
|
389
|
+
// 检查键是否存在
|
|
390
|
+
if (!this.data.hasOwnProperty(key)) {
|
|
391
|
+
return -2;
|
|
878
392
|
}
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
cancel: false
|
|
891
|
-
};
|
|
892
|
-
this.emit('setrange_before', beforeEventData);
|
|
893
|
-
|
|
894
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
895
|
-
if (beforeEventData.cancel) {
|
|
896
|
-
resolve('ERR');
|
|
897
|
-
return;
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
const obj = this.data[key];
|
|
901
|
-
if (obj) {
|
|
902
|
-
// 确保值为字符串类型
|
|
903
|
-
let val = String(obj.value || '');
|
|
904
|
-
index = Math.max(0, parseInt(index) || 0);
|
|
905
|
-
|
|
906
|
-
// 处理index超出字符串长度的情况
|
|
907
|
-
if (index > val.length) {
|
|
908
|
-
// 填充空白字符
|
|
909
|
-
val = val.padEnd(index, '');
|
|
393
|
+
|
|
394
|
+
const item = this.data[key];
|
|
395
|
+
|
|
396
|
+
// 检查是否过期
|
|
397
|
+
if (item.expire > 0) {
|
|
398
|
+
if (Date.now() > item.expire) {
|
|
399
|
+
// 键已过期,删除并返回-2
|
|
400
|
+
delete this.data[key];
|
|
401
|
+
const index = this.list.indexOf(key);
|
|
402
|
+
if (index !== -1) {
|
|
403
|
+
this.list.splice(index, 1);
|
|
910
404
|
}
|
|
911
|
-
|
|
912
|
-
const start = val.substring(0, index);
|
|
913
|
-
const end = val.substring(index, val.length);
|
|
914
|
-
obj.value = start + value + end;
|
|
915
|
-
|
|
916
|
-
// 触发后置事件
|
|
917
|
-
this.emit('setrange_after', {
|
|
918
|
-
key,
|
|
919
|
-
value: { index, value },
|
|
920
|
-
result: obj.value.length
|
|
921
|
-
});
|
|
922
|
-
resolve(obj.value.length);
|
|
405
|
+
return -2;
|
|
923
406
|
} else {
|
|
924
|
-
|
|
407
|
+
// 计算剩余时间
|
|
408
|
+
const ttl = Math.floor((item.expire - Date.now()) / 1000);
|
|
409
|
+
return ttl;
|
|
925
410
|
}
|
|
926
|
-
}
|
|
927
|
-
//
|
|
928
|
-
|
|
929
|
-
key,
|
|
930
|
-
value: { index, value },
|
|
931
|
-
error
|
|
932
|
-
});
|
|
933
|
-
$.log.error('[cachebase] setrange操作失败:', error);
|
|
934
|
-
resolve('ERR');
|
|
411
|
+
} else {
|
|
412
|
+
// 永不过期
|
|
413
|
+
return -1;
|
|
935
414
|
}
|
|
936
|
-
})
|
|
415
|
+
} catch (error) {
|
|
416
|
+
this.log.error('[cachebase] ttl操作失败:', error);
|
|
417
|
+
throw error;
|
|
418
|
+
}
|
|
937
419
|
}
|
|
938
420
|
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
resolve([]);
|
|
954
|
-
return;
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
// 执行实际操作
|
|
958
|
-
const obj = this.data[key];
|
|
959
|
-
let result = [];
|
|
960
|
-
if (obj && Array.isArray(obj.value)) {
|
|
961
|
-
if (end === -1) {
|
|
962
|
-
result = obj.value.slice(start);
|
|
963
|
-
} else {
|
|
964
|
-
result = obj.value.slice(start, end + 1);
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
|
|
968
|
-
// 触发后置事件
|
|
969
|
-
this.emit('list_get_after', {
|
|
970
|
-
key,
|
|
971
|
-
value: { start, end },
|
|
972
|
-
result
|
|
973
|
-
});
|
|
974
|
-
resolve(result);
|
|
975
|
-
} catch (error) {
|
|
976
|
-
// 触发错误事件
|
|
977
|
-
this.emit('list_get_error', {
|
|
978
|
-
key,
|
|
979
|
-
value: { start, end },
|
|
980
|
-
error
|
|
981
|
-
});
|
|
982
|
-
$.log.error('[cachebase] list_get操作失败:', error);
|
|
983
|
-
resolve([]);
|
|
421
|
+
/**
|
|
422
|
+
* 设置键的过期时间
|
|
423
|
+
* @param {string} key - 键名
|
|
424
|
+
* @param {number} seconds - 过期时间(秒)
|
|
425
|
+
* @returns {Promise<number>} - 返回1表示设置成功,0表示键不存在
|
|
426
|
+
*/
|
|
427
|
+
async expire(key, seconds) {
|
|
428
|
+
try {
|
|
429
|
+
this.emit('expire_before', { key, seconds });
|
|
430
|
+
|
|
431
|
+
// 检查键是否存在
|
|
432
|
+
if (!this.data.hasOwnProperty(key)) {
|
|
433
|
+
this.emit('expire_after', { key, seconds, result: 0 });
|
|
434
|
+
return 0;
|
|
984
435
|
}
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
};
|
|
998
|
-
this.emit('getrange_before', beforeEventData);
|
|
999
|
-
|
|
1000
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
1001
|
-
if (beforeEventData.cancel) {
|
|
1002
|
-
resolve('');
|
|
1003
|
-
return;
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
// 执行实际操作
|
|
1007
|
-
const obj = this.data[key];
|
|
1008
|
-
let result = '';
|
|
1009
|
-
if (obj && typeof obj.value === 'string') {
|
|
1010
|
-
// 处理负数索引
|
|
1011
|
-
if (start < 0) start = Math.max(0, obj.value.length + start);
|
|
1012
|
-
if (end < 0) end = Math.max(0, obj.value.length + end);
|
|
1013
|
-
|
|
1014
|
-
// 确保索引在有效范围内
|
|
1015
|
-
start = Math.max(0, start);
|
|
1016
|
-
end = Math.min(obj.value.length - 1, end);
|
|
1017
|
-
|
|
1018
|
-
if (start <= end) {
|
|
1019
|
-
result = obj.value.substring(start, end + 1);
|
|
1020
|
-
}
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
// 触发后置事件
|
|
1024
|
-
this.emit('getrange_after', {
|
|
1025
|
-
key,
|
|
1026
|
-
value: { start, end },
|
|
1027
|
-
result
|
|
1028
|
-
});
|
|
1029
|
-
resolve(result);
|
|
1030
|
-
} catch (error) {
|
|
1031
|
-
// 触发错误事件
|
|
1032
|
-
this.emit('getrange_error', {
|
|
1033
|
-
key,
|
|
1034
|
-
value: { start, end },
|
|
1035
|
-
error
|
|
1036
|
-
});
|
|
1037
|
-
$.log.error('[cachebase] getrange操作失败:', error);
|
|
1038
|
-
resolve('');
|
|
436
|
+
|
|
437
|
+
// 检查是否已过期
|
|
438
|
+
const item = this.data[key];
|
|
439
|
+
if (item.expire > 0 && Date.now() > item.expire) {
|
|
440
|
+
// 键已过期,删除并返回0
|
|
441
|
+
delete this.data[key];
|
|
442
|
+
const index = this.list.indexOf(key);
|
|
443
|
+
if (index !== -1) {
|
|
444
|
+
this.list.splice(index, 1);
|
|
445
|
+
}
|
|
446
|
+
this.emit('expire_after', { key, seconds, result: 0 });
|
|
447
|
+
return 0;
|
|
1039
448
|
}
|
|
1040
|
-
|
|
449
|
+
|
|
450
|
+
// 设置过期时间
|
|
451
|
+
this.data[key].expire = Date.now() + seconds * 1000;
|
|
452
|
+
|
|
453
|
+
this.emit('expire_after', { key, seconds, result: 1 });
|
|
454
|
+
return 1;
|
|
455
|
+
} catch (error) {
|
|
456
|
+
this.emit('expire_error', { key, seconds, error });
|
|
457
|
+
this.log.error('[cachebase] expire操作失败:', error);
|
|
458
|
+
throw error;
|
|
459
|
+
}
|
|
1041
460
|
}
|
|
1042
461
|
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
if (beforeEventData.cancel) {
|
|
1057
|
-
resolve(0);
|
|
1058
|
-
return;
|
|
1059
|
-
}
|
|
1060
|
-
|
|
1061
|
-
// 执行实际操作
|
|
1062
|
-
const obj = this.data[key];
|
|
1063
|
-
let result = 0;
|
|
1064
|
-
if (obj && Array.isArray(obj.value)) {
|
|
1065
|
-
result = obj.value.includes(value) ? 1 : 0;
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1068
|
-
// 触发后置事件
|
|
1069
|
-
this.emit('list_has_after', {
|
|
1070
|
-
key,
|
|
1071
|
-
value,
|
|
1072
|
-
result
|
|
1073
|
-
});
|
|
1074
|
-
resolve(result);
|
|
1075
|
-
} catch (error) {
|
|
1076
|
-
// 触发错误事件
|
|
1077
|
-
this.emit('list_has_error', {
|
|
1078
|
-
key,
|
|
1079
|
-
value,
|
|
1080
|
-
error
|
|
1081
|
-
});
|
|
1082
|
-
$.log.error('[cachebase] list_has操作失败:', error);
|
|
1083
|
-
resolve(0);
|
|
462
|
+
/**
|
|
463
|
+
* 移除键的过期时间
|
|
464
|
+
* @param {string} key - 键名
|
|
465
|
+
* @returns {Promise<number>} - 返回1表示移除成功,0表示键不存在或没有过期时间
|
|
466
|
+
*/
|
|
467
|
+
async persist(key) {
|
|
468
|
+
try {
|
|
469
|
+
this.emit('persist_before', { key });
|
|
470
|
+
|
|
471
|
+
// 检查键是否存在
|
|
472
|
+
if (!this.data.hasOwnProperty(key)) {
|
|
473
|
+
this.emit('persist_after', { key, result: 0 });
|
|
474
|
+
return 0;
|
|
1084
475
|
}
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
this.emit('exists_before', beforeEventData);
|
|
1098
|
-
|
|
1099
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
1100
|
-
if (beforeEventData.cancel) {
|
|
1101
|
-
resolve(0);
|
|
1102
|
-
return;
|
|
1103
|
-
}
|
|
1104
|
-
|
|
1105
|
-
// 执行实际操作
|
|
1106
|
-
const result = key in this.data ? 1 : 0;
|
|
1107
|
-
|
|
1108
|
-
// 触发后置事件
|
|
1109
|
-
this.emit('exists_after', {
|
|
1110
|
-
key,
|
|
1111
|
-
result
|
|
1112
|
-
});
|
|
1113
|
-
resolve(result);
|
|
1114
|
-
} catch (error) {
|
|
1115
|
-
// 触发错误事件
|
|
1116
|
-
this.emit('exists_error', {
|
|
1117
|
-
key,
|
|
1118
|
-
error
|
|
1119
|
-
});
|
|
1120
|
-
$.log.error('[cachebase] exists操作失败:', error);
|
|
1121
|
-
resolve(0);
|
|
476
|
+
|
|
477
|
+
// 检查是否已过期
|
|
478
|
+
const item = this.data[key];
|
|
479
|
+
if (item.expire > 0 && Date.now() > item.expire) {
|
|
480
|
+
// 键已过期,删除并返回0
|
|
481
|
+
delete this.data[key];
|
|
482
|
+
const index = this.list.indexOf(key);
|
|
483
|
+
if (index !== -1) {
|
|
484
|
+
this.list.splice(index, 1);
|
|
485
|
+
}
|
|
486
|
+
this.emit('persist_after', { key, result: 0 });
|
|
487
|
+
return 0;
|
|
1122
488
|
}
|
|
1123
|
-
|
|
489
|
+
|
|
490
|
+
// 检查是否有过期时间
|
|
491
|
+
if (item.expire === 0) {
|
|
492
|
+
// 没有过期时间,返回0
|
|
493
|
+
this.emit('persist_after', { key, result: 0 });
|
|
494
|
+
return 0;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// 移除过期时间
|
|
498
|
+
this.data[key].expire = 0;
|
|
499
|
+
|
|
500
|
+
this.emit('persist_after', { key, result: 1 });
|
|
501
|
+
return 1;
|
|
502
|
+
} catch (error) {
|
|
503
|
+
this.emit('persist_error', { key, error });
|
|
504
|
+
this.log.error('[cachebase] persist操作失败:', error);
|
|
505
|
+
throw error;
|
|
506
|
+
}
|
|
1124
507
|
}
|
|
1125
508
|
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
// 执行实际操作
|
|
1144
|
-
const result = key in this.data ? 1 : 0;
|
|
1145
|
-
|
|
1146
|
-
// 触发后置事件
|
|
1147
|
-
this.emit('has_after', {
|
|
1148
|
-
key,
|
|
1149
|
-
result
|
|
1150
|
-
});
|
|
1151
|
-
resolve(result);
|
|
1152
|
-
} catch (error) {
|
|
1153
|
-
// 触发错误事件
|
|
1154
|
-
this.emit('has_error', {
|
|
1155
|
-
key,
|
|
1156
|
-
error
|
|
1157
|
-
});
|
|
1158
|
-
$.log.error('[cachebase] has操作失败:', error);
|
|
1159
|
-
resolve(0);
|
|
509
|
+
/**
|
|
510
|
+
* 获取所有键名
|
|
511
|
+
* @param {string} pattern - 模式匹配
|
|
512
|
+
* @returns {Promise<Array>} - 返回键名数组
|
|
513
|
+
*/
|
|
514
|
+
async keys(pattern = '*') {
|
|
515
|
+
try {
|
|
516
|
+
// 支持通配符匹配
|
|
517
|
+
let filteredKeys = [];
|
|
518
|
+
if (pattern === '*') {
|
|
519
|
+
// 通配符匹配所有
|
|
520
|
+
filteredKeys = [...this.list];
|
|
521
|
+
} else {
|
|
522
|
+
// 简单的通配符匹配
|
|
523
|
+
const regex = new RegExp(pattern.replace(/\*/g, '.*'));
|
|
524
|
+
filteredKeys = this.list.filter(key => regex.test(key));
|
|
1160
525
|
}
|
|
1161
|
-
|
|
526
|
+
|
|
527
|
+
return filteredKeys;
|
|
528
|
+
} catch (error) {
|
|
529
|
+
this.log.error('[cachebase] keys操作失败:', error);
|
|
530
|
+
throw error;
|
|
531
|
+
}
|
|
1162
532
|
}
|
|
1163
533
|
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
if (beforeEventData.cancel) {
|
|
1178
|
-
resolve(maxAge !== undefined ? 0 : -2);
|
|
1179
|
-
return;
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
|
-
// 执行实际操作
|
|
1183
|
-
const obj = this.data[key];
|
|
1184
|
-
let result;
|
|
1185
|
-
|
|
1186
|
-
if (!obj) {
|
|
1187
|
-
result = -2; // 键不存在
|
|
1188
|
-
} else if (maxAge !== undefined) {
|
|
1189
|
-
// 设置过期时间
|
|
1190
|
-
if (maxAge === -1) {
|
|
1191
|
-
obj.expire = 0; // 永不过期
|
|
1192
|
-
} else {
|
|
1193
|
-
obj.expire = Date.now() + (parseInt(maxAge, 10) * 1000);
|
|
1194
|
-
}
|
|
1195
|
-
result = 1;
|
|
1196
|
-
} else {
|
|
1197
|
-
// 查询过期时间
|
|
1198
|
-
if (obj.expire === 0) {
|
|
1199
|
-
result = -1; // 永不过期
|
|
1200
|
-
} else {
|
|
1201
|
-
const remaining = Math.floor((obj.expire - Date.now()) / 1000);
|
|
1202
|
-
result = remaining > 0 ? remaining : -2; // -2表示已过期
|
|
534
|
+
/**
|
|
535
|
+
* 获取键数量
|
|
536
|
+
* @returns {Promise<number>} - 返回键数量
|
|
537
|
+
*/
|
|
538
|
+
async dbsize() {
|
|
539
|
+
try {
|
|
540
|
+
// 过滤掉已过期的键
|
|
541
|
+
let count = 0;
|
|
542
|
+
for (const key of this.list) {
|
|
543
|
+
if (this.data.hasOwnProperty(key)) {
|
|
544
|
+
const item = this.data[key];
|
|
545
|
+
if (item.expire === 0 || Date.now() <= item.expire) {
|
|
546
|
+
count++;
|
|
1203
547
|
}
|
|
1204
548
|
}
|
|
1205
|
-
|
|
1206
|
-
// 触发后置事件
|
|
1207
|
-
this.emit('ttl_after', {
|
|
1208
|
-
key,
|
|
1209
|
-
value: maxAge !== undefined ? { ttl: maxAge } : undefined,
|
|
1210
|
-
result
|
|
1211
|
-
});
|
|
1212
|
-
resolve(result);
|
|
1213
|
-
} catch (error) {
|
|
1214
|
-
// 触发错误事件
|
|
1215
|
-
this.emit('ttl_error', {
|
|
1216
|
-
key,
|
|
1217
|
-
value: maxAge !== undefined ? { ttl: maxAge } : undefined,
|
|
1218
|
-
error
|
|
1219
|
-
});
|
|
1220
|
-
$.log.error('[cachebase] ttl操作失败:', error);
|
|
1221
|
-
resolve(-2);
|
|
1222
549
|
}
|
|
1223
|
-
|
|
550
|
+
|
|
551
|
+
return count;
|
|
552
|
+
} catch (error) {
|
|
553
|
+
this.log.error('[cachebase] dbsize操作失败:', error);
|
|
554
|
+
throw error;
|
|
555
|
+
}
|
|
1224
556
|
}
|
|
1225
557
|
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
// 执行实际操作
|
|
1244
|
-
let result;
|
|
1245
|
-
if (!pattern || pattern === '*') {
|
|
1246
|
-
result = [...this.list];
|
|
1247
|
-
} else {
|
|
1248
|
-
// 转换模式为正则表达式
|
|
1249
|
-
const regexPattern = pattern
|
|
1250
|
-
.replace(/\./g, '\\.')
|
|
1251
|
-
.replace(/\*/g, '.*')
|
|
1252
|
-
.replace(/\?/g, '.');
|
|
1253
|
-
const regex = new RegExp(`^${regexPattern}$`);
|
|
1254
|
-
|
|
1255
|
-
// 过滤匹配的键
|
|
1256
|
-
result = this.list.filter(key => regex.test(key));
|
|
558
|
+
/**
|
|
559
|
+
* 设置键值并返回旧值
|
|
560
|
+
* @param {string} key - 键名
|
|
561
|
+
* @param {*} value - 键值
|
|
562
|
+
* @returns {Promise<*>} - 返回旧值
|
|
563
|
+
*/
|
|
564
|
+
async getset(key, value) {
|
|
565
|
+
try {
|
|
566
|
+
this.emit('getset_before', { key, value });
|
|
567
|
+
|
|
568
|
+
// 获取旧值
|
|
569
|
+
let oldValue = undefined;
|
|
570
|
+
if (this.data.hasOwnProperty(key)) {
|
|
571
|
+
const item = this.data[key];
|
|
572
|
+
if (!(item.expire > 0 && Date.now() > item.expire)) {
|
|
573
|
+
oldValue = item.value;
|
|
1257
574
|
}
|
|
1258
|
-
|
|
1259
|
-
// 触发后置事件
|
|
1260
|
-
this.emit('keys_after', {
|
|
1261
|
-
value: { pattern },
|
|
1262
|
-
result
|
|
1263
|
-
});
|
|
1264
|
-
resolve(result);
|
|
1265
|
-
} catch (error) {
|
|
1266
|
-
// 触发错误事件
|
|
1267
|
-
this.emit('keys_error', {
|
|
1268
|
-
value: { pattern },
|
|
1269
|
-
error
|
|
1270
|
-
});
|
|
1271
|
-
$.log.error('[cachebase] keys操作失败:', error);
|
|
1272
|
-
resolve([]);
|
|
1273
575
|
}
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
// 触发前置事件
|
|
1282
|
-
const beforeEventData = {
|
|
1283
|
-
value: { pattern },
|
|
1284
|
-
cancel: false
|
|
1285
|
-
};
|
|
1286
|
-
this.emit('clear_before', beforeEventData);
|
|
1287
|
-
|
|
1288
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
1289
|
-
if (beforeEventData.cancel) {
|
|
1290
|
-
resolve(0);
|
|
1291
|
-
return;
|
|
1292
|
-
}
|
|
1293
|
-
|
|
1294
|
-
// 执行实际操作
|
|
1295
|
-
let keysToDelete;
|
|
1296
|
-
|
|
1297
|
-
if (!pattern || pattern === '*') {
|
|
1298
|
-
keysToDelete = [...this.list];
|
|
1299
|
-
} else {
|
|
1300
|
-
// 转换模式为正则表达式
|
|
1301
|
-
const regexPattern = pattern
|
|
1302
|
-
.replace(/\./g, '\\.')
|
|
1303
|
-
.replace(/\*/g, '.*')
|
|
1304
|
-
.replace(/\?/g, '.');
|
|
1305
|
-
const regex = new RegExp(`^${regexPattern}$`);
|
|
1306
|
-
|
|
1307
|
-
keysToDelete = this.list.filter(key => regex.test(key));
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
|
-
// 删除匹配的键
|
|
1311
|
-
keysToDelete.forEach(key => {
|
|
1312
|
-
delete this.data[key];
|
|
1313
|
-
const index = this.list.indexOf(key);
|
|
1314
|
-
if (index > -1) {
|
|
1315
|
-
this.list.splice(index, 1);
|
|
1316
|
-
}
|
|
1317
|
-
});
|
|
1318
|
-
|
|
1319
|
-
// 触发后置事件
|
|
1320
|
-
this.emit('clear_after', {
|
|
1321
|
-
value: { pattern },
|
|
1322
|
-
result: keysToDelete.length
|
|
1323
|
-
});
|
|
1324
|
-
resolve(keysToDelete.length);
|
|
1325
|
-
} catch (error) {
|
|
1326
|
-
// 触发错误事件
|
|
1327
|
-
this.emit('clear_error', {
|
|
1328
|
-
value: { pattern },
|
|
1329
|
-
error
|
|
1330
|
-
});
|
|
1331
|
-
$.log.error('[cachebase] clear操作失败:', error);
|
|
1332
|
-
resolve(0);
|
|
576
|
+
|
|
577
|
+
// 设置新值
|
|
578
|
+
this.data[key] = { value, expire: 0 };
|
|
579
|
+
|
|
580
|
+
// 添加到键列表
|
|
581
|
+
if (!this.list.includes(key)) {
|
|
582
|
+
this.list.push(key);
|
|
1333
583
|
}
|
|
1334
|
-
|
|
584
|
+
|
|
585
|
+
this.emit('getset_after', { key, value, result: oldValue });
|
|
586
|
+
return oldValue;
|
|
587
|
+
} catch (error) {
|
|
588
|
+
this.emit('getset_error', { key, value, error });
|
|
589
|
+
this.log.error('[cachebase] getset操作失败:', error);
|
|
590
|
+
throw error;
|
|
591
|
+
}
|
|
1335
592
|
}
|
|
1336
593
|
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
if (beforeEventData.cancel) {
|
|
1351
|
-
resolve(null);
|
|
1352
|
-
return;
|
|
1353
|
-
}
|
|
1354
|
-
|
|
1355
|
-
// 执行实际操作
|
|
1356
|
-
const obj = this.data[key];
|
|
1357
|
-
let result = null;
|
|
1358
|
-
if (obj && typeof obj.value === 'object' && field in obj.value) {
|
|
1359
|
-
result = obj.value[field];
|
|
1360
|
-
}
|
|
1361
|
-
|
|
1362
|
-
// 触发后置事件
|
|
1363
|
-
this.emit('hget_after', {
|
|
1364
|
-
key,
|
|
1365
|
-
value: { field },
|
|
1366
|
-
result
|
|
1367
|
-
});
|
|
1368
|
-
resolve(result);
|
|
1369
|
-
} catch (error) {
|
|
1370
|
-
// 触发错误事件
|
|
1371
|
-
this.emit('hget_error', {
|
|
1372
|
-
key,
|
|
1373
|
-
value: { field },
|
|
1374
|
-
error
|
|
1375
|
-
});
|
|
1376
|
-
$.log.error('[cachebase] hget操作失败:', error);
|
|
1377
|
-
resolve(null);
|
|
594
|
+
/**
|
|
595
|
+
* 数值递增
|
|
596
|
+
* @param {string} key - 键名
|
|
597
|
+
* @returns {Promise<number>} - 返回递增后的值
|
|
598
|
+
*/
|
|
599
|
+
async incr(key) {
|
|
600
|
+
try {
|
|
601
|
+
this.emit('incr_before', { key });
|
|
602
|
+
|
|
603
|
+
// 获取当前值或默认为0
|
|
604
|
+
let currentValue = 0;
|
|
605
|
+
if (this.data.hasOwnProperty(key) && !this._checkExpire(key)) {
|
|
606
|
+
currentValue = parseFloat(this.data[key].value) || 0;
|
|
1378
607
|
}
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
cancel: false
|
|
1390
|
-
};
|
|
1391
|
-
this.emit('hgetall_before', beforeEventData);
|
|
1392
|
-
|
|
1393
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
1394
|
-
if (beforeEventData.cancel) {
|
|
1395
|
-
resolve({});
|
|
1396
|
-
return;
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
// 执行实际操作
|
|
1400
|
-
const obj = this.data[key];
|
|
1401
|
-
let result = {};
|
|
1402
|
-
if (obj && typeof obj.value === 'object') {
|
|
1403
|
-
result = {...obj.value};
|
|
1404
|
-
}
|
|
1405
|
-
|
|
1406
|
-
// 触发后置事件
|
|
1407
|
-
this.emit('hgetall_after', {
|
|
1408
|
-
key,
|
|
1409
|
-
result
|
|
1410
|
-
});
|
|
1411
|
-
resolve(result);
|
|
1412
|
-
} catch (error) {
|
|
1413
|
-
// 触发错误事件
|
|
1414
|
-
this.emit('hgetall_error', {
|
|
1415
|
-
key,
|
|
1416
|
-
error
|
|
1417
|
-
});
|
|
1418
|
-
$.log.error('[cachebase] hgetall操作失败:', error);
|
|
1419
|
-
resolve({});
|
|
608
|
+
|
|
609
|
+
// 递增
|
|
610
|
+
const result = currentValue + 1;
|
|
611
|
+
|
|
612
|
+
// 保存结果
|
|
613
|
+
this.data[key] = { value: result, expire: 0 };
|
|
614
|
+
|
|
615
|
+
// 如果键不存在于列表中,添加到列表
|
|
616
|
+
if (!this.list.includes(key)) {
|
|
617
|
+
this.list.push(key);
|
|
1420
618
|
}
|
|
1421
|
-
|
|
619
|
+
|
|
620
|
+
this.emit('incr_after', { key, result });
|
|
621
|
+
return result;
|
|
622
|
+
} catch (error) {
|
|
623
|
+
this.emit('incr_error', { key, error });
|
|
624
|
+
this.log.error('[cachebase] incr操作失败:', error);
|
|
625
|
+
throw error;
|
|
626
|
+
}
|
|
1422
627
|
}
|
|
1423
628
|
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
if (beforeEventData.cancel) {
|
|
1438
|
-
resolve(0);
|
|
1439
|
-
return;
|
|
1440
|
-
}
|
|
1441
|
-
|
|
1442
|
-
// 执行实际操作
|
|
1443
|
-
let result = 0;
|
|
1444
|
-
const obj = this.data[key];
|
|
1445
|
-
if (obj && typeof obj.value === 'object' && field in obj.value) {
|
|
1446
|
-
delete obj.value[field];
|
|
1447
|
-
// 如果哈希表变空了,删除整个键
|
|
1448
|
-
if (Object.keys(obj.value).length === 0) {
|
|
1449
|
-
delete this.data[key];
|
|
1450
|
-
const index = this.list.indexOf(key);
|
|
1451
|
-
if (index > -1) {
|
|
1452
|
-
this.list.splice(index, 1);
|
|
1453
|
-
}
|
|
1454
|
-
}
|
|
1455
|
-
result = 1;
|
|
1456
|
-
}
|
|
1457
|
-
|
|
1458
|
-
// 触发后置事件
|
|
1459
|
-
this.emit('hdel_after', {
|
|
1460
|
-
key,
|
|
1461
|
-
value: { field },
|
|
1462
|
-
result
|
|
1463
|
-
});
|
|
1464
|
-
resolve(result);
|
|
1465
|
-
} catch (error) {
|
|
1466
|
-
// 触发错误事件
|
|
1467
|
-
this.emit('hdel_error', {
|
|
1468
|
-
key,
|
|
1469
|
-
value: { field },
|
|
1470
|
-
error
|
|
1471
|
-
});
|
|
1472
|
-
$.log.error('[cachebase] hdel操作失败:', error);
|
|
1473
|
-
resolve(0);
|
|
629
|
+
/**
|
|
630
|
+
* 数值递减
|
|
631
|
+
* @param {string} key - 键名
|
|
632
|
+
* @returns {Promise<number>} - 返回递减后的值
|
|
633
|
+
*/
|
|
634
|
+
async decr(key) {
|
|
635
|
+
try {
|
|
636
|
+
this.emit('decr_before', { key });
|
|
637
|
+
|
|
638
|
+
// 获取当前值或默认为0
|
|
639
|
+
let currentValue = 0;
|
|
640
|
+
if (this.data.hasOwnProperty(key) && !this._checkExpire(key)) {
|
|
641
|
+
currentValue = parseFloat(this.data[key].value) || 0;
|
|
1474
642
|
}
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
cancel: false
|
|
1486
|
-
};
|
|
1487
|
-
this.emit('hkeys_before', beforeEventData);
|
|
1488
|
-
|
|
1489
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
1490
|
-
if (beforeEventData.cancel) {
|
|
1491
|
-
resolve([]);
|
|
1492
|
-
return;
|
|
1493
|
-
}
|
|
1494
|
-
|
|
1495
|
-
// 执行实际操作
|
|
1496
|
-
let result = [];
|
|
1497
|
-
const obj = this.data[key];
|
|
1498
|
-
if (obj && typeof obj.value === 'object') {
|
|
1499
|
-
result = Object.keys(obj.value);
|
|
1500
|
-
}
|
|
1501
|
-
|
|
1502
|
-
// 触发后置事件
|
|
1503
|
-
this.emit('hkeys_after', {
|
|
1504
|
-
key,
|
|
1505
|
-
result
|
|
1506
|
-
});
|
|
1507
|
-
resolve(result);
|
|
1508
|
-
} catch (error) {
|
|
1509
|
-
// 触发错误事件
|
|
1510
|
-
this.emit('hkeys_error', {
|
|
1511
|
-
key,
|
|
1512
|
-
error
|
|
1513
|
-
});
|
|
1514
|
-
$.log.error('[cachebase] hkeys操作失败:', error);
|
|
1515
|
-
resolve([]);
|
|
643
|
+
|
|
644
|
+
// 递减
|
|
645
|
+
const result = currentValue - 1;
|
|
646
|
+
|
|
647
|
+
// 保存结果
|
|
648
|
+
this.data[key] = { value: result, expire: 0 };
|
|
649
|
+
|
|
650
|
+
// 如果键不存在于列表中,添加到列表
|
|
651
|
+
if (!this.list.includes(key)) {
|
|
652
|
+
this.list.push(key);
|
|
1516
653
|
}
|
|
1517
|
-
|
|
654
|
+
|
|
655
|
+
this.emit('decr_after', { key, result });
|
|
656
|
+
return result;
|
|
657
|
+
} catch (error) {
|
|
658
|
+
this.emit('decr_error', { key, error });
|
|
659
|
+
this.log.error('[cachebase] decr操作失败:', error);
|
|
660
|
+
throw error;
|
|
661
|
+
}
|
|
1518
662
|
}
|
|
1519
663
|
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
return;
|
|
1535
|
-
}
|
|
1536
|
-
|
|
1537
|
-
// 执行实际操作
|
|
1538
|
-
let result = [];
|
|
1539
|
-
const obj = this.data[key];
|
|
1540
|
-
if (obj && typeof obj.value === 'object') {
|
|
1541
|
-
result = Object.values(obj.value);
|
|
1542
|
-
}
|
|
1543
|
-
|
|
1544
|
-
// 触发后置事件
|
|
1545
|
-
this.emit('hvals_after', {
|
|
1546
|
-
key,
|
|
1547
|
-
result
|
|
1548
|
-
});
|
|
1549
|
-
resolve(result);
|
|
1550
|
-
} catch (error) {
|
|
1551
|
-
// 触发错误事件
|
|
1552
|
-
this.emit('hvals_error', {
|
|
1553
|
-
key,
|
|
1554
|
-
error
|
|
1555
|
-
});
|
|
1556
|
-
$.log.error('[cachebase] hvals操作失败:', error);
|
|
1557
|
-
resolve([]);
|
|
664
|
+
/**
|
|
665
|
+
* 数值增加指定值
|
|
666
|
+
* @param {string} key - 键名
|
|
667
|
+
* @param {number} increment - 增加的值
|
|
668
|
+
* @returns {Promise<number>} - 返回增加后的值
|
|
669
|
+
*/
|
|
670
|
+
async incrby(key, increment) {
|
|
671
|
+
try {
|
|
672
|
+
this.emit('incrby_before', { key, increment });
|
|
673
|
+
|
|
674
|
+
// 获取当前值或默认为0
|
|
675
|
+
let currentValue = 0;
|
|
676
|
+
if (this.data.hasOwnProperty(key) && !this._checkExpire(key)) {
|
|
677
|
+
currentValue = parseFloat(this.data[key].value) || 0;
|
|
1558
678
|
}
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
cancel: false
|
|
1570
|
-
};
|
|
1571
|
-
this.emit('lpop_before', beforeEventData);
|
|
1572
|
-
|
|
1573
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
1574
|
-
if (beforeEventData.cancel) {
|
|
1575
|
-
resolve(null);
|
|
1576
|
-
return;
|
|
1577
|
-
}
|
|
1578
|
-
|
|
1579
|
-
// 执行实际操作
|
|
1580
|
-
const obj = this.data[key];
|
|
1581
|
-
let result = null;
|
|
1582
|
-
if (obj && Array.isArray(obj.value) && obj.value.length > 0) {
|
|
1583
|
-
result = obj.value.shift();
|
|
1584
|
-
// 如果列表变空了,删除整个键
|
|
1585
|
-
if (obj.value.length === 0) {
|
|
1586
|
-
delete this.data[key];
|
|
1587
|
-
const index = this.list.indexOf(key);
|
|
1588
|
-
if (index > -1) {
|
|
1589
|
-
this.list.splice(index, 1);
|
|
1590
|
-
}
|
|
1591
|
-
}
|
|
1592
|
-
}
|
|
1593
|
-
|
|
1594
|
-
// 触发后置事件
|
|
1595
|
-
this.emit('lpop_after', {
|
|
1596
|
-
key,
|
|
1597
|
-
result
|
|
1598
|
-
});
|
|
1599
|
-
resolve(result);
|
|
1600
|
-
} catch (error) {
|
|
1601
|
-
// 触发错误事件
|
|
1602
|
-
this.emit('lpop_error', {
|
|
1603
|
-
key,
|
|
1604
|
-
error
|
|
1605
|
-
});
|
|
1606
|
-
$.log.error('[cachebase] lpop操作失败:', error);
|
|
1607
|
-
resolve(null);
|
|
679
|
+
|
|
680
|
+
// 增加指定值
|
|
681
|
+
const result = currentValue + parseFloat(increment);
|
|
682
|
+
|
|
683
|
+
// 保存结果
|
|
684
|
+
this.data[key] = { value: result, expire: 0 };
|
|
685
|
+
|
|
686
|
+
// 如果键不存在于列表中,添加到列表
|
|
687
|
+
if (!this.list.includes(key)) {
|
|
688
|
+
this.list.push(key);
|
|
1608
689
|
}
|
|
1609
|
-
|
|
690
|
+
|
|
691
|
+
this.emit('incrby_after', { key, increment, result });
|
|
692
|
+
return result;
|
|
693
|
+
} catch (error) {
|
|
694
|
+
this.emit('incrby_error', { key, increment, error });
|
|
695
|
+
this.log.error('[cachebase] incrby操作失败:', error);
|
|
696
|
+
throw error;
|
|
697
|
+
}
|
|
1610
698
|
}
|
|
1611
699
|
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
resolve(0);
|
|
1627
|
-
return;
|
|
1628
|
-
}
|
|
1629
|
-
|
|
1630
|
-
// 确保列表存在
|
|
1631
|
-
if (!this.data[key]) {
|
|
1632
|
-
this.data[key] = { value: [], expire: 0 };
|
|
1633
|
-
// 添加到列表
|
|
1634
|
-
if (!this.list.includes(key)) {
|
|
1635
|
-
this.list.push(key);
|
|
1636
|
-
}
|
|
1637
|
-
} else if (!Array.isArray(this.data[key].value)) {
|
|
1638
|
-
this.data[key].value = [];
|
|
1639
|
-
}
|
|
1640
|
-
|
|
1641
|
-
// 将值添加到列表尾部
|
|
1642
|
-
this.data[key].value.push(...values);
|
|
1643
|
-
|
|
1644
|
-
// 触发后置事件
|
|
1645
|
-
this.emit('rpush_after', {
|
|
1646
|
-
key,
|
|
1647
|
-
value: { values },
|
|
1648
|
-
result: this.data[key].value.length
|
|
1649
|
-
});
|
|
1650
|
-
resolve(this.data[key].value.length);
|
|
1651
|
-
} catch (error) {
|
|
1652
|
-
// 触发错误事件
|
|
1653
|
-
this.emit('rpush_error', {
|
|
1654
|
-
key,
|
|
1655
|
-
value: { values },
|
|
1656
|
-
error
|
|
1657
|
-
});
|
|
1658
|
-
$.log.error('[cachebase] rpush操作失败:', error);
|
|
1659
|
-
resolve(0);
|
|
700
|
+
/**
|
|
701
|
+
* 数值减少指定值
|
|
702
|
+
* @param {string} key - 键名
|
|
703
|
+
* @param {number} decrement - 减少的值
|
|
704
|
+
* @returns {Promise<number>} - 返回减少后的值
|
|
705
|
+
*/
|
|
706
|
+
async decrby(key, decrement) {
|
|
707
|
+
try {
|
|
708
|
+
this.emit('decrby_before', { key, decrement });
|
|
709
|
+
|
|
710
|
+
// 获取当前值或默认为0
|
|
711
|
+
let currentValue = 0;
|
|
712
|
+
if (this.data.hasOwnProperty(key) && !this._checkExpire(key)) {
|
|
713
|
+
currentValue = parseFloat(this.data[key].value) || 0;
|
|
1660
714
|
}
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
cancel: false
|
|
1672
|
-
};
|
|
1673
|
-
this.emit('rpop_before', beforeEventData);
|
|
1674
|
-
|
|
1675
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
1676
|
-
if (beforeEventData.cancel) {
|
|
1677
|
-
resolve(null);
|
|
1678
|
-
return;
|
|
1679
|
-
}
|
|
1680
|
-
|
|
1681
|
-
// 执行实际操作
|
|
1682
|
-
const obj = this.data[key];
|
|
1683
|
-
let result = null;
|
|
1684
|
-
if (obj && Array.isArray(obj.value) && obj.value.length > 0) {
|
|
1685
|
-
result = obj.value.pop();
|
|
1686
|
-
// 如果列表变空了,删除整个键
|
|
1687
|
-
if (obj.value.length === 0) {
|
|
1688
|
-
delete this.data[key];
|
|
1689
|
-
const index = this.list.indexOf(key);
|
|
1690
|
-
if (index > -1) {
|
|
1691
|
-
this.list.splice(index, 1);
|
|
1692
|
-
}
|
|
1693
|
-
}
|
|
1694
|
-
}
|
|
1695
|
-
|
|
1696
|
-
// 触发后置事件
|
|
1697
|
-
this.emit('rpop_after', {
|
|
1698
|
-
key,
|
|
1699
|
-
result
|
|
1700
|
-
});
|
|
1701
|
-
resolve(result);
|
|
1702
|
-
} catch (error) {
|
|
1703
|
-
// 触发错误事件
|
|
1704
|
-
this.emit('rpop_error', {
|
|
1705
|
-
key,
|
|
1706
|
-
error
|
|
1707
|
-
});
|
|
1708
|
-
$.log.error('[cachebase] rpop操作失败:', error);
|
|
1709
|
-
resolve(null);
|
|
715
|
+
|
|
716
|
+
// 减少指定值
|
|
717
|
+
const result = currentValue - parseFloat(decrement);
|
|
718
|
+
|
|
719
|
+
// 保存结果
|
|
720
|
+
this.data[key] = { value: result, expire: 0 };
|
|
721
|
+
|
|
722
|
+
// 如果键不存在于列表中,添加到列表
|
|
723
|
+
if (!this.list.includes(key)) {
|
|
724
|
+
this.list.push(key);
|
|
1710
725
|
}
|
|
1711
|
-
|
|
726
|
+
|
|
727
|
+
this.emit('decrby_after', { key, decrement, result });
|
|
728
|
+
return result;
|
|
729
|
+
} catch (error) {
|
|
730
|
+
this.emit('decrby_error', { key, decrement, error });
|
|
731
|
+
this.log.error('[cachebase] decrby操作失败:', error);
|
|
732
|
+
throw error;
|
|
733
|
+
}
|
|
1712
734
|
}
|
|
1713
735
|
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
return;
|
|
1729
|
-
}
|
|
1730
|
-
|
|
1731
|
-
// 执行实际操作
|
|
1732
|
-
let result = 0;
|
|
1733
|
-
const obj = this.data[key];
|
|
1734
|
-
if (obj && Array.isArray(obj.value)) {
|
|
1735
|
-
result = obj.value.length;
|
|
1736
|
-
}
|
|
1737
|
-
|
|
1738
|
-
// 触发后置事件
|
|
1739
|
-
this.emit('llen_after', {
|
|
1740
|
-
key,
|
|
1741
|
-
result
|
|
1742
|
-
});
|
|
1743
|
-
resolve(result);
|
|
1744
|
-
} catch (error) {
|
|
1745
|
-
// 触发错误事件
|
|
1746
|
-
this.emit('llen_error', {
|
|
1747
|
-
key,
|
|
1748
|
-
error
|
|
1749
|
-
});
|
|
1750
|
-
$.log.error('[cachebase] llen操作失败:', error);
|
|
1751
|
-
resolve(0);
|
|
736
|
+
/**
|
|
737
|
+
* 浮点数增加指定值
|
|
738
|
+
* @param {string} key - 键名
|
|
739
|
+
* @param {number} increment - 增加的值
|
|
740
|
+
* @returns {Promise<number>} - 返回增加后的值
|
|
741
|
+
*/
|
|
742
|
+
async incrbyfloat(key, increment) {
|
|
743
|
+
try {
|
|
744
|
+
this.emit('incrbyfloat_before', { key, increment });
|
|
745
|
+
|
|
746
|
+
// 获取当前值或默认为0
|
|
747
|
+
let currentValue = 0;
|
|
748
|
+
if (this.data.hasOwnProperty(key) && !this._checkExpire(key)) {
|
|
749
|
+
currentValue = parseFloat(this.data[key].value) || 0;
|
|
1752
750
|
}
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
value,
|
|
1764
|
-
cancel: false
|
|
1765
|
-
};
|
|
1766
|
-
this.emit('srem_before', beforeEventData);
|
|
1767
|
-
|
|
1768
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
1769
|
-
if (beforeEventData.cancel) {
|
|
1770
|
-
resolve(0);
|
|
1771
|
-
return;
|
|
1772
|
-
}
|
|
1773
|
-
|
|
1774
|
-
// 执行实际操作
|
|
1775
|
-
let result = 0;
|
|
1776
|
-
const obj = this.data[key];
|
|
1777
|
-
if (obj && obj.value && obj.value.members) {
|
|
1778
|
-
if (obj.value.members.hasOwnProperty(value)) {
|
|
1779
|
-
delete obj.value.members[value];
|
|
1780
|
-
// 更新有序数组
|
|
1781
|
-
obj.value.sorted = Object.keys(obj.value.members);
|
|
1782
|
-
result = 1;
|
|
1783
|
-
// 如果集合变空了,删除整个键
|
|
1784
|
-
if (Object.keys(obj.value.members).length === 0) {
|
|
1785
|
-
delete this.data[key];
|
|
1786
|
-
const index = this.list.indexOf(key);
|
|
1787
|
-
if (index > -1) {
|
|
1788
|
-
this.list.splice(index, 1);
|
|
1789
|
-
}
|
|
1790
|
-
}
|
|
1791
|
-
}
|
|
1792
|
-
}
|
|
1793
|
-
|
|
1794
|
-
// 触发后置事件
|
|
1795
|
-
this.emit('srem_after', {
|
|
1796
|
-
key,
|
|
1797
|
-
value,
|
|
1798
|
-
result
|
|
1799
|
-
});
|
|
1800
|
-
resolve(result);
|
|
1801
|
-
} catch (error) {
|
|
1802
|
-
// 触发错误事件
|
|
1803
|
-
this.emit('srem_error', {
|
|
1804
|
-
key,
|
|
1805
|
-
value,
|
|
1806
|
-
error
|
|
1807
|
-
});
|
|
1808
|
-
$.log.error('[cachebase] srem操作失败:', error);
|
|
1809
|
-
resolve(0);
|
|
751
|
+
|
|
752
|
+
// 增加指定值
|
|
753
|
+
const result = currentValue + parseFloat(increment);
|
|
754
|
+
|
|
755
|
+
// 保存结果
|
|
756
|
+
this.data[key] = { value: result, expire: 0 };
|
|
757
|
+
|
|
758
|
+
// 如果键不存在于列表中,添加到列表
|
|
759
|
+
if (!this.list.includes(key)) {
|
|
760
|
+
this.list.push(key);
|
|
1810
761
|
}
|
|
1811
|
-
|
|
762
|
+
|
|
763
|
+
this.emit('incrbyfloat_after', { key, increment, result });
|
|
764
|
+
return result;
|
|
765
|
+
} catch (error) {
|
|
766
|
+
this.emit('incrbyfloat_error', { key, increment, error });
|
|
767
|
+
this.log.error('[cachebase] incrbyfloat操作失败:', error);
|
|
768
|
+
throw error;
|
|
769
|
+
}
|
|
1812
770
|
}
|
|
1813
771
|
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
return;
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
|
-
// 执行实际操作
|
|
1832
|
-
let result = [];
|
|
1833
|
-
const obj = this.data[key];
|
|
1834
|
-
if (obj && obj.value && obj.value.sorted) {
|
|
1835
|
-
result = [...obj.value.sorted];
|
|
1836
|
-
}
|
|
1837
|
-
|
|
1838
|
-
// 触发后置事件
|
|
1839
|
-
this.emit('smembers_after', {
|
|
1840
|
-
key,
|
|
1841
|
-
result
|
|
1842
|
-
});
|
|
1843
|
-
resolve(result);
|
|
1844
|
-
} catch (error) {
|
|
1845
|
-
// 触发错误事件
|
|
1846
|
-
this.emit('smembers_error', {
|
|
1847
|
-
key,
|
|
1848
|
-
error
|
|
1849
|
-
});
|
|
1850
|
-
$.log.error('[cachebase] smembers操作失败:', error);
|
|
1851
|
-
resolve([]);
|
|
772
|
+
/**
|
|
773
|
+
* 字符串追加
|
|
774
|
+
* @param {string} key - 键名
|
|
775
|
+
* @param {string} value - 追加的字符串
|
|
776
|
+
* @returns {Promise<number>} - 返回追加后的字符串长度
|
|
777
|
+
*/
|
|
778
|
+
async append(key, value) {
|
|
779
|
+
try {
|
|
780
|
+
this.emit('append_before', { key, value });
|
|
781
|
+
|
|
782
|
+
// 获取当前值或默认为空字符串
|
|
783
|
+
let currentValue = '';
|
|
784
|
+
if (this.data.hasOwnProperty(key) && !this._checkExpire(key)) {
|
|
785
|
+
currentValue = String(this.data[key].value);
|
|
1852
786
|
}
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
cancel: false
|
|
1865
|
-
};
|
|
1866
|
-
this.emit('sismember_before', beforeEventData);
|
|
1867
|
-
|
|
1868
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
1869
|
-
if (beforeEventData.cancel) {
|
|
1870
|
-
resolve(0);
|
|
1871
|
-
return;
|
|
1872
|
-
}
|
|
1873
|
-
|
|
1874
|
-
// 执行实际操作
|
|
1875
|
-
let result = 0;
|
|
1876
|
-
const obj = this.data[key];
|
|
1877
|
-
if (obj && obj.value && obj.value.members && obj.value.members.hasOwnProperty(value)) {
|
|
1878
|
-
result = 1;
|
|
1879
|
-
}
|
|
1880
|
-
|
|
1881
|
-
// 触发后置事件
|
|
1882
|
-
this.emit('sismember_after', {
|
|
1883
|
-
key,
|
|
1884
|
-
value,
|
|
1885
|
-
result
|
|
1886
|
-
});
|
|
1887
|
-
resolve(result);
|
|
1888
|
-
} catch (error) {
|
|
1889
|
-
// 触发错误事件
|
|
1890
|
-
this.emit('sismember_error', {
|
|
1891
|
-
key,
|
|
1892
|
-
value,
|
|
1893
|
-
error
|
|
1894
|
-
});
|
|
1895
|
-
$.log.error('[cachebase] sismember操作失败:', error);
|
|
1896
|
-
resolve(0);
|
|
787
|
+
|
|
788
|
+
// 执行字符串拼接
|
|
789
|
+
const newValue = currentValue + String(value);
|
|
790
|
+
const result = newValue.length;
|
|
791
|
+
|
|
792
|
+
// 保存结果
|
|
793
|
+
this.data[key] = { value: newValue, expire: 0 };
|
|
794
|
+
|
|
795
|
+
// 如果键不存在于列表中,添加到列表
|
|
796
|
+
if (!this.list.includes(key)) {
|
|
797
|
+
this.list.push(key);
|
|
1897
798
|
}
|
|
1898
|
-
|
|
799
|
+
|
|
800
|
+
this.emit('append_after', { key, value, result });
|
|
801
|
+
return result;
|
|
802
|
+
} catch (error) {
|
|
803
|
+
this.emit('append_error', { key, value, error });
|
|
804
|
+
this.log.error('[cachebase] append操作失败:', error);
|
|
805
|
+
throw error;
|
|
806
|
+
}
|
|
1899
807
|
}
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
return;
|
|
1916
|
-
}
|
|
1917
|
-
|
|
1918
|
-
// 执行实际操作
|
|
1919
|
-
let result = 0;
|
|
1920
|
-
const obj = this.data[key];
|
|
1921
|
-
if (obj && obj.value && obj.value.sorted) {
|
|
1922
|
-
result = obj.value.sorted.length;
|
|
1923
|
-
}
|
|
1924
|
-
|
|
1925
|
-
// 触发后置事件
|
|
1926
|
-
this.emit('scard_after', {
|
|
1927
|
-
key,
|
|
1928
|
-
result
|
|
1929
|
-
});
|
|
1930
|
-
resolve(result);
|
|
1931
|
-
} catch (error) {
|
|
1932
|
-
// 触发错误事件
|
|
1933
|
-
this.emit('scard_error', {
|
|
1934
|
-
key,
|
|
1935
|
-
error
|
|
1936
|
-
});
|
|
1937
|
-
$.log.error('[cachebase] scard操作失败:', error);
|
|
1938
|
-
resolve(0);
|
|
808
|
+
|
|
809
|
+
/**
|
|
810
|
+
* 获取字符串长度
|
|
811
|
+
* @param {string} key - 键名
|
|
812
|
+
* @returns {Promise<number>} - 返回字符串长度
|
|
813
|
+
*/
|
|
814
|
+
async strlen(key) {
|
|
815
|
+
try {
|
|
816
|
+
this.emit('strlen_before', { key });
|
|
817
|
+
|
|
818
|
+
// 检查键是否存在且未过期
|
|
819
|
+
if (this.data.hasOwnProperty(key) && !this._checkExpire(key)) {
|
|
820
|
+
const result = String(this.data[key].value).length;
|
|
821
|
+
this.emit('strlen_after', { key, result });
|
|
822
|
+
return result;
|
|
1939
823
|
}
|
|
1940
|
-
|
|
824
|
+
|
|
825
|
+
this.emit('strlen_after', { key, result: 0 });
|
|
826
|
+
return 0;
|
|
827
|
+
} catch (error) {
|
|
828
|
+
this.emit('strlen_error', { key, error });
|
|
829
|
+
this.log.error('[cachebase] strlen操作失败:', error);
|
|
830
|
+
throw error;
|
|
831
|
+
}
|
|
1941
832
|
}
|
|
1942
833
|
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
let result = [];
|
|
1963
|
-
const obj = this.data[key];
|
|
1964
|
-
if (obj && obj.value && obj.value.sorted) {
|
|
1965
|
-
const sorted = obj.value.sorted.slice(start, stop + 1);
|
|
1966
|
-
if (withScores) {
|
|
1967
|
-
result = [];
|
|
1968
|
-
for (const member of sorted) {
|
|
1969
|
-
result.push(member);
|
|
1970
|
-
result.push(obj.value.members[member]);
|
|
1971
|
-
}
|
|
1972
|
-
} else {
|
|
1973
|
-
result = sorted;
|
|
1974
|
-
}
|
|
1975
|
-
}
|
|
1976
|
-
|
|
1977
|
-
// 触发后置事件
|
|
1978
|
-
this.emit('zrange_after', {
|
|
1979
|
-
key,
|
|
1980
|
-
value: { start, stop, withScores },
|
|
1981
|
-
result
|
|
1982
|
-
});
|
|
1983
|
-
resolve(result);
|
|
1984
|
-
} catch (error) {
|
|
1985
|
-
// 触发错误事件
|
|
1986
|
-
this.emit('zrange_error', {
|
|
1987
|
-
key,
|
|
1988
|
-
value: { start, stop, withScores },
|
|
1989
|
-
error
|
|
1990
|
-
});
|
|
1991
|
-
$.log.error('[cachebase] zrange操作失败:', error);
|
|
1992
|
-
resolve([]);
|
|
1993
|
-
}
|
|
1994
|
-
});
|
|
834
|
+
/**
|
|
835
|
+
* 清空数据库
|
|
836
|
+
* @returns {Promise<string>} - 返回'OK'
|
|
837
|
+
*/
|
|
838
|
+
async flushdb() {
|
|
839
|
+
try {
|
|
840
|
+
this.emit('flushdb_before');
|
|
841
|
+
|
|
842
|
+
// 清空数据
|
|
843
|
+
this.data = {};
|
|
844
|
+
this.list = [];
|
|
845
|
+
|
|
846
|
+
this.emit('flushdb_after', { result: 'OK' });
|
|
847
|
+
return 'OK';
|
|
848
|
+
} catch (error) {
|
|
849
|
+
this.emit('flushdb_error', { error });
|
|
850
|
+
this.log.error('[cachebase] flushdb操作失败:', error);
|
|
851
|
+
throw error;
|
|
852
|
+
}
|
|
1995
853
|
}
|
|
1996
854
|
|
|
1997
|
-
//
|
|
1998
|
-
async
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
};
|
|
2007
|
-
this.emit('zrem_before', beforeEventData);
|
|
2008
|
-
|
|
2009
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
2010
|
-
if (beforeEventData.cancel) {
|
|
2011
|
-
resolve(0);
|
|
2012
|
-
return;
|
|
2013
|
-
}
|
|
2014
|
-
|
|
2015
|
-
// 执行实际操作
|
|
2016
|
-
let result = 0;
|
|
2017
|
-
const obj = this.data[key];
|
|
2018
|
-
if (obj && obj.value && obj.value.members && obj.value.members.hasOwnProperty(member)) {
|
|
2019
|
-
delete obj.value.members[member];
|
|
2020
|
-
// 重新排序
|
|
2021
|
-
obj.value.sorted = Object.entries(obj.value.members)
|
|
2022
|
-
.sort((a, b) => a[1] - b[1])
|
|
2023
|
-
.map(entry => entry[0]);
|
|
2024
|
-
result = 1;
|
|
2025
|
-
// 如果集合变空了,删除整个键
|
|
2026
|
-
if (Object.keys(obj.value.members).length === 0) {
|
|
2027
|
-
delete this.data[key];
|
|
2028
|
-
const index = this.list.indexOf(key);
|
|
2029
|
-
if (index > -1) {
|
|
2030
|
-
this.list.splice(index, 1);
|
|
2031
|
-
}
|
|
2032
|
-
}
|
|
2033
|
-
}
|
|
2034
|
-
|
|
2035
|
-
// 触发后置事件
|
|
2036
|
-
this.emit('zrem_after', {
|
|
2037
|
-
key,
|
|
2038
|
-
value: { member },
|
|
2039
|
-
result
|
|
2040
|
-
});
|
|
2041
|
-
resolve(result);
|
|
2042
|
-
} catch (error) {
|
|
2043
|
-
// 触发错误事件
|
|
2044
|
-
this.emit('zrem_error', {
|
|
2045
|
-
key,
|
|
2046
|
-
value: { member },
|
|
2047
|
-
error
|
|
2048
|
-
});
|
|
2049
|
-
$.log.error('[cachebase] zrem操作失败:', error);
|
|
2050
|
-
resolve(0);
|
|
2051
|
-
}
|
|
2052
|
-
});
|
|
855
|
+
// 保持兼容性的方法
|
|
856
|
+
async has(key) {
|
|
857
|
+
try {
|
|
858
|
+
const exists = await this.exists(key);
|
|
859
|
+
return exists > 0;
|
|
860
|
+
} catch (error) {
|
|
861
|
+
this.log.error('[cachebase] has操作失败:', error);
|
|
862
|
+
throw error;
|
|
863
|
+
}
|
|
2053
864
|
}
|
|
2054
865
|
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
try {
|
|
2059
|
-
// 触发前置事件
|
|
2060
|
-
const beforeEventData = {
|
|
2061
|
-
key,
|
|
2062
|
-
value: { member },
|
|
2063
|
-
cancel: false
|
|
2064
|
-
};
|
|
2065
|
-
this.emit('zscore_before', beforeEventData);
|
|
866
|
+
async clear(pattern) {
|
|
867
|
+
return this.flushdb();
|
|
868
|
+
}
|
|
2066
869
|
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
return;
|
|
2071
|
-
}
|
|
870
|
+
async add(key, value) {
|
|
871
|
+
return this.incrby(key, value);
|
|
872
|
+
}
|
|
2072
873
|
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
if (obj && obj.value && obj.value.members && obj.value.members.hasOwnProperty(member)) {
|
|
2077
|
-
result = obj.value.members[member];
|
|
2078
|
-
}
|
|
874
|
+
async addFloat(key, value) {
|
|
875
|
+
return this.incrbyfloat(key, value);
|
|
876
|
+
}
|
|
2079
877
|
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
key,
|
|
2083
|
-
value: { member },
|
|
2084
|
-
result
|
|
2085
|
-
});
|
|
2086
|
-
resolve(result);
|
|
2087
|
-
} catch (error) {
|
|
2088
|
-
// 触发错误事件
|
|
2089
|
-
this.emit('zscore_error', {
|
|
2090
|
-
key,
|
|
2091
|
-
value: { member },
|
|
2092
|
-
error
|
|
2093
|
-
});
|
|
2094
|
-
$.log.error('[cachebase] zscore操作失败:', error);
|
|
2095
|
-
resolve(null);
|
|
2096
|
-
}
|
|
2097
|
-
});
|
|
878
|
+
async addStr(key, value) {
|
|
879
|
+
return this.append(key, value);
|
|
2098
880
|
}
|
|
2099
881
|
|
|
2100
|
-
|
|
882
|
+
/**
|
|
883
|
+
* 资源销毁方法
|
|
884
|
+
*/
|
|
2101
885
|
dispose() {
|
|
2102
886
|
try {
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
// 如果事件处理器设置了cancel为true,则取消操作
|
|
2108
|
-
if (beforeEventData.cancel) {
|
|
2109
|
-
return;
|
|
2110
|
-
}
|
|
2111
|
-
|
|
2112
|
-
// 执行实际操作
|
|
887
|
+
this.emit('dispose_before');
|
|
888
|
+
|
|
889
|
+
// 清空数据
|
|
2113
890
|
this.data = {};
|
|
2114
891
|
this.list = [];
|
|
2115
|
-
this.dict = this.data; // 同步dict引用
|
|
2116
892
|
|
|
2117
|
-
|
|
2118
|
-
this.emit('dispose_after', {});
|
|
893
|
+
this.emit('dispose_after');
|
|
2119
894
|
|
|
2120
|
-
//
|
|
895
|
+
// 移除所有监听器
|
|
2121
896
|
this.removeAllListeners();
|
|
2122
897
|
} catch (error) {
|
|
2123
|
-
// 触发错误事件
|
|
2124
898
|
this.emit('dispose_error', { error });
|
|
2125
|
-
|
|
899
|
+
this.log.error('[cachebase] dispose操作失败:', error);
|
|
2126
900
|
}
|
|
2127
901
|
}
|
|
2128
902
|
}
|
|
2129
903
|
|
|
2130
904
|
// 导出CacheBase类
|
|
2131
|
-
|
|
905
|
+
exports.CacheBase = CacheBase;
|
|
906
|
+
|
|
907
|
+
|
|
908
|
+
/**
|
|
909
|
+
* 确保连接池对象存在
|
|
910
|
+
*/
|
|
911
|
+
if (!$.pool) {
|
|
912
|
+
$.pool = {};
|
|
913
|
+
}
|
|
914
|
+
if (!$.pool.cachebase) {
|
|
915
|
+
$.pool.cachebase = {};
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
/**
|
|
919
|
+
* @description cachebase管理器,用于创建缓存
|
|
920
|
+
* @param {String} scope 作用域
|
|
921
|
+
* @param {String} dir 当前路径
|
|
922
|
+
* @return {Object} 返回一个cachebase类实例
|
|
923
|
+
*/
|
|
924
|
+
function cachebase_admin(scope, dir) {
|
|
925
|
+
if (!scope) {
|
|
926
|
+
scope = 'sys';
|
|
927
|
+
}
|
|
928
|
+
var obj = $.pool.cachebase[scope];
|
|
929
|
+
if (!obj) {
|
|
930
|
+
$.pool.cachebase[scope] = new CacheBase(scope, dir);
|
|
931
|
+
obj = $.pool.cachebase[scope];
|
|
932
|
+
}
|
|
933
|
+
return obj;
|
|
934
|
+
}
|
|
2132
935
|
|
|
936
|
+
/**
|
|
937
|
+
* @module 导出cachebase管理器
|
|
938
|
+
*/
|
|
939
|
+
exports.cachebase_admin = cachebase_admin;
|