@taicode/common-server 3.7.5 → 3.7.7

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 (62) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +9 -10
  3. package/output/context/index.d.ts +0 -6
  4. package/output/context/index.d.ts.map +0 -1
  5. package/output/context/index.js +0 -14
  6. package/output/context/index.test.d.ts +0 -2
  7. package/output/context/index.test.d.ts.map +0 -1
  8. package/output/context/index.test.js +0 -14
  9. package/output/index.d.ts +0 -5
  10. package/output/index.d.ts.map +0 -1
  11. package/output/index.js +0 -5
  12. package/output/rate-limiter/index.d.ts +0 -4
  13. package/output/rate-limiter/index.d.ts.map +0 -1
  14. package/output/rate-limiter/index.js +0 -3
  15. package/output/rate-limiter/memory-store.d.ts +0 -12
  16. package/output/rate-limiter/memory-store.d.ts.map +0 -1
  17. package/output/rate-limiter/memory-store.js +0 -46
  18. package/output/rate-limiter/rate-limiter.d.ts +0 -17
  19. package/output/rate-limiter/rate-limiter.d.ts.map +0 -1
  20. package/output/rate-limiter/rate-limiter.js +0 -64
  21. package/output/rate-limiter/types.d.ts +0 -27
  22. package/output/rate-limiter/types.d.ts.map +0 -1
  23. package/output/rate-limiter/types.js +0 -1
  24. package/output/redis-queue/index.d.ts +0 -8
  25. package/output/redis-queue/index.d.ts.map +0 -1
  26. package/output/redis-queue/index.js +0 -6
  27. package/output/redis-queue/redis-queue-batch-consumer.d.ts +0 -97
  28. package/output/redis-queue/redis-queue-batch-consumer.d.ts.map +0 -1
  29. package/output/redis-queue/redis-queue-batch-consumer.js +0 -341
  30. package/output/redis-queue/redis-queue-batch-consumer.test.d.ts +0 -26
  31. package/output/redis-queue/redis-queue-batch-consumer.test.d.ts.map +0 -1
  32. package/output/redis-queue/redis-queue-batch-consumer.test.js +0 -341
  33. package/output/redis-queue/redis-queue-common.d.ts +0 -73
  34. package/output/redis-queue/redis-queue-common.d.ts.map +0 -1
  35. package/output/redis-queue/redis-queue-common.js +0 -303
  36. package/output/redis-queue/redis-queue-common.test.d.ts +0 -19
  37. package/output/redis-queue/redis-queue-common.test.d.ts.map +0 -1
  38. package/output/redis-queue/redis-queue-common.test.js +0 -585
  39. package/output/redis-queue/redis-queue-consumer.d.ts +0 -95
  40. package/output/redis-queue/redis-queue-consumer.d.ts.map +0 -1
  41. package/output/redis-queue/redis-queue-consumer.js +0 -327
  42. package/output/redis-queue/redis-queue-consumer.test.d.ts +0 -26
  43. package/output/redis-queue/redis-queue-consumer.test.d.ts.map +0 -1
  44. package/output/redis-queue/redis-queue-consumer.test.js +0 -316
  45. package/output/redis-queue/redis-queue-provider.d.ts +0 -69
  46. package/output/redis-queue/redis-queue-provider.d.ts.map +0 -1
  47. package/output/redis-queue/redis-queue-provider.js +0 -205
  48. package/output/redis-queue/redis-queue-provider.test.d.ts +0 -28
  49. package/output/redis-queue/redis-queue-provider.test.d.ts.map +0 -1
  50. package/output/redis-queue/redis-queue-provider.test.js +0 -149
  51. package/output/redis-queue/test-helpers.d.ts +0 -112
  52. package/output/redis-queue/test-helpers.d.ts.map +0 -1
  53. package/output/redis-queue/test-helpers.js +0 -242
  54. package/output/redis-queue/test-helpers.test.d.ts +0 -28
  55. package/output/redis-queue/test-helpers.test.d.ts.map +0 -1
  56. package/output/redis-queue/test-helpers.test.js +0 -572
  57. package/output/redis-queue/types.d.ts +0 -146
  58. package/output/redis-queue/types.d.ts.map +0 -1
  59. package/output/redis-queue/types.js +0 -1
  60. package/output/schema/index.d.ts +0 -177
  61. package/output/schema/index.d.ts.map +0 -1
  62. package/output/schema/index.js +0 -180
@@ -1,242 +0,0 @@
1
- import { RedisQueueConsumer } from './redis-queue-consumer.js';
2
- /**
3
- * 测试辅助函数:立即派发任务到消费者
4
- *
5
- * 这个辅助函数提供了一个简洁的测试接口,让你能够立即派发任务到消费者,
6
- * 而不需要等待定时轮询机制。这使得测试更加快速和可控。
7
- *
8
- * @param consumer RedisQueueConsumer 或 RedisQueueBatchConsumer 实例
9
- * @param taskIds 要派发的任务 ID 列表
10
- * @returns Promise,等待所有任务处理完成
11
- *
12
- * @example
13
- * ```ts
14
- * import { dispatchQueueTask } from '@taicode/common-server/redis-queue/test-helpers'
15
- * import { RedisQueueProvider, RedisQueueConsumer } from '@taicode/common-server/redis-queue'
16
- *
17
- * describe('My Queue Tests', () => {
18
- * it('should process tasks', async () => {
19
- * const provider = new RedisQueueProvider({ ... })
20
- * const consumer = new RedisQueueConsumer({ ... })
21
- *
22
- * await provider.connect()
23
- * await consumer.connect()
24
- *
25
- * // 添加任务
26
- * const taskId = await provider.enqueue({ data: 'test' })
27
- *
28
- * // 立即派发任务进行测试
29
- * await dispatchQueueTask(consumer, [taskId as string])
30
- *
31
- * // 验证结果
32
- * const stats = await consumer.statistics()
33
- * expect(stats.completed).toBe(1)
34
- * })
35
- * })
36
- * ```
37
- */
38
- export async function dispatchQueueTask(consumer, taskIds) {
39
- if (taskIds.length === 0) {
40
- return;
41
- }
42
- // @ts-ignore - 访问 protected 属性用于测试
43
- const redis = consumer.redis;
44
- // @ts-ignore
45
- const queueKey = consumer.queueKey;
46
- // @ts-ignore
47
- const pendingQueue = consumer.pendingQueue;
48
- // @ts-ignore
49
- const processingQueue = consumer.processingQueue;
50
- if (!redis || !redis.isOpen) {
51
- throw new Error('Redis client is not connected');
52
- }
53
- // 使用 Lua 脚本将指定的任务从 pending 移到 processing 队列
54
- const moveTasksScript = `
55
- local pendingQueue = KEYS[1]
56
- local processingQueue = KEYS[2]
57
- local moved = 0
58
-
59
- for i = 3, #KEYS do
60
- local taskId = KEYS[i]
61
- -- 从 pending 队列移除
62
- local removed = redis.call('LREM', pendingQueue, 1, taskId)
63
- if (removed > 0) then
64
- -- 添加到 processing 队列
65
- redis.call('RPUSH', processingQueue, taskId)
66
- moved = moved + 1
67
- end
68
- end
69
-
70
- return moved
71
- `;
72
- // 持续处理直到所有任务完成或失败
73
- let remainingTasks = [...taskIds];
74
- let maxAttempts = 100; // 防止无限循环
75
- let attempts = 0;
76
- while (remainingTasks.length > 0 && attempts < maxAttempts) {
77
- attempts++;
78
- // 移动任务到 processing 队列
79
- await redis.eval(moveTasksScript, {
80
- keys: [pendingQueue, processingQueue, ...remainingTasks],
81
- arguments: [],
82
- });
83
- // 处理任务
84
- if (consumer instanceof RedisQueueConsumer) {
85
- // RedisQueueConsumer: 逐个处理任务
86
- const promises = remainingTasks.map(taskId =>
87
- // @ts-ignore
88
- consumer.processTask(taskId).catch(() => {
89
- // 忽略错误,让 consumer 内部处理
90
- }));
91
- await Promise.all(promises);
92
- }
93
- else {
94
- // RedisQueueBatchConsumer: 按照 consumer 的 batchSize 分批处理任务
95
- // @ts-ignore
96
- const batchConsumer = consumer;
97
- const batchSize = batchConsumer.config?.batchSize || 10;
98
- // 分批处理任务
99
- for (let i = 0; i < remainingTasks.length; i += batchSize) {
100
- const batch = remainingTasks.slice(i, i + batchSize);
101
- try {
102
- // @ts-ignore
103
- await batchConsumer.processBatch(batch);
104
- }
105
- catch (error) {
106
- // 批次处理失败是正常的,consumer 会处理重试逻辑
107
- }
108
- }
109
- }
110
- // 等待一小段时间让重试任务被放回 pending 队列
111
- await new Promise(resolve => setTimeout(resolve, 10));
112
- // 检查还有哪些任务在 pending 队列中(需要重试)
113
- const stillPending = [];
114
- for (const taskId of remainingTasks) {
115
- // @ts-ignore
116
- const task = await consumer.getTask(taskId);
117
- if (task && task.status === 'pending') {
118
- stillPending.push(taskId);
119
- }
120
- }
121
- remainingTasks = stillPending;
122
- }
123
- }
124
- /**
125
- * 测试辅助函数:等待队列达到指定状态
126
- *
127
- * @param instance Provider 或 Consumer 实例
128
- * @param predicate 状态断言函数
129
- * @param options 配置选项
130
- * @returns Promise,在条件满足时 resolve
131
- *
132
- * @example
133
- * ```ts
134
- * // 使用 consumer 等待所有任务完成
135
- * await waitQueueCompletion(consumer, stats => stats.pending === 0 && stats.processing === 0)
136
- *
137
- * // 使用 provider 等待至少完成 10 个任务
138
- * await waitQueueCompletion(provider, stats => stats.completed >= 10, { timeout: 5000 })
139
- * ```
140
- */
141
- export async function waitQueueCompletion(instance, predicate, options = {}) {
142
- const timeout = options.timeout ?? 10000; // 默认 10 秒超时
143
- const interval = options.interval ?? 100; // 默认 100ms 检查间隔
144
- const startTime = Date.now();
145
- while (Date.now() - startTime < timeout) {
146
- const stats = await instance.statistics();
147
- if (predicate(stats)) {
148
- return;
149
- }
150
- await new Promise(resolve => setTimeout(resolve, interval));
151
- }
152
- const finalStats = await instance.statistics();
153
- throw new Error(`Queue state timeout after ${timeout}ms. Final state: ${JSON.stringify(finalStats)}`);
154
- }
155
- /**
156
- * 测试辅助函数:清空队列所有状态
157
- *
158
- * 用于测试前后的清理工作,支持 Provider 或 Consumer 实例
159
- *
160
- * @param instance Provider 或 Consumer 实例
161
- * @returns Promise
162
- *
163
- * @example
164
- * ```ts
165
- * // 使用 consumer 清理
166
- * afterEach(async () => {
167
- * await clearQueue(consumer)
168
- * consumer.disconnect()
169
- * })
170
- *
171
- * // 使用 provider 清理
172
- * afterEach(async () => {
173
- * await clearQueue(provider)
174
- * provider.disconnect()
175
- * })
176
- * ```
177
- */
178
- export async function clearQueue(instance) {
179
- // 访问 protected 属性需要类型断言
180
- const redis = instance.redis;
181
- const queueKey = instance.queueKey;
182
- if (!redis || !redis.isOpen) {
183
- return;
184
- }
185
- // 删除所有队列相关的键
186
- const keys = await redis.keys(`${queueKey}:*`);
187
- if (keys.length > 0) {
188
- await redis.del(keys);
189
- }
190
- }
191
- /**
192
- * 测试辅助函数:获取队列中的所有任务详情
193
- *
194
- * 用于测试验证,可以检查任务的完整状态
195
- *
196
- * @param provider Provider 实例
197
- * @param status 可选,筛选特定状态的任务
198
- * @returns 任务列表
199
- *
200
- * @example
201
- * ```typescript
202
- * // 获取所有失败的任务
203
- * const failedTasks = await getQueueTasks(provider, 'failed')
204
- * expect(failedTasks).toHaveLength(3)
205
- *
206
- * // 验证任务数据
207
- * expect(failedTasks[0].data).toMatchObject({ id: 123 })
208
- * ```
209
- */
210
- export async function getQueueTasks(provider, status) {
211
- // @ts-ignore
212
- const redis = provider.redis;
213
- // @ts-ignore
214
- const queueKey = provider.queueKey;
215
- if (!redis || !redis.isOpen) {
216
- return [];
217
- }
218
- const queueName = status ? `${queueKey}:${status}` : null;
219
- const tasks = [];
220
- if (queueName) {
221
- // 获取特定状态队列中的所有任务 ID
222
- const taskIds = await redis.lRange(queueName, 0, -1);
223
- for (const taskId of taskIds) {
224
- const taskKey = `${queueKey}:task:${taskId}`;
225
- const taskData = await redis.get(taskKey);
226
- if (taskData) {
227
- tasks.push(JSON.parse(taskData));
228
- }
229
- }
230
- }
231
- else {
232
- // 获取所有任务
233
- const taskKeys = await redis.keys(`${queueKey}:task:*`);
234
- for (const taskKey of taskKeys) {
235
- const taskData = await redis.get(taskKey);
236
- if (taskData) {
237
- tasks.push(JSON.parse(taskData));
238
- }
239
- }
240
- }
241
- return tasks;
242
- }
@@ -1,28 +0,0 @@
1
- type TestTaskData = {
2
- id?: string;
3
- message?: string;
4
- value?: string | number;
5
- name?: string;
6
- test?: string | boolean;
7
- shouldFail?: boolean;
8
- order?: number;
9
- taskId?: number;
10
- index?: number;
11
- step?: number;
12
- real?: boolean;
13
- nested?: {
14
- value: number;
15
- };
16
- example?: string;
17
- payload?: string;
18
- data?: any;
19
- foo?: string;
20
- number?: number;
21
- };
22
- declare module './types.js' {
23
- interface RedisQueueRegistry {
24
- [key: `test:${string}`]: TestTaskData;
25
- }
26
- }
27
- export {};
28
- //# sourceMappingURL=test-helpers.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test-helpers.test.d.ts","sourceRoot":"","sources":["../../source/redis-queue/test-helpers.test.ts"],"names":[],"mappings":"AAcA,KAAK,YAAY,GAAG;IAClB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACvB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,GAAG,CAAA;IACV,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAGD,OAAO,QAAQ,YAAY,CAAC;IAC1B,UAAU,kBAAkB;QAC1B,CAAC,GAAG,EAAE,QAAQ,MAAM,EAAE,GAAG,YAAY,CAAA;KACtC;CACF"}