@taicode/common-server 1.0.11 → 1.0.13

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 (51) hide show
  1. package/output/index.d.ts +1 -0
  2. package/output/index.d.ts.map +1 -1
  3. package/output/index.js +1 -0
  4. package/output/redis-queue/index.d.ts +6 -4
  5. package/output/redis-queue/index.d.ts.map +1 -1
  6. package/output/redis-queue/index.js +4 -2
  7. package/output/redis-queue/redis-batch-consumer.d.ts +80 -0
  8. package/output/redis-queue/redis-batch-consumer.d.ts.map +1 -0
  9. package/output/redis-queue/redis-batch-consumer.js +308 -0
  10. package/output/redis-queue/redis-batch-consumer.test.d.ts +7 -0
  11. package/output/redis-queue/redis-batch-consumer.test.d.ts.map +1 -0
  12. package/output/redis-queue/redis-batch-consumer.test.js +265 -0
  13. package/output/redis-queue/redis-queue-common.d.ts +73 -0
  14. package/output/redis-queue/redis-queue-common.d.ts.map +1 -0
  15. package/output/redis-queue/redis-queue-common.js +302 -0
  16. package/output/redis-queue/redis-queue-common.test.d.ts +19 -0
  17. package/output/redis-queue/redis-queue-common.test.d.ts.map +1 -0
  18. package/output/redis-queue/redis-queue-common.test.js +623 -0
  19. package/output/redis-queue/redis-queue-consumer.d.ts +81 -0
  20. package/output/redis-queue/redis-queue-consumer.d.ts.map +1 -0
  21. package/output/redis-queue/redis-queue-consumer.js +297 -0
  22. package/output/redis-queue/redis-queue-consumer.test.d.ts +7 -0
  23. package/output/redis-queue/redis-queue-consumer.test.d.ts.map +1 -0
  24. package/output/redis-queue/redis-queue-consumer.test.js +242 -0
  25. package/output/redis-queue/redis-queue-provider.d.ts +56 -0
  26. package/output/redis-queue/redis-queue-provider.d.ts.map +1 -0
  27. package/output/redis-queue/redis-queue-provider.js +187 -0
  28. package/output/redis-queue/redis-queue-provider.test.d.ts +7 -0
  29. package/output/redis-queue/redis-queue-provider.test.d.ts.map +1 -0
  30. package/output/redis-queue/redis-queue-provider.test.js +114 -0
  31. package/output/redis-queue/types.d.ts +77 -19
  32. package/output/redis-queue/types.d.ts.map +1 -1
  33. package/package.json +1 -1
  34. package/output/logger/logger.d.ts +0 -33
  35. package/output/logger/logger.d.ts.map +0 -1
  36. package/output/logger/logger.js +0 -65
  37. package/output/logger/logger.test.d.ts +0 -2
  38. package/output/logger/logger.test.d.ts.map +0 -1
  39. package/output/logger/logger.test.js +0 -87
  40. package/output/redis-queue/batch-redis-queue.d.ts +0 -136
  41. package/output/redis-queue/batch-redis-queue.d.ts.map +0 -1
  42. package/output/redis-queue/batch-redis-queue.js +0 -573
  43. package/output/redis-queue/batch-redis-queue.test.d.ts +0 -2
  44. package/output/redis-queue/batch-redis-queue.test.d.ts.map +0 -1
  45. package/output/redis-queue/batch-redis-queue.test.js +0 -243
  46. package/output/redis-queue/redis-queue.d.ts +0 -129
  47. package/output/redis-queue/redis-queue.d.ts.map +0 -1
  48. package/output/redis-queue/redis-queue.js +0 -547
  49. package/output/redis-queue/redis-queue.test.d.ts +0 -2
  50. package/output/redis-queue/redis-queue.test.d.ts.map +0 -1
  51. package/output/redis-queue/redis-queue.test.js +0 -234
@@ -1,234 +0,0 @@
1
- import { describe, it, expect, afterEach } from 'vitest';
2
- import { catchIt } from '@taicode/common-base';
3
- import { RedisQueue } from './redis-queue';
4
- const REDIS_URL = process.env.REDIS_URL || 'redis://localhost:6379';
5
- describe('RedisQueue', () => {
6
- const queues = [];
7
- afterEach(async () => {
8
- for (const queue of queues) {
9
- try {
10
- await queue.clear();
11
- }
12
- catch (error) {
13
- // 忽略清理错误
14
- }
15
- queue.disconnect();
16
- }
17
- queues.length = 0;
18
- });
19
- const createQueue = (handler, options) => {
20
- const uniqueKey = `test:queue:${Date.now()}:${Math.random()}`;
21
- const queue = new RedisQueue({
22
- redisUrl: REDIS_URL,
23
- queueKey: uniqueKey,
24
- consumerInterval: 100,
25
- maxRetries: 2,
26
- ...options,
27
- handler,
28
- });
29
- queues.push(queue);
30
- return queue;
31
- };
32
- describe('连接管理', () => {
33
- it('应该成功连接到 Redis', async () => {
34
- const queue = createQueue(async () => catchIt(() => { }));
35
- await queue.connect();
36
- const health = await queue.health();
37
- expect(health).toBe(true);
38
- });
39
- it('连接后应该自动启动消费者', async () => {
40
- let processed = false;
41
- const queue = createQueue(async () => {
42
- processed = true;
43
- return catchIt(() => { });
44
- });
45
- await queue.connect();
46
- await queue.enqueue({ test: true });
47
- await new Promise(resolve => setTimeout(resolve, 300));
48
- expect(processed).toBe(true);
49
- });
50
- });
51
- describe('任务入队', () => {
52
- it('应该成功将任务推入队列', async () => {
53
- const queue = createQueue(async () => catchIt(() => { }));
54
- await queue.connect();
55
- const taskId = await queue.enqueue({ foo: 'bar' });
56
- expect(taskId).toBeTruthy();
57
- const stats = await queue.statistics();
58
- expect(stats.pending).toBeGreaterThan(0);
59
- });
60
- it('应该能够批量入队任务', async () => {
61
- const queue = createQueue(async () => catchIt(() => { }));
62
- await queue.connect();
63
- const taskIds = await queue.enqueue([
64
- { value: 1 },
65
- { value: 2 },
66
- { value: 3 },
67
- ]);
68
- expect(taskIds).toHaveLength(3);
69
- const stats = await queue.statistics();
70
- expect(stats.pending + stats.processing).toBe(3);
71
- });
72
- it('入队的任务应该包含正确的元数据', async () => {
73
- const queue = createQueue(async () => catchIt(() => { }));
74
- await queue.connect();
75
- const taskId = await queue.enqueue({ test: 'data', number: 42 });
76
- const task = await queue.getTask(taskId);
77
- expect(task).toBeTruthy();
78
- expect(task?.id).toBe(taskId);
79
- expect(task?.data).toEqual({ test: 'data', number: 42 });
80
- expect(task?.status).toBe('pending');
81
- expect(task?.retryCount).toBe(0);
82
- expect(task?.maxRetries).toBe(2);
83
- });
84
- });
85
- describe('任务处理', () => {
86
- it('应该成功处理任务', async () => {
87
- const processedData = [];
88
- const queue = createQueue(async (data) => {
89
- processedData.push(data);
90
- return catchIt(() => { });
91
- });
92
- await queue.connect();
93
- await queue.enqueue({ value: 'test' });
94
- await new Promise(resolve => setTimeout(resolve, 500));
95
- expect(processedData).toHaveLength(1);
96
- expect(processedData[0]).toEqual({ value: 'test' });
97
- });
98
- it('应该按 FIFO 顺序处理任务', async () => {
99
- const processOrder = [];
100
- const queue = createQueue(async (data) => {
101
- processOrder.push(data.order);
102
- await new Promise(resolve => setTimeout(resolve, 50));
103
- return catchIt(() => { });
104
- });
105
- await queue.connect();
106
- await queue.enqueue({ order: 1 });
107
- await new Promise(resolve => setTimeout(resolve, 10));
108
- await queue.enqueue({ order: 2 });
109
- await new Promise(resolve => setTimeout(resolve, 10));
110
- await queue.enqueue({ order: 3 });
111
- await new Promise(resolve => setTimeout(resolve, 1000));
112
- expect(processOrder).toEqual([1, 2, 3]);
113
- });
114
- });
115
- describe('错误处理和重试', () => {
116
- it('失败的任务应该自动重试', async () => {
117
- let attemptCount = 0;
118
- const queue = createQueue(async () => {
119
- attemptCount++;
120
- if (attemptCount < 2) {
121
- throw new Error('Simulated failure');
122
- }
123
- return catchIt(() => { });
124
- });
125
- await queue.connect();
126
- await queue.enqueue({ test: 'retry' });
127
- await new Promise(resolve => setTimeout(resolve, 1000));
128
- expect(attemptCount).toBe(2);
129
- });
130
- it('超过最大重试次数应该标记为失败', async () => {
131
- let attemptCount = 0;
132
- const queue = createQueue(async () => {
133
- attemptCount++;
134
- throw new Error('Always fails');
135
- });
136
- await queue.connect();
137
- const taskId = await queue.enqueue({ test: 'fail' });
138
- await new Promise(resolve => setTimeout(resolve, 1500));
139
- expect(attemptCount).toBe(3); // 初始 + 2 次重试
140
- const task = await queue.getTask(taskId);
141
- expect(task?.status).toBe('failed');
142
- });
143
- });
144
- describe('消费者管理', () => {
145
- it('断开连接后消费者应该停止', async () => {
146
- let processCount = 0;
147
- const queue = createQueue(async () => {
148
- processCount++;
149
- return catchIt(() => { });
150
- });
151
- await queue.connect();
152
- await queue.enqueue({ test: 1 });
153
- await new Promise(resolve => setTimeout(resolve, 300));
154
- expect(processCount).toBe(1);
155
- queue.disconnect();
156
- await queue.connect();
157
- await queue.enqueue({ test: 2 });
158
- await new Promise(resolve => setTimeout(resolve, 300));
159
- expect(processCount).toBe(2);
160
- });
161
- });
162
- describe('队列操作', () => {
163
- it('应该正确返回队列统计信息', async () => {
164
- const queue = createQueue(async () => {
165
- await new Promise(resolve => setTimeout(resolve, 100));
166
- return catchIt(() => { });
167
- });
168
- await queue.connect();
169
- await queue.enqueue([{ data: 1 }, { data: 2 }, { data: 3 }]);
170
- await new Promise(resolve => setTimeout(resolve, 50));
171
- const stats = await queue.statistics();
172
- expect(stats.pending + stats.processing).toBeGreaterThan(0);
173
- });
174
- it('应该能够清空队列', async () => {
175
- const queue = createQueue(async () => catchIt(() => { }));
176
- await queue.connect();
177
- await queue.enqueue([{ data: 1 }, { data: 2 }]);
178
- await queue.clear();
179
- const stats = await queue.statistics();
180
- expect(stats.pending).toBe(0);
181
- });
182
- });
183
- describe('并发处理', () => {
184
- it('应该支持并发处理多个任务', async () => {
185
- const processing = [];
186
- const completed = [];
187
- const queue = createQueue(async (data) => {
188
- processing.push(data.taskId);
189
- await new Promise(resolve => setTimeout(resolve, 200));
190
- completed.push(data.taskId);
191
- return catchIt(() => { });
192
- }, { concurrency: 3 });
193
- await queue.connect();
194
- await queue.enqueue([
195
- { taskId: 1 }, { taskId: 2 }, { taskId: 3 }, { taskId: 4 }, { taskId: 5 },
196
- ]);
197
- await new Promise(resolve => setTimeout(resolve, 250));
198
- expect(processing.length).toBeGreaterThanOrEqual(2);
199
- await new Promise(resolve => setTimeout(resolve, 1500));
200
- expect(completed.length).toBe(5);
201
- });
202
- });
203
- describe('幂等性', () => {
204
- it('应该支持在 data 中指定 id 来实现幂等性', async () => {
205
- let processCount = 0;
206
- const queue = createQueue(async () => {
207
- processCount++;
208
- return catchIt(() => { });
209
- });
210
- await queue.connect();
211
- await queue.enqueue({ id: 'unique-1', value: 1 });
212
- await queue.enqueue({ id: 'unique-1', value: 2 });
213
- await queue.enqueue({ id: 'unique-2', value: 3 });
214
- await new Promise(resolve => setTimeout(resolve, 1000));
215
- expect(processCount).toBe(2); // 只处理 unique-1 和 unique-2
216
- });
217
- });
218
- describe('延迟处理', () => {
219
- it('应该支持延迟处理任务', async () => {
220
- const startTime = Date.now();
221
- let processTime = 0;
222
- const queue = createQueue(async () => {
223
- processTime = Date.now() - startTime;
224
- return catchIt(() => { });
225
- }, { processingDelay: 2000 });
226
- await queue.connect();
227
- await queue.enqueue({ test: true });
228
- await new Promise(resolve => setTimeout(resolve, 1000));
229
- expect(processTime).toBe(0); // 还未处理
230
- await new Promise(resolve => setTimeout(resolve, 2000));
231
- expect(processTime).toBeGreaterThanOrEqual(1900);
232
- });
233
- });
234
- });