befly 3.9.38 → 3.9.40

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.
Files changed (155) hide show
  1. package/README.md +37 -38
  2. package/befly.config.ts +62 -40
  3. package/checks/checkApi.ts +16 -16
  4. package/checks/checkApp.ts +19 -25
  5. package/checks/checkTable.ts +42 -42
  6. package/docs/README.md +42 -35
  7. package/docs/{api.md → api/api.md} +223 -231
  8. package/docs/cipher.md +71 -69
  9. package/docs/database.md +143 -141
  10. package/docs/{examples.md → guide/examples.md} +181 -181
  11. package/docs/guide/quickstart.md +331 -0
  12. package/docs/hooks/auth.md +38 -0
  13. package/docs/hooks/cors.md +28 -0
  14. package/docs/{hook.md → hooks/hook.md} +140 -57
  15. package/docs/hooks/parser.md +19 -0
  16. package/docs/hooks/rateLimit.md +47 -0
  17. package/docs/{redis.md → infra/redis.md} +84 -93
  18. package/docs/plugins/cipher.md +61 -0
  19. package/docs/plugins/database.md +128 -0
  20. package/docs/{plugin.md → plugins/plugin.md} +83 -81
  21. package/docs/quickstart.md +26 -26
  22. package/docs/{addon.md → reference/addon.md} +46 -46
  23. package/docs/{config.md → reference/config.md} +32 -80
  24. package/docs/{logger.md → reference/logger.md} +52 -52
  25. package/docs/{sync.md → reference/sync.md} +32 -35
  26. package/docs/{table.md → reference/table.md} +1 -1
  27. package/docs/{validator.md → reference/validator.md} +57 -57
  28. package/hooks/auth.ts +8 -4
  29. package/hooks/cors.ts +13 -13
  30. package/hooks/parser.ts +37 -17
  31. package/hooks/permission.ts +26 -14
  32. package/hooks/rateLimit.ts +276 -0
  33. package/hooks/validator.ts +8 -8
  34. package/lib/asyncContext.ts +43 -0
  35. package/lib/cacheHelper.ts +212 -77
  36. package/lib/cacheKeys.ts +38 -0
  37. package/lib/cipher.ts +30 -30
  38. package/lib/connect.ts +28 -28
  39. package/lib/dbHelper.ts +183 -102
  40. package/lib/jwt.ts +16 -16
  41. package/lib/logger.ts +610 -19
  42. package/lib/redisHelper.ts +185 -44
  43. package/lib/sqlBuilder.ts +90 -91
  44. package/lib/validator.ts +59 -39
  45. package/loader/loadApis.ts +48 -44
  46. package/loader/loadHooks.ts +40 -14
  47. package/loader/loadPlugins.ts +16 -17
  48. package/main.ts +57 -47
  49. package/package.json +47 -45
  50. package/paths.ts +15 -14
  51. package/plugins/cache.ts +5 -4
  52. package/plugins/cipher.ts +3 -3
  53. package/plugins/config.ts +2 -2
  54. package/plugins/db.ts +9 -9
  55. package/plugins/jwt.ts +3 -3
  56. package/plugins/logger.ts +8 -12
  57. package/plugins/redis.ts +8 -8
  58. package/plugins/tool.ts +6 -6
  59. package/router/api.ts +85 -56
  60. package/router/static.ts +12 -12
  61. package/sync/syncAll.ts +12 -12
  62. package/sync/syncApi.ts +55 -52
  63. package/sync/syncDb/apply.ts +20 -19
  64. package/sync/syncDb/constants.ts +25 -23
  65. package/sync/syncDb/ddl.ts +35 -36
  66. package/sync/syncDb/helpers.ts +6 -9
  67. package/sync/syncDb/schema.ts +10 -9
  68. package/sync/syncDb/sqlite.ts +7 -8
  69. package/sync/syncDb/table.ts +37 -35
  70. package/sync/syncDb/tableCreate.ts +21 -20
  71. package/sync/syncDb/types.ts +23 -20
  72. package/sync/syncDb/version.ts +10 -10
  73. package/sync/syncDb.ts +43 -36
  74. package/sync/syncDev.ts +74 -65
  75. package/sync/syncMenu.ts +190 -55
  76. package/tests/api-integration-array-number.test.ts +282 -0
  77. package/tests/befly-config-env.test.ts +78 -0
  78. package/tests/cacheHelper.test.ts +135 -104
  79. package/tests/cacheKeys.test.ts +41 -0
  80. package/tests/cipher.test.ts +90 -89
  81. package/tests/dbHelper-advanced.test.ts +140 -134
  82. package/tests/dbHelper-all-array-types.test.ts +316 -0
  83. package/tests/dbHelper-array-serialization.test.ts +258 -0
  84. package/tests/dbHelper-columns.test.ts +56 -55
  85. package/tests/dbHelper-execute.test.ts +45 -44
  86. package/tests/dbHelper-joins.test.ts +124 -119
  87. package/tests/fields-redis-cache.test.ts +29 -27
  88. package/tests/fields-validate.test.ts +38 -38
  89. package/tests/getClientIp.test.ts +54 -0
  90. package/tests/integration.test.ts +69 -67
  91. package/tests/jwt.test.ts +27 -26
  92. package/tests/logger.test.ts +267 -34
  93. package/tests/rateLimit-hook.test.ts +477 -0
  94. package/tests/redisHelper.test.ts +187 -188
  95. package/tests/redisKeys.test.ts +6 -73
  96. package/tests/scanConfig.test.ts +144 -0
  97. package/tests/sqlBuilder-advanced.test.ts +217 -215
  98. package/tests/sqlBuilder.test.ts +92 -91
  99. package/tests/sync-connection.test.ts +29 -29
  100. package/tests/syncDb-apply.test.ts +97 -96
  101. package/tests/syncDb-array-number.test.ts +160 -0
  102. package/tests/syncDb-constants.test.ts +48 -47
  103. package/tests/syncDb-ddl.test.ts +99 -98
  104. package/tests/syncDb-helpers.test.ts +29 -28
  105. package/tests/syncDb-schema.test.ts +61 -60
  106. package/tests/syncDb-types.test.ts +60 -59
  107. package/tests/syncMenu-paths.test.ts +68 -0
  108. package/tests/util.test.ts +42 -41
  109. package/tests/validator-array-number.test.ts +310 -0
  110. package/tests/validator-default.test.ts +373 -0
  111. package/tests/validator.test.ts +271 -266
  112. package/tsconfig.json +4 -5
  113. package/types/api.d.ts +7 -12
  114. package/types/befly.d.ts +60 -13
  115. package/types/cache.d.ts +8 -4
  116. package/types/common.d.ts +17 -9
  117. package/types/context.d.ts +2 -2
  118. package/types/crypto.d.ts +23 -0
  119. package/types/database.d.ts +19 -19
  120. package/types/hook.d.ts +2 -2
  121. package/types/jwt.d.ts +118 -0
  122. package/types/logger.d.ts +30 -0
  123. package/types/plugin.d.ts +4 -4
  124. package/types/redis.d.ts +7 -3
  125. package/types/roleApisCache.ts +23 -0
  126. package/types/sync.d.ts +10 -10
  127. package/types/table.d.ts +50 -9
  128. package/types/validate.d.ts +69 -0
  129. package/utils/addonHelper.ts +90 -0
  130. package/utils/arrayKeysToCamel.ts +18 -0
  131. package/utils/calcPerfTime.ts +13 -0
  132. package/utils/configTypes.ts +3 -0
  133. package/utils/cors.ts +19 -0
  134. package/utils/fieldClear.ts +75 -0
  135. package/utils/genShortId.ts +12 -0
  136. package/utils/getClientIp.ts +45 -0
  137. package/utils/keysToCamel.ts +22 -0
  138. package/utils/keysToSnake.ts +22 -0
  139. package/utils/modules.ts +98 -0
  140. package/utils/pickFields.ts +19 -0
  141. package/utils/process.ts +56 -0
  142. package/utils/regex.ts +225 -0
  143. package/utils/response.ts +115 -0
  144. package/utils/route.ts +23 -0
  145. package/utils/scanConfig.ts +142 -0
  146. package/utils/scanFiles.ts +48 -0
  147. package/.prettierignore +0 -2
  148. package/.prettierrc +0 -12
  149. package/docs/1-/345/237/272/346/234/254/344/273/213/347/273/215.md +0 -35
  150. package/docs/2-/345/210/235/346/255/245/344/275/223/351/252/214.md +0 -64
  151. package/docs/3-/347/254/254/344/270/200/344/270/252/346/216/245/345/217/243.md +0 -46
  152. package/docs/4-/346/223/215/344/275/234/346/225/260/346/215/256/345/272/223.md +0 -172
  153. package/hooks/requestLogger.ts +0 -84
  154. package/types/index.ts +0 -24
  155. package/util.ts +0 -283
@@ -1,12 +1,12 @@
1
- /**
1
+ /**
2
2
  * Redis 助手 - TypeScript 版本
3
3
  * 提供 Redis 操作的便捷方法
4
4
  */
5
5
 
6
- import { SQL, RedisClient } from 'bun';
7
- import { Logger } from './logger.js';
8
- import { Connect } from './connect.js';
9
- import type { KeyValue } from 'befly-shared/types';
6
+ import { RedisClient } from "bun";
7
+
8
+ import { Connect } from "./connect.js";
9
+ import { Logger } from "./logger.js";
10
10
 
11
11
  /**
12
12
  * Redis 助手类
@@ -15,17 +15,34 @@ export class RedisHelper {
15
15
  private client: RedisClient;
16
16
  private prefix: string;
17
17
 
18
+ private readonly slowThresholdMs: number = 500;
19
+
18
20
  /**
19
21
  * 构造函数
20
22
  * @param prefix - Key 前缀
21
23
  */
22
- constructor(prefix: string = '') {
24
+ constructor(prefix: string = "") {
23
25
  const client = Connect.getRedis();
24
26
  if (!client) {
25
- throw new Error('Redis 客户端未初始化,请先调用 Connect.connectRedis()');
27
+ throw new Error("Redis 客户端未初始化,请先调用 Connect.connectRedis()");
26
28
  }
27
29
  this.client = client;
28
- this.prefix = prefix ? `${prefix}:` : '';
30
+ this.prefix = prefix ? `${prefix}:` : "";
31
+ }
32
+
33
+ private logSlow(cmd: string, key: string, duration: number, extra: Record<string, any> = {}): void {
34
+ if (duration <= this.slowThresholdMs) return;
35
+ Logger.warn(
36
+ {
37
+ subsystem: "redis",
38
+ event: "slow",
39
+ duration: duration,
40
+ cmd: cmd,
41
+ key: key,
42
+ extra: extra
43
+ },
44
+ "🐌 Redis 慢操作"
45
+ );
29
46
  }
30
47
 
31
48
  /**
@@ -40,12 +57,21 @@ export class RedisHelper {
40
57
  const data = JSON.stringify(obj);
41
58
  const pkey = `${this.prefix}${key}`;
42
59
 
60
+ const startTime = Date.now();
61
+
43
62
  if (ttl) {
44
- return await this.client.setex(pkey, ttl, data);
63
+ const res = await this.client.setex(pkey, ttl, data);
64
+ const duration = Date.now() - startTime;
65
+ this.logSlow("SETEX", pkey, duration, { ttl: ttl });
66
+ return res;
45
67
  }
46
- return await this.client.set(pkey, data);
68
+
69
+ const res = await this.client.set(pkey, data);
70
+ const duration = Date.now() - startTime;
71
+ this.logSlow("SET", pkey, duration);
72
+ return res;
47
73
  } catch (error: any) {
48
- Logger.error('Redis setObject 错误', error);
74
+ Logger.error({ err: error }, "Redis setObject 错误");
49
75
  return null;
50
76
  }
51
77
  }
@@ -58,10 +84,14 @@ export class RedisHelper {
58
84
  async getObject<T = any>(key: string): Promise<T | null> {
59
85
  try {
60
86
  const pkey = `${this.prefix}${key}`;
87
+
88
+ const startTime = Date.now();
61
89
  const data = await this.client.get(pkey);
90
+ const duration = Date.now() - startTime;
91
+ this.logSlow("GET", pkey, duration);
62
92
  return data ? JSON.parse(data) : null;
63
93
  } catch (error: any) {
64
- Logger.error('Redis getObject 错误', error);
94
+ Logger.error({ err: error }, "Redis getObject 错误");
65
95
  return null;
66
96
  }
67
97
  }
@@ -73,9 +103,13 @@ export class RedisHelper {
73
103
  async delObject(key: string): Promise<void> {
74
104
  try {
75
105
  const pkey = `${this.prefix}${key}`;
106
+
107
+ const startTime = Date.now();
76
108
  await this.client.del(pkey);
109
+ const duration = Date.now() - startTime;
110
+ this.logSlow("DEL", pkey, duration);
77
111
  } catch (error: any) {
78
- Logger.error('Redis delObject 错误', error);
112
+ Logger.error({ err: error }, "Redis delObject 错误");
79
113
  }
80
114
  }
81
115
 
@@ -93,11 +127,16 @@ export class RedisHelper {
93
127
  const timestamp = Date.now();
94
128
  const key = `${this.prefix}time_id:${timestamp}`;
95
129
 
130
+ const startTime = Date.now();
131
+
96
132
  const counter = await this.client.incr(key);
97
133
  if (counter === 1) {
98
134
  await this.client.expire(key, 1);
99
135
  }
100
136
 
137
+ const duration = Date.now() - startTime;
138
+ this.logSlow("INCR", key, duration, { expireSeconds: 1 });
139
+
101
140
  // 基于时间戳偏移起点,后缀 100-999 循环
102
141
  const suffix = 100 + (((timestamp % 900) + counter - 1) % 900);
103
142
 
@@ -113,12 +152,21 @@ export class RedisHelper {
113
152
  async setString(key: string, value: string, ttl: number | null = null): Promise<string | null> {
114
153
  try {
115
154
  const pkey = `${this.prefix}${key}`;
155
+
156
+ const startTime = Date.now();
116
157
  if (ttl) {
117
- return await this.client.setex(pkey, ttl, value);
158
+ const res = await this.client.setex(pkey, ttl, value);
159
+ const duration = Date.now() - startTime;
160
+ this.logSlow("SETEX", pkey, duration, { ttl: ttl });
161
+ return res;
118
162
  }
119
- return await this.client.set(pkey, value);
163
+
164
+ const res = await this.client.set(pkey, value);
165
+ const duration = Date.now() - startTime;
166
+ this.logSlow("SET", pkey, duration);
167
+ return res;
120
168
  } catch (error: any) {
121
- Logger.error('Redis setString 错误', error);
169
+ Logger.error({ err: error }, "Redis setString 错误");
122
170
  return null;
123
171
  }
124
172
  }
@@ -130,9 +178,14 @@ export class RedisHelper {
130
178
  async getString(key: string): Promise<string | null> {
131
179
  try {
132
180
  const pkey = `${this.prefix}${key}`;
133
- return await this.client.get(pkey);
181
+
182
+ const startTime = Date.now();
183
+ const res = await this.client.get(pkey);
184
+ const duration = Date.now() - startTime;
185
+ this.logSlow("GET", pkey, duration);
186
+ return res;
134
187
  } catch (error: any) {
135
- Logger.error('Redis getString 错误', error);
188
+ Logger.error({ err: error }, "Redis getString 错误");
136
189
  return null;
137
190
  }
138
191
  }
@@ -145,13 +198,62 @@ export class RedisHelper {
145
198
  async exists(key: string): Promise<boolean> {
146
199
  try {
147
200
  const pkey = `${this.prefix}${key}`;
148
- return await this.client.exists(pkey);
201
+
202
+ const startTime = Date.now();
203
+ const res = await this.client.exists(pkey);
204
+ const duration = Date.now() - startTime;
205
+ this.logSlow("EXISTS", pkey, duration);
206
+ return res;
149
207
  } catch (error: any) {
150
- Logger.error('Redis exists 错误', error);
208
+ Logger.error({ err: error }, "Redis exists 错误");
151
209
  return false;
152
210
  }
153
211
  }
154
212
 
213
+ /**
214
+ * 原子自增
215
+ * @param key - 键名
216
+ * @returns 自增后的值
217
+ */
218
+ async incr(key: string): Promise<number> {
219
+ try {
220
+ const pkey = `${this.prefix}${key}`;
221
+
222
+ const startTime = Date.now();
223
+ const res = await this.client.incr(pkey);
224
+ const duration = Date.now() - startTime;
225
+ this.logSlow("INCR", pkey, duration);
226
+ return res;
227
+ } catch (error: any) {
228
+ Logger.error({ err: error }, "Redis incr 错误");
229
+ return 0;
230
+ }
231
+ }
232
+
233
+ /**
234
+ * 原子自增并在首次自增时设置过期时间(常用于限流/计数)
235
+ * @param key - 键名
236
+ * @param seconds - 过期秒数
237
+ * @returns 自增后的值
238
+ */
239
+ async incrWithExpire(key: string, seconds: number): Promise<number> {
240
+ try {
241
+ const pkey = `${this.prefix}${key}`;
242
+
243
+ const startTime = Date.now();
244
+ const res = await this.client.incr(pkey);
245
+ if (res === 1) {
246
+ await this.client.expire(pkey, seconds);
247
+ }
248
+ const duration = Date.now() - startTime;
249
+ this.logSlow("INCR", pkey, duration, { expireSeconds: seconds });
250
+ return res;
251
+ } catch (error: any) {
252
+ Logger.error({ err: error }, "Redis incrWithExpire 错误");
253
+ return 0;
254
+ }
255
+ }
256
+
155
257
  /**
156
258
  * 设置过期时间
157
259
  * @param key - 键名
@@ -160,9 +262,14 @@ export class RedisHelper {
160
262
  async expire(key: string, seconds: number): Promise<number> {
161
263
  try {
162
264
  const pkey = `${this.prefix}${key}`;
163
- return await this.client.expire(pkey, seconds);
265
+
266
+ const startTime = Date.now();
267
+ const res = await this.client.expire(pkey, seconds);
268
+ const duration = Date.now() - startTime;
269
+ this.logSlow("EXPIRE", pkey, duration, { seconds: seconds });
270
+ return res;
164
271
  } catch (error: any) {
165
- Logger.error('Redis expire 错误', error);
272
+ Logger.error({ err: error }, "Redis expire 错误");
166
273
  return 0;
167
274
  }
168
275
  }
@@ -174,9 +281,14 @@ export class RedisHelper {
174
281
  async ttl(key: string): Promise<number> {
175
282
  try {
176
283
  const pkey = `${this.prefix}${key}`;
177
- return await this.client.ttl(pkey);
284
+
285
+ const startTime = Date.now();
286
+ const res = await this.client.ttl(pkey);
287
+ const duration = Date.now() - startTime;
288
+ this.logSlow("TTL", pkey, duration);
289
+ return res;
178
290
  } catch (error: any) {
179
- Logger.error('Redis ttl 错误', error);
291
+ Logger.error({ err: error }, "Redis ttl 错误");
180
292
  return -1;
181
293
  }
182
294
  }
@@ -195,7 +307,7 @@ export class RedisHelper {
195
307
  const results = await Promise.all(keys.map((key) => this.ttl(key)));
196
308
  return results;
197
309
  } catch (error: any) {
198
- Logger.error('Redis ttlBatch 错误', error);
310
+ Logger.error({ err: error }, "Redis ttlBatch 错误");
199
311
  return keys.map(() => -1);
200
312
  }
201
313
  }
@@ -211,9 +323,14 @@ export class RedisHelper {
211
323
  if (members.length === 0) return 0;
212
324
 
213
325
  const pkey = `${this.prefix}${key}`;
214
- return await this.client.sadd(pkey, ...members);
326
+
327
+ const startTime = Date.now();
328
+ const res = await this.client.sadd(pkey, ...members);
329
+ const duration = Date.now() - startTime;
330
+ this.logSlow("SADD", pkey, duration, { membersCount: members.length });
331
+ return res;
215
332
  } catch (error: any) {
216
- Logger.error('Redis sadd 错误', error);
333
+ Logger.error({ err: error }, "Redis sadd 错误");
217
334
  return 0;
218
335
  }
219
336
  }
@@ -227,9 +344,14 @@ export class RedisHelper {
227
344
  async sismember(key: string, member: string): Promise<boolean> {
228
345
  try {
229
346
  const pkey = `${this.prefix}${key}`;
230
- return await this.client.sismember(pkey, member);
347
+
348
+ const startTime = Date.now();
349
+ const res = await this.client.sismember(pkey, member);
350
+ const duration = Date.now() - startTime;
351
+ this.logSlow("SISMEMBER", pkey, duration);
352
+ return res;
231
353
  } catch (error: any) {
232
- Logger.error('Redis sismember 错误', error);
354
+ Logger.error({ err: error }, "Redis sismember 错误");
233
355
  return false;
234
356
  }
235
357
  }
@@ -242,9 +364,14 @@ export class RedisHelper {
242
364
  async scard(key: string): Promise<number> {
243
365
  try {
244
366
  const pkey = `${this.prefix}${key}`;
245
- return await this.client.scard(pkey);
367
+
368
+ const startTime = Date.now();
369
+ const res = await this.client.scard(pkey);
370
+ const duration = Date.now() - startTime;
371
+ this.logSlow("SCARD", pkey, duration);
372
+ return res;
246
373
  } catch (error: any) {
247
- Logger.error('Redis scard 错误', error);
374
+ Logger.error({ err: error }, "Redis scard 错误");
248
375
  return 0;
249
376
  }
250
377
  }
@@ -257,9 +384,14 @@ export class RedisHelper {
257
384
  async smembers(key: string): Promise<string[]> {
258
385
  try {
259
386
  const pkey = `${this.prefix}${key}`;
260
- return await this.client.smembers(pkey);
387
+
388
+ const startTime = Date.now();
389
+ const res = await this.client.smembers(pkey);
390
+ const duration = Date.now() - startTime;
391
+ this.logSlow("SMEMBERS", pkey, duration);
392
+ return res;
261
393
  } catch (error: any) {
262
- Logger.error('Redis smembers 错误', error);
394
+ Logger.error({ err: error }, "Redis smembers 错误");
263
395
  return [];
264
396
  }
265
397
  }
@@ -278,7 +410,7 @@ export class RedisHelper {
278
410
  const results = await Promise.all(items.map((item) => this.sadd(item.key, item.members)));
279
411
  return results.reduce((sum, count) => sum + count, 0);
280
412
  } catch (error: any) {
281
- Logger.error('Redis saddBatch 错误', error);
413
+ Logger.error({ err: error }, "Redis saddBatch 错误");
282
414
  return 0;
283
415
  }
284
416
  }
@@ -296,7 +428,7 @@ export class RedisHelper {
296
428
  try {
297
429
  return await Promise.all(items.map((item) => this.sismember(item.key, item.member)));
298
430
  } catch (error: any) {
299
- Logger.error('Redis sismemberBatch 错误', error);
431
+ Logger.error({ err: error }, "Redis sismemberBatch 错误");
300
432
  return items.map(() => false);
301
433
  }
302
434
  }
@@ -309,9 +441,14 @@ export class RedisHelper {
309
441
  async del(key: string): Promise<number> {
310
442
  try {
311
443
  const pkey = `${this.prefix}${key}`;
312
- return await this.client.del(pkey);
444
+
445
+ const startTime = Date.now();
446
+ const res = await this.client.del(pkey);
447
+ const duration = Date.now() - startTime;
448
+ this.logSlow("DEL", pkey, duration);
449
+ return res;
313
450
  } catch (error: any) {
314
- Logger.error('Redis del 错误', error);
451
+ Logger.error({ err: error }, "Redis del 错误");
315
452
  return 0;
316
453
  }
317
454
  }
@@ -335,7 +472,7 @@ export class RedisHelper {
335
472
  );
336
473
  return results.reduce((sum, count) => sum + count, 0);
337
474
  } catch (error: any) {
338
- Logger.error('Redis delBatch 错误', error);
475
+ Logger.error({ err: error }, "Redis delBatch 错误");
339
476
  return 0;
340
477
  }
341
478
  }
@@ -354,7 +491,7 @@ export class RedisHelper {
354
491
  const results = await Promise.all(items.map((item) => this.setObject(item.key, item.value, item.ttl ?? null)));
355
492
  return results.filter((r) => r !== null).length;
356
493
  } catch (error: any) {
357
- Logger.error('Redis setBatch 错误', error);
494
+ Logger.error({ err: error }, "Redis setBatch 错误");
358
495
  return 0;
359
496
  }
360
497
  }
@@ -373,7 +510,7 @@ export class RedisHelper {
373
510
  const results = await Promise.all(keys.map((key) => this.getObject<T>(key)));
374
511
  return results;
375
512
  } catch (error: any) {
376
- Logger.error('Redis getBatch 错误', error);
513
+ Logger.error({ err: error }, "Redis getBatch 错误");
377
514
  return keys.map(() => null);
378
515
  }
379
516
  }
@@ -391,7 +528,7 @@ export class RedisHelper {
391
528
  try {
392
529
  return await Promise.all(keys.map((key) => this.exists(key)));
393
530
  } catch (error: any) {
394
- Logger.error('Redis existsBatch 错误', error);
531
+ Logger.error({ err: error }, "Redis existsBatch 错误");
395
532
  return keys.map(() => false);
396
533
  }
397
534
  }
@@ -410,7 +547,7 @@ export class RedisHelper {
410
547
  const results = await Promise.all(items.map((item) => this.expire(item.key, item.seconds)));
411
548
  return results.filter((r) => r > 0).length;
412
549
  } catch (error: any) {
413
- Logger.error('Redis expireBatch 错误', error);
550
+ Logger.error({ err: error }, "Redis expireBatch 错误");
414
551
  return 0;
415
552
  }
416
553
  }
@@ -421,9 +558,13 @@ export class RedisHelper {
421
558
  */
422
559
  async ping(): Promise<string> {
423
560
  try {
424
- return await this.client.ping();
561
+ const startTime = Date.now();
562
+ const res = await this.client.ping();
563
+ const duration = Date.now() - startTime;
564
+ this.logSlow("PING", "(no-key)", duration);
565
+ return res;
425
566
  } catch (error: any) {
426
- Logger.error('Redis ping 错误', error);
567
+ Logger.error({ err: error }, "Redis ping 错误");
427
568
  throw error;
428
569
  }
429
570
  }