imean-service-engine 2.0.0 → 2.0.2

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 (72) hide show
  1. package/dist/index.d.mts +77 -52
  2. package/dist/index.d.ts +77 -52
  3. package/dist/index.js +2078 -1945
  4. package/dist/index.mjs +2076 -1944
  5. package/package.json +9 -2
  6. package/.vscode/settings.json +0 -8
  7. package/src/core/checker.ts +0 -33
  8. package/src/core/decorators.test.ts +0 -96
  9. package/src/core/decorators.ts +0 -68
  10. package/src/core/engine.test.ts +0 -218
  11. package/src/core/engine.ts +0 -635
  12. package/src/core/errors.ts +0 -28
  13. package/src/core/factory.test.ts +0 -73
  14. package/src/core/factory.ts +0 -92
  15. package/src/core/logger.ts +0 -65
  16. package/src/core/testing.ts +0 -73
  17. package/src/core/types.ts +0 -191
  18. package/src/index.ts +0 -49
  19. package/src/metadata/README.md +0 -422
  20. package/src/metadata/metadata.test.ts +0 -369
  21. package/src/metadata/metadata.ts +0 -512
  22. package/src/plugins/action/action-plugin.test.ts +0 -660
  23. package/src/plugins/action/decorator.ts +0 -14
  24. package/src/plugins/action/index.ts +0 -4
  25. package/src/plugins/action/plugin.ts +0 -349
  26. package/src/plugins/action/types.ts +0 -49
  27. package/src/plugins/action/utils.test.ts +0 -196
  28. package/src/plugins/action/utils.ts +0 -111
  29. package/src/plugins/cache/adapter.test.ts +0 -689
  30. package/src/plugins/cache/adapter.ts +0 -324
  31. package/src/plugins/cache/cache-plugin.test.ts +0 -269
  32. package/src/plugins/cache/decorator.ts +0 -26
  33. package/src/plugins/cache/index.ts +0 -20
  34. package/src/plugins/cache/plugin.ts +0 -299
  35. package/src/plugins/cache/types.ts +0 -69
  36. package/src/plugins/client-code/client-code-plugin.test.ts +0 -511
  37. package/src/plugins/client-code/format.ts +0 -9
  38. package/src/plugins/client-code/generator.test.ts +0 -52
  39. package/src/plugins/client-code/generator.ts +0 -263
  40. package/src/plugins/client-code/index.ts +0 -15
  41. package/src/plugins/client-code/plugin.ts +0 -158
  42. package/src/plugins/client-code/types.ts +0 -52
  43. package/src/plugins/client-code/utils.ts +0 -164
  44. package/src/plugins/graceful-shutdown/graceful-shutdown-plugin.test.ts +0 -401
  45. package/src/plugins/graceful-shutdown/index.ts +0 -3
  46. package/src/plugins/graceful-shutdown/plugin.ts +0 -279
  47. package/src/plugins/graceful-shutdown/types.ts +0 -17
  48. package/src/plugins/rate-limit/rate-limit-plugin.example.ts +0 -171
  49. package/src/plugins/route/components/Layout.tsx +0 -42
  50. package/src/plugins/route/components/ServiceStatusPage.tsx +0 -141
  51. package/src/plugins/route/decorator.ts +0 -50
  52. package/src/plugins/route/index.ts +0 -16
  53. package/src/plugins/route/plugin.ts +0 -218
  54. package/src/plugins/route/route-plugin.test.ts +0 -759
  55. package/src/plugins/route/types.ts +0 -72
  56. package/src/plugins/schedule/README.md +0 -309
  57. package/src/plugins/schedule/decorator.ts +0 -25
  58. package/src/plugins/schedule/index.ts +0 -12
  59. package/src/plugins/schedule/mock-etcd.ts +0 -145
  60. package/src/plugins/schedule/plugin.ts +0 -164
  61. package/src/plugins/schedule/schedule-plugin.test.ts +0 -312
  62. package/src/plugins/schedule/scheduler.ts +0 -164
  63. package/src/plugins/schedule/types.ts +0 -94
  64. package/src/plugins/schedule/utils.test.ts +0 -163
  65. package/src/plugins/schedule/utils.ts +0 -41
  66. package/tests/integration/client.test.ts +0 -203
  67. package/tests/integration/dev-service.ts +0 -301
  68. package/tests/integration/generated/client.ts +0 -123
  69. package/tests/integration/start-service.ts +0 -21
  70. package/tsconfig.json +0 -27
  71. package/tsup.config.ts +0 -16
  72. package/vitest.config.ts +0 -19
@@ -1,689 +0,0 @@
1
- import { beforeEach, describe, expect, it } from "vitest";
2
- import { MemoryCacheAdapter, RedisCacheAdapter } from "./adapter";
3
- import { CacheItem } from "./types";
4
-
5
- describe("CacheAdapter", () => {
6
- describe("MemoryCacheAdapter", () => {
7
- let adapter: MemoryCacheAdapter;
8
-
9
- beforeEach(() => {
10
- adapter = new MemoryCacheAdapter();
11
- });
12
-
13
- describe("基本操作", () => {
14
- it("应该能够设置和获取缓存项", async () => {
15
- const item: CacheItem<string> = {
16
- value: "test-value",
17
- expiresAt: Date.now() + 10000,
18
- createdAt: Date.now(),
19
- };
20
-
21
- await adapter.set("test-key", item);
22
- const result = await adapter.get("test-key");
23
-
24
- expect(result).not.toBeNull();
25
- expect(result?.value).toBe("test-value");
26
- expect(result?.expiresAt).toBe(item.expiresAt);
27
- expect(result?.createdAt).toBe(item.createdAt);
28
- });
29
-
30
- it("应该返回 null 当键不存在时", async () => {
31
- const result = await adapter.get("non-existent-key");
32
- expect(result).toBeNull();
33
- });
34
-
35
- it("应该能够删除缓存项", async () => {
36
- const item: CacheItem<string> = {
37
- value: "test-value",
38
- expiresAt: Date.now() + 10000,
39
- createdAt: Date.now(),
40
- };
41
-
42
- await adapter.set("test-key", item);
43
- const deleted = await adapter.delete("test-key");
44
- expect(deleted).toBe(true);
45
-
46
- const result = await adapter.get("test-key");
47
- expect(result).toBeNull();
48
- });
49
-
50
- it("删除不存在的键应该返回 false", async () => {
51
- const deleted = await adapter.delete("non-existent-key");
52
- expect(deleted).toBe(false);
53
- });
54
-
55
- it("应该能够清空所有缓存", async () => {
56
- await adapter.set("key1", {
57
- value: "value1",
58
- expiresAt: Date.now() + 10000,
59
- createdAt: Date.now(),
60
- });
61
- await adapter.set("key2", {
62
- value: "value2",
63
- expiresAt: Date.now() + 10000,
64
- createdAt: Date.now(),
65
- });
66
-
67
- await adapter.clear();
68
-
69
- const stats = await adapter.getStats();
70
- expect(stats.size).toBe(0);
71
- });
72
- });
73
-
74
- describe("过期处理", () => {
75
- it("应该自动删除过期的缓存项", async () => {
76
- const expiredItem: CacheItem<string> = {
77
- value: "expired-value",
78
- expiresAt: Date.now() - 1000, // 已过期
79
- createdAt: Date.now() - 5000,
80
- };
81
-
82
- await adapter.set("expired-key", expiredItem);
83
- const result = await adapter.get("expired-key");
84
-
85
- expect(result).toBeNull();
86
- });
87
-
88
- it("应该保留未过期的缓存项", async () => {
89
- const validItem: CacheItem<string> = {
90
- value: "valid-value",
91
- expiresAt: Date.now() + 10000, // 10秒后过期
92
- createdAt: Date.now(),
93
- };
94
-
95
- await adapter.set("valid-key", validItem);
96
- const result = await adapter.get("valid-key");
97
-
98
- expect(result).not.toBeNull();
99
- expect(result?.value).toBe("valid-value");
100
- });
101
- });
102
-
103
- describe("键管理", () => {
104
- it("应该能够获取所有缓存键", async () => {
105
- await adapter.set("key1", {
106
- value: "value1",
107
- expiresAt: Date.now() + 10000,
108
- createdAt: Date.now(),
109
- });
110
- await adapter.set("key2", {
111
- value: "value2",
112
- expiresAt: Date.now() + 10000,
113
- createdAt: Date.now(),
114
- });
115
-
116
- const keys = await adapter.keys();
117
- expect(keys).toContain("key1");
118
- expect(keys).toContain("key2");
119
- expect(keys.length).toBe(2);
120
- });
121
-
122
- it("清空后应该返回空数组", async () => {
123
- await adapter.set("key1", {
124
- value: "value1",
125
- expiresAt: Date.now() + 10000,
126
- createdAt: Date.now(),
127
- });
128
-
129
- await adapter.clear();
130
- const keys = await adapter.keys();
131
- expect(keys).toEqual([]);
132
- });
133
- });
134
-
135
- describe("统计信息", () => {
136
- it("应该能够获取缓存统计信息", async () => {
137
- const now = Date.now();
138
- await adapter.set("key1", {
139
- value: "value1",
140
- expiresAt: now + 10000,
141
- createdAt: now,
142
- });
143
- await adapter.set("key2", {
144
- value: "value2",
145
- expiresAt: now + 20000,
146
- createdAt: now + 1000,
147
- });
148
-
149
- const stats = await adapter.getStats();
150
- expect(stats.size).toBe(2);
151
- expect(stats.entries).toHaveLength(2);
152
- expect(stats.entries[0]).toHaveProperty("key");
153
- expect(stats.entries[0]).toHaveProperty("expiresAt");
154
- expect(stats.entries[0]).toHaveProperty("createdAt");
155
- });
156
-
157
- it("应该排除过期的项", async () => {
158
- await adapter.set("valid-key", {
159
- value: "valid",
160
- expiresAt: Date.now() + 10000,
161
- createdAt: Date.now(),
162
- });
163
- await adapter.set("expired-key", {
164
- value: "expired",
165
- expiresAt: Date.now() - 1000,
166
- createdAt: Date.now() - 5000,
167
- });
168
-
169
- const stats = await adapter.getStats();
170
- // 过期项在 get 时会被删除,所以统计中不包含
171
- expect(stats.size).toBe(1);
172
- expect(stats.entries[0].key).toBe("valid-key");
173
- });
174
- });
175
-
176
- describe("类型支持", () => {
177
- it("应该支持不同的数据类型", async () => {
178
- // 字符串
179
- await adapter.set("string-key", {
180
- value: "string-value",
181
- expiresAt: Date.now() + 10000,
182
- createdAt: Date.now(),
183
- });
184
-
185
- // 数字
186
- await adapter.set("number-key", {
187
- value: 123,
188
- expiresAt: Date.now() + 10000,
189
- createdAt: Date.now(),
190
- });
191
-
192
- // 对象
193
- await adapter.set("object-key", {
194
- value: { name: "test", age: 25 },
195
- expiresAt: Date.now() + 10000,
196
- createdAt: Date.now(),
197
- });
198
-
199
- // 数组
200
- await adapter.set("array-key", {
201
- value: [1, 2, 3],
202
- expiresAt: Date.now() + 10000,
203
- createdAt: Date.now(),
204
- });
205
-
206
- const stringResult = await adapter.get<string>("string-key");
207
- expect(stringResult?.value).toBe("string-value");
208
-
209
- const numberResult = await adapter.get<number>("number-key");
210
- expect(numberResult?.value).toBe(123);
211
-
212
- const objectResult = await adapter.get<{ name: string; age: number }>(
213
- "object-key"
214
- );
215
- expect(objectResult?.value).toEqual({ name: "test", age: 25 });
216
-
217
- const arrayResult = await adapter.get<number[]>("array-key");
218
- expect(arrayResult?.value).toEqual([1, 2, 3]);
219
- });
220
- });
221
-
222
- describe("定期清理", () => {
223
- it("应该能够批量清理过期项", async () => {
224
- const now = Date.now();
225
-
226
- // 添加一些过期项
227
- await adapter.set("expired1", {
228
- value: "expired1",
229
- expiresAt: now - 1000,
230
- createdAt: now - 5000,
231
- });
232
- await adapter.set("expired2", {
233
- value: "expired2",
234
- expiresAt: now - 500,
235
- createdAt: now - 3000,
236
- });
237
-
238
- // 添加一些有效项
239
- await adapter.set("valid1", {
240
- value: "valid1",
241
- expiresAt: now + 10000,
242
- createdAt: now,
243
- });
244
- await adapter.set("valid2", {
245
- value: "valid2",
246
- expiresAt: now + 20000,
247
- createdAt: now,
248
- });
249
-
250
- // 执行清理
251
- const cleaned = await adapter.cleanupExpired!();
252
- expect(cleaned).toBe(2);
253
-
254
- // 验证过期项已被删除
255
- const expired1 = await adapter.get("expired1");
256
- const expired2 = await adapter.get("expired2");
257
- expect(expired1).toBeNull();
258
- expect(expired2).toBeNull();
259
-
260
- // 验证有效项仍然存在
261
- const valid1 = await adapter.get("valid1");
262
- const valid2 = await adapter.get("valid2");
263
- expect(valid1).not.toBeNull();
264
- expect(valid2).not.toBeNull();
265
-
266
- // 验证统计信息
267
- const stats = await adapter.getStats();
268
- expect(stats.size).toBe(2);
269
- });
270
-
271
- it("清理时如果没有过期项应该返回 0", async () => {
272
- await adapter.set("valid1", {
273
- value: "valid1",
274
- expiresAt: Date.now() + 10000,
275
- createdAt: Date.now(),
276
- });
277
-
278
- const cleaned = await adapter.cleanupExpired!();
279
- expect(cleaned).toBe(0);
280
-
281
- const stats = await adapter.getStats();
282
- expect(stats.size).toBe(1);
283
- });
284
- });
285
- });
286
-
287
- describe("RedisCacheAdapter", () => {
288
- let adapter: RedisCacheAdapter;
289
- let mockClient: {
290
- storage: Map<string, { value: string; expiresAt?: number }>;
291
- get(key: string): Promise<string | null>;
292
- set(
293
- key: string,
294
- value: string,
295
- expiryMode?: string,
296
- time?: number
297
- ): Promise<string | null>;
298
- del(key: string): Promise<number>;
299
- keys(pattern: string): Promise<string[]>;
300
- };
301
-
302
- beforeEach(() => {
303
- mockClient = {
304
- storage: new Map(),
305
- async get(key: string): Promise<string | null> {
306
- const item = this.storage.get(key);
307
- if (!item) {
308
- return null;
309
- }
310
- // 检查是否过期
311
- if (item.expiresAt && item.expiresAt <= Date.now()) {
312
- this.storage.delete(key);
313
- return null;
314
- }
315
- return item.value;
316
- },
317
- async set(
318
- key: string,
319
- value: string,
320
- expiryMode?: string,
321
- time?: number
322
- ): Promise<string | null> {
323
- const expiresAt =
324
- expiryMode === "EX" && time ? Date.now() + time * 1000 : undefined;
325
- this.storage.set(key, { value, expiresAt });
326
- return "OK";
327
- },
328
- async del(key: string): Promise<number> {
329
- return this.storage.delete(key) ? 1 : 0;
330
- },
331
- async keys(pattern: string): Promise<string[]> {
332
- const prefix = pattern.replace("*", "");
333
- return Array.from(this.storage.keys()).filter((key) =>
334
- key.startsWith(prefix)
335
- );
336
- },
337
- };
338
-
339
- adapter = new RedisCacheAdapter({ client: mockClient });
340
- });
341
-
342
- describe("基本操作", () => {
343
- it("应该能够设置和获取缓存项", async () => {
344
- const item: CacheItem<string> = {
345
- value: "test-value",
346
- expiresAt: Date.now() + 10000,
347
- createdAt: Date.now(),
348
- };
349
-
350
- await adapter.set("test-key", item);
351
- const result = await adapter.get("test-key");
352
-
353
- expect(result).not.toBeNull();
354
- expect(result?.value).toBe("test-value");
355
- expect(result?.expiresAt).toBe(item.expiresAt);
356
- expect(result?.createdAt).toBe(item.createdAt);
357
- });
358
-
359
- it("应该返回 null 当键不存在时", async () => {
360
- const result = await adapter.get("non-existent-key");
361
- expect(result).toBeNull();
362
- });
363
-
364
- it("应该能够删除缓存项", async () => {
365
- const item: CacheItem<string> = {
366
- value: "test-value",
367
- expiresAt: Date.now() + 10000,
368
- createdAt: Date.now(),
369
- };
370
-
371
- await adapter.set("test-key", item);
372
- const deleted = await adapter.delete("test-key");
373
- expect(deleted).toBe(true);
374
-
375
- const result = await adapter.get("test-key");
376
- expect(result).toBeNull();
377
- });
378
-
379
- it("删除不存在的键应该返回 false", async () => {
380
- const deleted = await adapter.delete("non-existent-key");
381
- expect(deleted).toBe(false);
382
- });
383
-
384
- it("应该能够清空所有缓存", async () => {
385
- await adapter.set("key1", {
386
- value: "value1",
387
- expiresAt: Date.now() + 10000,
388
- createdAt: Date.now(),
389
- });
390
- await adapter.set("key2", {
391
- value: "value2",
392
- expiresAt: Date.now() + 10000,
393
- createdAt: Date.now(),
394
- });
395
-
396
- await adapter.clear();
397
-
398
- const stats = await adapter.getStats();
399
- expect(stats.size).toBe(0);
400
- });
401
- });
402
-
403
- describe("键前缀", () => {
404
- it("应该使用默认前缀 'cache:'", async () => {
405
- const item: CacheItem<string> = {
406
- value: "test-value",
407
- expiresAt: Date.now() + 10000,
408
- createdAt: Date.now(),
409
- };
410
-
411
- await adapter.set("test-key", item);
412
-
413
- // 检查 Redis 存储中是否有带前缀的键
414
- const keys = await mockClient.keys("cache:*");
415
- expect(keys).toContain("cache:test-key");
416
- });
417
-
418
- it("应该支持自定义前缀", async () => {
419
- const customAdapter = new RedisCacheAdapter({
420
- client: mockClient,
421
- keyPrefix: "myapp:cache:",
422
- });
423
-
424
- const item: CacheItem<string> = {
425
- value: "test-value",
426
- expiresAt: Date.now() + 10000,
427
- createdAt: Date.now(),
428
- };
429
-
430
- await customAdapter.set("test-key", item);
431
-
432
- const keys = await mockClient.keys("myapp:cache:*");
433
- expect(keys).toContain("myapp:cache:test-key");
434
- });
435
-
436
- it("keys() 应该返回不带前缀的键", async () => {
437
- await adapter.set("key1", {
438
- value: "value1",
439
- expiresAt: Date.now() + 10000,
440
- createdAt: Date.now(),
441
- });
442
-
443
- const keys = await adapter.keys();
444
- expect(keys).toContain("key1");
445
- expect(keys.every((key) => !key.startsWith("cache:"))).toBe(true);
446
- });
447
- });
448
-
449
- describe("过期处理", () => {
450
- it("应该自动删除过期的缓存项", async () => {
451
- const expiredItem: CacheItem<string> = {
452
- value: "expired-value",
453
- expiresAt: Date.now() - 1000, // 已过期
454
- createdAt: Date.now() - 5000,
455
- };
456
-
457
- await adapter.set("expired-key", expiredItem);
458
- const result = await adapter.get("expired-key");
459
-
460
- expect(result).toBeNull();
461
- });
462
-
463
- it("应该保留未过期的缓存项", async () => {
464
- const validItem: CacheItem<string> = {
465
- value: "valid-value",
466
- expiresAt: Date.now() + 10000, // 10秒后过期
467
- createdAt: Date.now(),
468
- };
469
-
470
- await adapter.set("valid-key", validItem);
471
- const result = await adapter.get("valid-key");
472
-
473
- expect(result).not.toBeNull();
474
- expect(result?.value).toBe("valid-value");
475
- });
476
-
477
- it("应该使用 Redis 的过期时间", async () => {
478
- const item: CacheItem<string> = {
479
- value: "test-value",
480
- expiresAt: Date.now() + 5000, // 5秒后过期
481
- createdAt: Date.now(),
482
- };
483
-
484
- await adapter.set("test-key", item);
485
-
486
- // 验证 Redis 存储中的过期时间设置
487
- const redisKey = "cache:test-key";
488
- const stored = mockClient.storage.get(redisKey);
489
- expect(stored).toBeDefined();
490
- expect(stored?.expiresAt).toBeGreaterThan(Date.now());
491
- });
492
- });
493
-
494
- describe("错误处理", () => {
495
- it("应该处理 JSON 解析错误", async () => {
496
- // 设置无效的 JSON 数据
497
- await mockClient.set("cache:invalid-key", "invalid-json");
498
-
499
- const result = await adapter.get("invalid-key");
500
- expect(result).toBeNull();
501
-
502
- // 验证无效数据已被删除
503
- const exists = mockClient.storage.has("cache:invalid-key");
504
- expect(exists).toBe(false);
505
- });
506
-
507
- it("应该处理 Redis 返回 null 的情况", async () => {
508
- const result = await adapter.get("non-existent-key");
509
- expect(result).toBeNull();
510
- });
511
- });
512
-
513
- describe("统计信息", () => {
514
- it("应该能够获取缓存统计信息", async () => {
515
- const now = Date.now();
516
- await adapter.set("key1", {
517
- value: "value1",
518
- expiresAt: now + 10000,
519
- createdAt: now,
520
- });
521
- await adapter.set("key2", {
522
- value: "value2",
523
- expiresAt: now + 20000,
524
- createdAt: now + 1000,
525
- });
526
-
527
- const stats = await adapter.getStats();
528
- expect(stats.size).toBe(2);
529
- expect(stats.entries).toHaveLength(2);
530
- expect(stats.entries[0]).toHaveProperty("key");
531
- expect(stats.entries[0]).toHaveProperty("expiresAt");
532
- expect(stats.entries[0]).toHaveProperty("createdAt");
533
- });
534
-
535
- it("应该排除过期的项", async () => {
536
- await adapter.set("valid-key", {
537
- value: "valid",
538
- expiresAt: Date.now() + 10000,
539
- createdAt: Date.now(),
540
- });
541
- await adapter.set("expired-key", {
542
- value: "expired",
543
- expiresAt: Date.now() - 1000,
544
- createdAt: Date.now() - 5000,
545
- });
546
-
547
- const stats = await adapter.getStats();
548
- // 过期项在 get 时会被删除,所以统计中不包含
549
- expect(stats.size).toBe(1);
550
- expect(stats.entries[0].key).toBe("valid-key");
551
- });
552
- });
553
-
554
- describe("类型支持", () => {
555
- it("应该支持不同的数据类型", async () => {
556
- // 字符串
557
- await adapter.set("string-key", {
558
- value: "string-value",
559
- expiresAt: Date.now() + 10000,
560
- createdAt: Date.now(),
561
- });
562
-
563
- // 数字
564
- await adapter.set("number-key", {
565
- value: 123,
566
- expiresAt: Date.now() + 10000,
567
- createdAt: Date.now(),
568
- });
569
-
570
- // 对象
571
- await adapter.set("object-key", {
572
- value: { name: "test", age: 25 },
573
- expiresAt: Date.now() + 10000,
574
- createdAt: Date.now(),
575
- });
576
-
577
- // 数组
578
- await adapter.set("array-key", {
579
- value: [1, 2, 3],
580
- expiresAt: Date.now() + 10000,
581
- createdAt: Date.now(),
582
- });
583
-
584
- const stringResult = await adapter.get<string>("string-key");
585
- expect(stringResult?.value).toBe("string-value");
586
-
587
- const numberResult = await adapter.get<number>("number-key");
588
- expect(numberResult?.value).toBe(123);
589
-
590
- const objectResult = await adapter.get<{ name: string; age: number }>(
591
- "object-key"
592
- );
593
- expect(objectResult?.value).toEqual({ name: "test", age: 25 });
594
-
595
- const arrayResult = await adapter.get<number[]>("array-key");
596
- expect(arrayResult?.value).toEqual([1, 2, 3]);
597
- });
598
- });
599
-
600
- describe("批量操作", () => {
601
- it("应该能够批量清空缓存", async () => {
602
- await adapter.set("key1", {
603
- value: "value1",
604
- expiresAt: Date.now() + 10000,
605
- createdAt: Date.now(),
606
- });
607
- await adapter.set("key2", {
608
- value: "value2",
609
- expiresAt: Date.now() + 10000,
610
- createdAt: Date.now(),
611
- });
612
- await adapter.set("key3", {
613
- value: "value3",
614
- expiresAt: Date.now() + 10000,
615
- createdAt: Date.now(),
616
- });
617
-
618
- await adapter.clear();
619
-
620
- const stats = await adapter.getStats();
621
- expect(stats.size).toBe(0);
622
- });
623
- });
624
-
625
- describe("定期清理", () => {
626
- it("应该能够批量清理过期项", async () => {
627
- const now = Date.now();
628
-
629
- // 添加一些过期项
630
- await adapter.set("expired1", {
631
- value: "expired1",
632
- expiresAt: now - 1000,
633
- createdAt: now - 5000,
634
- });
635
- await adapter.set("expired2", {
636
- value: "expired2",
637
- expiresAt: now - 500,
638
- createdAt: now - 3000,
639
- });
640
-
641
- // 添加一些有效项
642
- await adapter.set("valid1", {
643
- value: "valid1",
644
- expiresAt: now + 10000,
645
- createdAt: now,
646
- });
647
- await adapter.set("valid2", {
648
- value: "valid2",
649
- expiresAt: now + 20000,
650
- createdAt: now,
651
- });
652
-
653
- // 执行清理
654
- const cleaned = await adapter.cleanupExpired!();
655
- expect(cleaned).toBe(2);
656
-
657
- // 验证过期项已被删除
658
- const expired1 = await adapter.get("expired1");
659
- const expired2 = await adapter.get("expired2");
660
- expect(expired1).toBeNull();
661
- expect(expired2).toBeNull();
662
-
663
- // 验证有效项仍然存在
664
- const valid1 = await adapter.get("valid1");
665
- const valid2 = await adapter.get("valid2");
666
- expect(valid1).not.toBeNull();
667
- expect(valid2).not.toBeNull();
668
-
669
- // 验证统计信息
670
- const stats = await adapter.getStats();
671
- expect(stats.size).toBe(2);
672
- });
673
-
674
- it("清理时如果没有过期项应该返回 0", async () => {
675
- await adapter.set("valid1", {
676
- value: "valid1",
677
- expiresAt: Date.now() + 10000,
678
- createdAt: Date.now(),
679
- });
680
-
681
- const cleaned = await adapter.cleanupExpired!();
682
- expect(cleaned).toBe(0);
683
-
684
- const stats = await adapter.getStats();
685
- expect(stats.size).toBe(1);
686
- });
687
- });
688
- });
689
- });