befly 3.74.2 → 3.75.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/apis/dashboard/systemResources.js +3 -1
- package/apis/dict/_dict.js +1 -1
- package/apis/role/_role.js +2 -2
- package/apis/tongJi/dailyStats.js +2 -2
- package/apis/tongJi/dailyStatsDistribution.js +3 -3
- package/apis/tongJi/errorList.js +2 -2
- package/apis/tongJi/errorStats.js +6 -6
- package/checks/api.js +11 -6
- package/checks/items.js +56 -0
- package/checks/menu.js +1 -1
- package/checks/table.js +4 -5
- package/configs/beflyConfig.json +5 -10
- package/configs/constConfig.js +44 -3
- package/hooks/auth.js +3 -2
- package/hooks/parser.js +15 -4
- package/hooks/permission.js +3 -2
- package/hooks/rateLimit.js +16 -3
- package/hooks/validator.js +2 -1
- package/index.js +53 -24
- package/lib/cacheHelper.js +83 -229
- package/lib/connect.js +3 -13
- package/lib/dbHelper.js +57 -142
- package/lib/dbParse.js +65 -248
- package/lib/dbUtil.js +19 -63
- package/lib/logger.js +45 -22
- package/lib/redisHelper.js +186 -420
- package/lib/smtpText.js +7 -18
- package/lib/sqlBuilder.js +22 -51
- package/lib/xmlParse.js +15 -59
- package/package.json +1 -1
- package/plugins/cache.js +2 -3
- package/plugins/config.js +3 -1
- package/plugins/cron.js +2 -2
- package/plugins/email.js +3 -1
- package/plugins/logger.js +2 -2
- package/plugins/mysql.js +5 -10
- package/plugins/redis.js +4 -11
- package/plugins/tool.js +3 -3
- package/plugins/xmlParse.js +3 -1
- package/router/api.js +2 -6
- package/router/static.js +9 -10
- package/schemas/config.js +4 -4
- package/scripts/syncDb/context.js +4 -7
- package/scripts/syncDb/diff.js +2 -1
- package/scripts/syncDb/index.js +2 -6
- package/sync/api.js +7 -8
- package/sync/cache.js +3 -1
- package/sync/dev.js +28 -65
- package/sync/menu.js +5 -6
- package/sync/syncUtil.js +25 -0
- package/utils/calcPerfTime.js +2 -3
- package/utils/crypto.js +0 -40
- package/utils/deepMerge.js +2 -6
- package/utils/error.js +64 -0
- package/utils/fieldClear.js +13 -56
- package/utils/importDefault.js +11 -12
- package/utils/is.js +5 -182
- package/utils/loggerUtils.js +3 -1
- package/utils/response.js +12 -8
- package/utils/scanFiles.js +2 -53
- package/utils/scanSources.js +9 -0
- package/utils/util.js +25 -222
- package/checks/hook.js +0 -39
- package/checks/plugin.js +0 -39
- package/utils/processInfo.js +0 -39
package/lib/redisHelper.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Redis 助手 - JavaScript 版本
|
|
3
2
|
* 提供 Redis 操作的便捷方法
|
|
4
3
|
*/
|
|
5
4
|
|
|
5
|
+
import { createError } from "../utils/error.js";
|
|
6
6
|
import { Connect } from "./connect.js";
|
|
7
7
|
import { Logger } from "./logger.js";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Redis 助手类
|
|
11
|
-
*
|
|
11
|
+
* 约定:除构造函数与 ping 外,方法默认不抛异常;失败时返回 null/false/0/[] 并记录日志。
|
|
12
12
|
*/
|
|
13
13
|
export class RedisHelper {
|
|
14
14
|
/**
|
|
@@ -18,15 +18,27 @@ export class RedisHelper {
|
|
|
18
18
|
constructor(prefix = "") {
|
|
19
19
|
const client = Connect.getRedis();
|
|
20
20
|
if (!client) {
|
|
21
|
-
throw
|
|
22
|
-
cause: null,
|
|
23
|
-
code: "runtime"
|
|
24
|
-
});
|
|
21
|
+
throw createError("Redis 客户端未初始化,请先调用 Connect.connectRedis()", { code: "runtime" });
|
|
25
22
|
}
|
|
26
23
|
this.client = client;
|
|
27
24
|
this.prefix = prefix ? `${prefix}:` : "";
|
|
28
25
|
}
|
|
29
26
|
|
|
27
|
+
/**
|
|
28
|
+
* 吞错执行:失败记录日志并返回 fallback(不抛出)
|
|
29
|
+
* @param label - 操作名(用于日志文案)
|
|
30
|
+
* @param operation - 实际操作
|
|
31
|
+
* @param fallback - 失败返回值
|
|
32
|
+
*/
|
|
33
|
+
async safeCall(label, operation, fallback) {
|
|
34
|
+
try {
|
|
35
|
+
return await operation();
|
|
36
|
+
} catch (error) {
|
|
37
|
+
Logger.error(`Redis ${label} 错误`, error);
|
|
38
|
+
return fallback;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
30
42
|
/**
|
|
31
43
|
* 设置对象到 Redis
|
|
32
44
|
* @param key - 键名
|
|
@@ -35,19 +47,15 @@ export class RedisHelper {
|
|
|
35
47
|
* @returns 操作结果
|
|
36
48
|
*/
|
|
37
49
|
async setObject(key, obj, ttl = null) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
} catch (error) {
|
|
48
|
-
Logger.error("Redis setObject 错误", error);
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
50
|
+
return this.safeCall(
|
|
51
|
+
"setObject",
|
|
52
|
+
async () => {
|
|
53
|
+
const data = JSON.stringify(obj);
|
|
54
|
+
const pkey = `${this.prefix}${key}`;
|
|
55
|
+
return ttl ? this.client.setex(pkey, ttl, data) : this.client.set(pkey, data);
|
|
56
|
+
},
|
|
57
|
+
null
|
|
58
|
+
);
|
|
51
59
|
}
|
|
52
60
|
|
|
53
61
|
/**
|
|
@@ -56,14 +64,15 @@ export class RedisHelper {
|
|
|
56
64
|
* @returns 对象或 null
|
|
57
65
|
*/
|
|
58
66
|
async getObject(key) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
return this.safeCall(
|
|
68
|
+
"getObject",
|
|
69
|
+
async () => {
|
|
70
|
+
const pkey = `${this.prefix}${key}`;
|
|
71
|
+
const data = await this.client.get(pkey);
|
|
72
|
+
return data ? JSON.parse(data) : null;
|
|
73
|
+
},
|
|
74
|
+
null
|
|
75
|
+
);
|
|
67
76
|
}
|
|
68
77
|
|
|
69
78
|
/**
|
|
@@ -71,12 +80,10 @@ export class RedisHelper {
|
|
|
71
80
|
* @param key - 键名
|
|
72
81
|
*/
|
|
73
82
|
async delObject(key) {
|
|
74
|
-
|
|
83
|
+
return this.safeCall("delObject", async () => {
|
|
75
84
|
const pkey = `${this.prefix}${key}`;
|
|
76
85
|
await this.client.del(pkey);
|
|
77
|
-
}
|
|
78
|
-
Logger.error("Redis delObject 错误", error);
|
|
79
|
-
}
|
|
86
|
+
});
|
|
80
87
|
}
|
|
81
88
|
|
|
82
89
|
// ==================== ID 生成 ====================
|
|
@@ -112,17 +119,14 @@ export class RedisHelper {
|
|
|
112
119
|
* @param ttl - 过期时间(秒)
|
|
113
120
|
*/
|
|
114
121
|
async setString(key, value, ttl = null) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
Logger.error("Redis setString 错误", error);
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
122
|
+
return this.safeCall(
|
|
123
|
+
"setString",
|
|
124
|
+
async () => {
|
|
125
|
+
const pkey = `${this.prefix}${key}`;
|
|
126
|
+
return ttl ? this.client.setex(pkey, ttl, value) : this.client.set(pkey, value);
|
|
127
|
+
},
|
|
128
|
+
null
|
|
129
|
+
);
|
|
126
130
|
}
|
|
127
131
|
|
|
128
132
|
/**
|
|
@@ -130,13 +134,14 @@ export class RedisHelper {
|
|
|
130
134
|
* @param key - 键名
|
|
131
135
|
*/
|
|
132
136
|
async getString(key) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
137
|
+
return this.safeCall(
|
|
138
|
+
"getString",
|
|
139
|
+
async () => {
|
|
140
|
+
const pkey = `${this.prefix}${key}`;
|
|
141
|
+
return this.client.get(pkey);
|
|
142
|
+
},
|
|
143
|
+
null
|
|
144
|
+
);
|
|
140
145
|
}
|
|
141
146
|
|
|
142
147
|
/**
|
|
@@ -145,13 +150,14 @@ export class RedisHelper {
|
|
|
145
150
|
* @returns 是否存在(true/false)
|
|
146
151
|
*/
|
|
147
152
|
async exists(key) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
return this.safeCall(
|
|
154
|
+
"exists",
|
|
155
|
+
async () => {
|
|
156
|
+
const pkey = `${this.prefix}${key}`;
|
|
157
|
+
return this.client.exists(pkey);
|
|
158
|
+
},
|
|
159
|
+
false
|
|
160
|
+
);
|
|
155
161
|
}
|
|
156
162
|
|
|
157
163
|
/**
|
|
@@ -160,29 +166,14 @@ export class RedisHelper {
|
|
|
160
166
|
* @returns 自增后的值
|
|
161
167
|
*/
|
|
162
168
|
async incr(key) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* 原子按指定值自增
|
|
174
|
-
* @param key - 键名
|
|
175
|
-
* @param value - 自增值
|
|
176
|
-
* @returns 自增后的值
|
|
177
|
-
*/
|
|
178
|
-
async incrBy(key, value) {
|
|
179
|
-
try {
|
|
180
|
-
const pkey = `${this.prefix}${key}`;
|
|
181
|
-
return await this.client.incrby(pkey, value);
|
|
182
|
-
} catch (error) {
|
|
183
|
-
Logger.error("Redis incrBy 错误", error);
|
|
184
|
-
return 0;
|
|
185
|
-
}
|
|
169
|
+
return this.safeCall(
|
|
170
|
+
"incr",
|
|
171
|
+
async () => {
|
|
172
|
+
const pkey = `${this.prefix}${key}`;
|
|
173
|
+
return this.client.incr(pkey);
|
|
174
|
+
},
|
|
175
|
+
0
|
|
176
|
+
);
|
|
186
177
|
}
|
|
187
178
|
|
|
188
179
|
/**
|
|
@@ -192,17 +183,18 @@ export class RedisHelper {
|
|
|
192
183
|
* @returns 自增后的值
|
|
193
184
|
*/
|
|
194
185
|
async incrWithExpire(key, seconds) {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
await this.client.
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
186
|
+
return this.safeCall(
|
|
187
|
+
"incrWithExpire",
|
|
188
|
+
async () => {
|
|
189
|
+
const pkey = `${this.prefix}${key}`;
|
|
190
|
+
const res = await this.client.incr(pkey);
|
|
191
|
+
if (res === 1) {
|
|
192
|
+
await this.client.expire(pkey, seconds);
|
|
193
|
+
}
|
|
194
|
+
return res;
|
|
195
|
+
},
|
|
196
|
+
0
|
|
197
|
+
);
|
|
206
198
|
}
|
|
207
199
|
|
|
208
200
|
/**
|
|
@@ -211,13 +203,14 @@ export class RedisHelper {
|
|
|
211
203
|
* @param seconds - 秒数
|
|
212
204
|
*/
|
|
213
205
|
async expire(key, seconds) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
206
|
+
return this.safeCall(
|
|
207
|
+
"expire",
|
|
208
|
+
async () => {
|
|
209
|
+
const pkey = `${this.prefix}${key}`;
|
|
210
|
+
return this.client.expire(pkey, seconds);
|
|
211
|
+
},
|
|
212
|
+
0
|
|
213
|
+
);
|
|
221
214
|
}
|
|
222
215
|
|
|
223
216
|
/**
|
|
@@ -225,32 +218,14 @@ export class RedisHelper {
|
|
|
225
218
|
* @param key - 键名
|
|
226
219
|
*/
|
|
227
220
|
async ttl(key) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* 批量获取剩余过期时间(利用 Bun Redis 自动管道优化)
|
|
239
|
-
* @param keys - 键名数组
|
|
240
|
-
* @returns TTL 数组(-2 表示键不存在,-1 表示无过期时间)
|
|
241
|
-
*/
|
|
242
|
-
async ttlBatch(keys) {
|
|
243
|
-
if (keys.length === 0) {
|
|
244
|
-
return [];
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
try {
|
|
248
|
-
const results = await Promise.all(keys.map((key) => this.ttl(key)));
|
|
249
|
-
return results;
|
|
250
|
-
} catch (error) {
|
|
251
|
-
Logger.error("Redis ttlBatch 错误", error);
|
|
252
|
-
return keys.map(() => -1);
|
|
253
|
-
}
|
|
221
|
+
return this.safeCall(
|
|
222
|
+
"ttl",
|
|
223
|
+
async () => {
|
|
224
|
+
const pkey = `${this.prefix}${key}`;
|
|
225
|
+
return this.client.ttl(pkey);
|
|
226
|
+
},
|
|
227
|
+
-1
|
|
228
|
+
);
|
|
254
229
|
}
|
|
255
230
|
|
|
256
231
|
/**
|
|
@@ -260,19 +235,20 @@ export class RedisHelper {
|
|
|
260
235
|
* @returns 成功添加的成员数量
|
|
261
236
|
*/
|
|
262
237
|
async sadd(key, members) {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
args
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
238
|
+
return this.safeCall(
|
|
239
|
+
"sadd",
|
|
240
|
+
async () => {
|
|
241
|
+
if (members.length === 0) return 0;
|
|
242
|
+
|
|
243
|
+
const pkey = `${this.prefix}${key}`;
|
|
244
|
+
const args = [pkey];
|
|
245
|
+
for (const member of members) {
|
|
246
|
+
args.push(member);
|
|
247
|
+
}
|
|
248
|
+
return this.client.sadd.apply(this.client, args);
|
|
249
|
+
},
|
|
250
|
+
0
|
|
251
|
+
);
|
|
276
252
|
}
|
|
277
253
|
|
|
278
254
|
/**
|
|
@@ -282,28 +258,29 @@ export class RedisHelper {
|
|
|
282
258
|
* @returns 是否存在(true/false)
|
|
283
259
|
*/
|
|
284
260
|
async sismember(key, member) {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
261
|
+
return this.safeCall(
|
|
262
|
+
"sismember",
|
|
263
|
+
async () => {
|
|
264
|
+
const pkey = `${this.prefix}${key}`;
|
|
265
|
+
return this.client.sismember(pkey, member);
|
|
266
|
+
},
|
|
267
|
+
false
|
|
268
|
+
);
|
|
292
269
|
}
|
|
293
270
|
|
|
294
271
|
/**
|
|
295
272
|
* 获取 Set 的成员数量
|
|
296
273
|
* @param key - 键名
|
|
297
|
-
* @returns 成员数量
|
|
298
274
|
*/
|
|
299
275
|
async scard(key) {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
276
|
+
return this.safeCall(
|
|
277
|
+
"scard",
|
|
278
|
+
async () => {
|
|
279
|
+
const pkey = `${this.prefix}${key}`;
|
|
280
|
+
return this.client.scard(pkey);
|
|
281
|
+
},
|
|
282
|
+
0
|
|
283
|
+
);
|
|
307
284
|
}
|
|
308
285
|
|
|
309
286
|
/**
|
|
@@ -312,35 +289,14 @@ export class RedisHelper {
|
|
|
312
289
|
* @returns 成员数组
|
|
313
290
|
*/
|
|
314
291
|
async smembers(key) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
/**
|
|
325
|
-
* 从 Set 中删除一个或多个成员
|
|
326
|
-
* @param key - 键名
|
|
327
|
-
* @param members - 成员数组
|
|
328
|
-
* @returns 删除的成员数量
|
|
329
|
-
*/
|
|
330
|
-
async srem(key, members) {
|
|
331
|
-
try {
|
|
332
|
-
if (members.length === 0) return 0;
|
|
333
|
-
|
|
334
|
-
const pkey = `${this.prefix}${key}`;
|
|
335
|
-
const args = [pkey];
|
|
336
|
-
for (const member of members) {
|
|
337
|
-
args.push(member);
|
|
338
|
-
}
|
|
339
|
-
return await this.client.srem.apply(this.client, args);
|
|
340
|
-
} catch (error) {
|
|
341
|
-
Logger.error("Redis srem 错误", error);
|
|
342
|
-
return 0;
|
|
343
|
-
}
|
|
292
|
+
return this.safeCall(
|
|
293
|
+
"smembers",
|
|
294
|
+
async () => {
|
|
295
|
+
const pkey = `${this.prefix}${key}`;
|
|
296
|
+
return this.client.smembers(pkey);
|
|
297
|
+
},
|
|
298
|
+
[]
|
|
299
|
+
);
|
|
344
300
|
}
|
|
345
301
|
|
|
346
302
|
/**
|
|
@@ -349,128 +305,18 @@ export class RedisHelper {
|
|
|
349
305
|
* @returns 成功添加的总成员数量
|
|
350
306
|
*/
|
|
351
307
|
async saddBatch(items) {
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
const results = await Promise.all(items.map((item) => this.sadd(item.key, item.members)));
|
|
358
|
-
return results.reduce((sum, count) => sum + count, 0);
|
|
359
|
-
} catch (error) {
|
|
360
|
-
Logger.error("Redis saddBatch 错误", error);
|
|
361
|
-
return 0;
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* 批量检查成员是否在 Set 中(利用 Bun Redis 自动管道优化)
|
|
367
|
-
* @param items - [{ key, member }] 数组
|
|
368
|
-
* @returns 布尔数组(true 表示存在,false 表示不存在)
|
|
369
|
-
*/
|
|
370
|
-
async sismemberBatch(items) {
|
|
371
|
-
if (items.length === 0) {
|
|
372
|
-
return [];
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
try {
|
|
376
|
-
return await Promise.all(items.map((item) => this.sismember(item.key, item.member)));
|
|
377
|
-
} catch (error) {
|
|
378
|
-
Logger.error("Redis sismemberBatch 错误", error);
|
|
379
|
-
return items.map(() => false);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* 向有序集合添加成员
|
|
385
|
-
* @param key - 键名
|
|
386
|
-
* @param items - [{ score, member }] 数组
|
|
387
|
-
* @returns 成功添加的成员数量
|
|
388
|
-
*/
|
|
389
|
-
async zadd(key, items) {
|
|
390
|
-
try {
|
|
391
|
-
if (items.length === 0) {
|
|
392
|
-
return 0;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
const pkey = `${this.prefix}${key}`;
|
|
396
|
-
const args = [pkey];
|
|
397
|
-
|
|
398
|
-
for (const item of items) {
|
|
399
|
-
const score = Number(item.score);
|
|
400
|
-
const member = String(item.member);
|
|
401
|
-
|
|
402
|
-
if (!Number.isFinite(score) || member.length === 0) {
|
|
403
|
-
continue;
|
|
308
|
+
return this.safeCall(
|
|
309
|
+
"saddBatch",
|
|
310
|
+
async () => {
|
|
311
|
+
if (items.length === 0) {
|
|
312
|
+
return 0;
|
|
404
313
|
}
|
|
405
314
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
return 0;
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
return await this.client.zadd.apply(this.client, args);
|
|
415
|
-
} catch (error) {
|
|
416
|
-
Logger.error("Redis zadd 错误", error);
|
|
417
|
-
return 0;
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
/**
|
|
422
|
-
* 获取有序集合成员数量
|
|
423
|
-
* @param key - 键名
|
|
424
|
-
*/
|
|
425
|
-
async zcard(key) {
|
|
426
|
-
try {
|
|
427
|
-
const pkey = `${this.prefix}${key}`;
|
|
428
|
-
return await this.client.zcard(pkey);
|
|
429
|
-
} catch (error) {
|
|
430
|
-
Logger.error("Redis zcard 错误", error);
|
|
431
|
-
return 0;
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
/**
|
|
436
|
-
* 按 score 区间删除有序集合成员
|
|
437
|
-
* @param key - 键名
|
|
438
|
-
* @param min - 最小分值
|
|
439
|
-
* @param max - 最大分值
|
|
440
|
-
*/
|
|
441
|
-
async zremrangebyscore(key, min, max) {
|
|
442
|
-
try {
|
|
443
|
-
const pkey = `${this.prefix}${key}`;
|
|
444
|
-
return await this.client.zremrangebyscore(pkey, min, max);
|
|
445
|
-
} catch (error) {
|
|
446
|
-
Logger.error("Redis zremrangebyscore 错误", error);
|
|
447
|
-
return 0;
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/**
|
|
452
|
-
* 从有序集合删除一个或多个成员
|
|
453
|
-
* @param key - 键名
|
|
454
|
-
* @param members - 成员数组
|
|
455
|
-
*/
|
|
456
|
-
async zrem(key, members) {
|
|
457
|
-
try {
|
|
458
|
-
if (members.length === 0) {
|
|
459
|
-
return 0;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
const pkey = `${this.prefix}${key}`;
|
|
463
|
-
const args = [pkey];
|
|
464
|
-
|
|
465
|
-
for (const member of members) {
|
|
466
|
-
args.push(String(member));
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
return await this.client.zrem.apply(this.client, args);
|
|
470
|
-
} catch (error) {
|
|
471
|
-
Logger.error("Redis zrem 错误", error);
|
|
472
|
-
return 0;
|
|
473
|
-
}
|
|
315
|
+
const results = await Promise.all(items.map((item) => this.sadd(item.key, item.members)));
|
|
316
|
+
return results.reduce((sum, count) => sum + count, 0);
|
|
317
|
+
},
|
|
318
|
+
0
|
|
319
|
+
);
|
|
474
320
|
}
|
|
475
321
|
|
|
476
322
|
/**
|
|
@@ -479,13 +325,14 @@ export class RedisHelper {
|
|
|
479
325
|
* @returns 删除的键数量
|
|
480
326
|
*/
|
|
481
327
|
async del(key) {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
328
|
+
return this.safeCall(
|
|
329
|
+
"del",
|
|
330
|
+
async () => {
|
|
331
|
+
const pkey = `${this.prefix}${key}`;
|
|
332
|
+
return this.client.del(pkey);
|
|
333
|
+
},
|
|
334
|
+
0
|
|
335
|
+
);
|
|
489
336
|
}
|
|
490
337
|
|
|
491
338
|
/**
|
|
@@ -494,97 +341,23 @@ export class RedisHelper {
|
|
|
494
341
|
* @returns 成功删除的键数量
|
|
495
342
|
*/
|
|
496
343
|
async delBatch(keys) {
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
keys.map((key) => {
|
|
504
|
-
const pkey = `${this.prefix}${key}`;
|
|
505
|
-
return this.client.del(pkey);
|
|
506
|
-
})
|
|
507
|
-
);
|
|
508
|
-
return results.reduce((sum, count) => sum + count, 0);
|
|
509
|
-
} catch (error) {
|
|
510
|
-
Logger.error("Redis delBatch 错误", error);
|
|
511
|
-
return 0;
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
/**
|
|
516
|
-
* 批量设置对象(利用 Bun Redis 自动管道优化)
|
|
517
|
-
* @param items - 键值对数组 [{ key, value, ttl? }]
|
|
518
|
-
* @returns 成功设置的数量
|
|
519
|
-
*/
|
|
520
|
-
async setBatch(items) {
|
|
521
|
-
if (items.length === 0) {
|
|
522
|
-
return 0;
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
try {
|
|
526
|
-
const results = await Promise.all(items.map((item) => this.setObject(item.key, item.value, item.ttl ?? null)));
|
|
527
|
-
return results.filter((r) => r !== null).length;
|
|
528
|
-
} catch (error) {
|
|
529
|
-
Logger.error("Redis setBatch 错误", error);
|
|
530
|
-
return 0;
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
/**
|
|
535
|
-
* 批量获取对象(利用 Bun Redis 自动管道优化)
|
|
536
|
-
* @param keys - 键名数组
|
|
537
|
-
* @returns 对象数组(不存在的键返回 null)
|
|
538
|
-
*/
|
|
539
|
-
async getBatch(keys) {
|
|
540
|
-
if (keys.length === 0) {
|
|
541
|
-
return [];
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
try {
|
|
545
|
-
const results = await Promise.all(keys.map((key) => this.getObject(key)));
|
|
546
|
-
return results;
|
|
547
|
-
} catch (error) {
|
|
548
|
-
Logger.error("Redis getBatch 错误", error);
|
|
549
|
-
return keys.map(() => null);
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
/**
|
|
554
|
-
* 批量检查键是否存在(利用 Bun Redis 自动管道优化)
|
|
555
|
-
* @param keys - 键名数组
|
|
556
|
-
* @returns 布尔数组(true 表示存在,false 表示不存在)
|
|
557
|
-
*/
|
|
558
|
-
async existsBatch(keys) {
|
|
559
|
-
if (keys.length === 0) {
|
|
560
|
-
return [];
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
try {
|
|
564
|
-
return await Promise.all(keys.map((key) => this.exists(key)));
|
|
565
|
-
} catch (error) {
|
|
566
|
-
Logger.error("Redis existsBatch 错误", error);
|
|
567
|
-
return keys.map(() => false);
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
/**
|
|
572
|
-
* 批量设置过期时间(利用 Bun Redis 自动管道优化)
|
|
573
|
-
* @param items - 键名和过期时间数组 [{ key, seconds }]
|
|
574
|
-
* @returns 成功设置的数量
|
|
575
|
-
*/
|
|
576
|
-
async expireBatch(items) {
|
|
577
|
-
if (items.length === 0) {
|
|
578
|
-
return 0;
|
|
579
|
-
}
|
|
344
|
+
return this.safeCall(
|
|
345
|
+
"delBatch",
|
|
346
|
+
async () => {
|
|
347
|
+
if (keys.length === 0) {
|
|
348
|
+
return 0;
|
|
349
|
+
}
|
|
580
350
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
351
|
+
const results = await Promise.all(
|
|
352
|
+
keys.map((key) => {
|
|
353
|
+
const pkey = `${this.prefix}${key}`;
|
|
354
|
+
return this.client.del(pkey);
|
|
355
|
+
})
|
|
356
|
+
);
|
|
357
|
+
return results.reduce((sum, count) => sum + count, 0);
|
|
358
|
+
},
|
|
359
|
+
0
|
|
360
|
+
);
|
|
588
361
|
}
|
|
589
362
|
|
|
590
363
|
/**
|
|
@@ -592,29 +365,27 @@ export class RedisHelper {
|
|
|
592
365
|
* @param section - 可选 section(如 "server")
|
|
593
366
|
*/
|
|
594
367
|
async info(section) {
|
|
595
|
-
|
|
596
|
-
|
|
368
|
+
return this.safeCall(
|
|
369
|
+
"info",
|
|
370
|
+
async () => {
|
|
371
|
+
const client = this.client;
|
|
597
372
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
373
|
+
if (typeof client.info === "function") {
|
|
374
|
+
return client.info(section);
|
|
375
|
+
}
|
|
601
376
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
377
|
+
if (typeof client.send === "function") {
|
|
378
|
+
return client.send("INFO", section ? [String(section)] : []);
|
|
379
|
+
}
|
|
605
380
|
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
} catch (error) {
|
|
611
|
-
Logger.error("Redis info 错误", error);
|
|
612
|
-
return "";
|
|
613
|
-
}
|
|
381
|
+
throw createError("Redis info 不支持", { code: "runtime" });
|
|
382
|
+
},
|
|
383
|
+
""
|
|
384
|
+
);
|
|
614
385
|
}
|
|
615
386
|
|
|
616
387
|
/**
|
|
617
|
-
* 测试 Redis
|
|
388
|
+
* 测试 Redis 连接(异常时抛出,供调用方感知连接状态)
|
|
618
389
|
* @returns ping 响应结果
|
|
619
390
|
*/
|
|
620
391
|
async ping() {
|
|
@@ -622,12 +393,7 @@ export class RedisHelper {
|
|
|
622
393
|
return await this.client.ping();
|
|
623
394
|
} catch (error) {
|
|
624
395
|
Logger.error("Redis ping 错误", error);
|
|
625
|
-
throw
|
|
626
|
-
cause: error,
|
|
627
|
-
code: "runtime",
|
|
628
|
-
subsystem: "redis",
|
|
629
|
-
operation: "ping"
|
|
630
|
-
});
|
|
396
|
+
throw createError("Redis ping 错误", { cause: error, code: "runtime", subsystem: "redis", operation: "ping" });
|
|
631
397
|
}
|
|
632
398
|
}
|
|
633
399
|
}
|