@taicode/common-base 1.7.3 → 1.7.4

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.
@@ -75,6 +75,8 @@
75
75
  * - **流量控制**:可配置任务间延迟,避免资源竞争
76
76
  * - **状态追踪**:清晰的成功/失败状态管理
77
77
  * - **背压处理**:避免内存溢出的队列管理
78
+ * - **并发控制**:支持配置并发处理数量,默认为 1
79
+ * - **链式调用**:支持流畅的链式 API 调用
78
80
  */
79
81
  type FlowQueueInput = {};
80
82
  type FlowQueueOutput = {};
@@ -157,6 +159,7 @@ export type FlowQueueDelayConfig = {
157
159
  export type FlowQueueOptions = {
158
160
  retry?: FlowQueueRetryConfig;
159
161
  delay?: FlowQueueDelayConfig;
162
+ concurrency?: number;
160
163
  };
161
164
  /**
162
165
  * FlowQueue 流式队列处理器类
@@ -172,7 +175,8 @@ export type FlowQueueOptions = {
172
175
  * const queue = new FlowQueue<InputType, OutputType>(
173
176
  * {
174
177
  * retry: { strategy: 'exponential', baseDelay: 1000, maxRetries: 3 },
175
- * delay: { base: 100, jitter: true }
178
+ * delay: { base: 100, jitter: true },
179
+ * concurrency: 3 // 支持 3 个并发处理
176
180
  * },
177
181
  * async (input) => {
178
182
  * // 处理逻辑
@@ -180,13 +184,25 @@ export type FlowQueueOptions = {
180
184
  * }
181
185
  * );
182
186
  *
183
- * // 添加输入并监听输出
187
+ * // 传统方式
184
188
  * queue.input(data1, data2, data3);
185
189
  * queue.onGenerate(result => console.log('处理完成:', result));
186
- *
187
- * // 等待所有处理完成
188
190
  * queue.closeInput();
189
191
  * await queue.awaitCompletion();
192
+ *
193
+ * // 链式调用方式
194
+ * await queue
195
+ * .input(data1, data2)
196
+ * .input(data3)
197
+ * .closeInput()
198
+ * .awaitCompletion();
199
+ *
200
+ * // 重置并重新开始
201
+ * await queue
202
+ * .reset()
203
+ * .input(newData1, newData2)
204
+ * .closeInput()
205
+ * .awaitCompletion();
190
206
  * ```
191
207
  */
192
208
  export declare class FlowQueue<I extends FlowQueueInput, O extends FlowQueueOutput> {
@@ -196,7 +212,7 @@ export declare class FlowQueue<I extends FlowQueueInput, O extends FlowQueueOutp
196
212
  private processedInputs;
197
213
  successOutputs: Map<I, O>;
198
214
  erroredOutputs: Map<I, unknown>;
199
- private isProcessing;
215
+ private processingCount;
200
216
  private retryCount;
201
217
  private onGenerates;
202
218
  private isInputClosed;
@@ -212,14 +228,16 @@ export declare class FlowQueue<I extends FlowQueueInput, O extends FlowQueueOutp
212
228
  * - 可以在处理过程中通过 this.input() 动态添加新任务
213
229
  * - 支持异步处理,避免阻塞主线程
214
230
  * - 失败时会根据重试策略自动重试
231
+ * - 支持并发处理,默认并发数为 1
215
232
  *
216
233
  * @example
217
234
  * ```typescript
218
- * // 处理嵌套文件结构的示例
235
+ * // 处理嵌套文件结构的示例(单线程)
219
236
  * const fileQueue = new FlowQueue<FileNode, ProcessedFile>(
220
237
  * {
221
238
  * retry: { strategy: 'exponential', baseDelay: 1000, maxRetries: 3 },
222
- * delay: { base: 100, jitter: true }
239
+ * delay: { base: 100, jitter: true },
240
+ * concurrency: 1 // 默认值,可省略
223
241
  * },
224
242
  * async (node) => {
225
243
  * try {
@@ -236,6 +254,17 @@ export declare class FlowQueue<I extends FlowQueueInput, O extends FlowQueueOutp
236
254
  * }
237
255
  * }
238
256
  * );
257
+ *
258
+ * // 并发处理示例
259
+ * const concurrentQueue = new FlowQueue<Task, Result>(
260
+ * {
261
+ * concurrency: 5, // 同时处理 5 个任务
262
+ * retry: { strategy: 'exponential', baseDelay: 1000, maxRetries: 3 }
263
+ * },
264
+ * async (task) => {
265
+ * return await processTask(task);
266
+ * }
267
+ * );
239
268
  * ```
240
269
  */
241
270
  constructor(options: FlowQueueOptions, processor: FlowQueueProcessor<I, O>);
@@ -277,8 +306,10 @@ export declare class FlowQueue<I extends FlowQueueInput, O extends FlowQueueOutp
277
306
  * - 在 processor 函数内部可以动态添加新的输入
278
307
  * - 避免了深度递归调用栈
279
308
  * - 支持批量添加多个输入
309
+ * - 支持链式调用
280
310
  *
281
311
  * @param inputs 要处理的输入数据
312
+ * @returns 返回 FlowQueue 实例以支持链式调用
282
313
  *
283
314
  * @example
284
315
  * ```typescript
@@ -293,9 +324,15 @@ export declare class FlowQueue<I extends FlowQueueInput, O extends FlowQueueOutp
293
324
  *
294
325
  * return result;
295
326
  * };
327
+ *
328
+ * // 链式调用示例
329
+ * queue
330
+ * .input(data1, data2)
331
+ * .input(data3)
332
+ * .closeInput();
296
333
  * ```
297
334
  */
298
- input(...inputs: I[]): void;
335
+ input(...inputs: I[]): FlowQueue<I, O>;
299
336
  /**
300
337
  * 注册输出监听器
301
338
  *
@@ -331,9 +368,12 @@ export declare class FlowQueue<I extends FlowQueueInput, O extends FlowQueueOutp
331
368
  * - 队列将不再接受新的输入
332
369
  * - 当所有现有输入处理完成后,队列将进入完成状态
333
370
  * - 可以通过 awaitCompletion() 等待所有处理完成
371
+ * - 支持链式调用
334
372
  *
335
373
  * 在深度循环解耦场景中,这是控制处理边界的重要方法。
336
374
  *
375
+ * @returns 返回 FlowQueue 实例以支持链式调用
376
+ *
337
377
  * @example
338
378
  * ```typescript
339
379
  * // 添加所有初始数据
@@ -345,9 +385,15 @@ export declare class FlowQueue<I extends FlowQueueInput, O extends FlowQueueOutp
345
385
  * // 等待所有处理完成
346
386
  * await queue.awaitCompletion();
347
387
  * console.log('所有数据处理完成');
388
+ *
389
+ * // 链式调用示例
390
+ * await queue
391
+ * .input(data1, data2)
392
+ * .closeInput()
393
+ * .awaitCompletion();
348
394
  * ```
349
395
  */
350
- closeInput(): void;
396
+ closeInput(): FlowQueue<I, O>;
351
397
  /**
352
398
  * 返回一个 Promise,代表当前已经标记为输入关闭状态、所有输入都已经处理完毕
353
399
  *
@@ -375,14 +421,36 @@ export declare class FlowQueue<I extends FlowQueueInput, O extends FlowQueueOutp
375
421
  awaitCompletion(): Promise<void>;
376
422
  /**
377
423
  * 移除尚未处理的输入并调用 closeInput
424
+ *
425
+ * @returns 返回 FlowQueue 实例以支持链式调用
426
+ *
427
+ * @example
428
+ * ```typescript
429
+ * // 链式调用示例
430
+ * queue
431
+ * .input(data1, data2)
432
+ * .cancel()
433
+ * .reset();
434
+ * ```
378
435
  */
379
- cancel(): void;
436
+ cancel(): FlowQueue<I, O>;
380
437
  /**
381
438
  * 重置 FlowQueue 到初始状态
382
439
  * 清空所有数据,包括待处理、已处理、输出、重试计数等
383
440
  * 重置后可以重新开始处理
441
+ *
442
+ * @returns 返回 FlowQueue 实例以支持链式调用
443
+ *
444
+ * @example
445
+ * ```typescript
446
+ * // 链式调用示例
447
+ * queue
448
+ * .reset()
449
+ * .input(newData1, newData2)
450
+ * .closeInput();
451
+ * ```
384
452
  */
385
- reset(): void;
453
+ reset(): FlowQueue<I, O>;
386
454
  /**
387
455
  * 重试所有失败的输入
388
456
  *
@@ -1 +1 @@
1
- {"version":3,"file":"flow-queue.d.ts","sourceRoot":"","sources":["../../source/flow-queue/flow-queue.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"flow-queue.d.ts","sourceRoot":"","sources":["../../source/flow-queue/flow-queue.ts"],"names":[],"mappings":"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"}
@@ -75,6 +75,8 @@
75
75
  * - **流量控制**:可配置任务间延迟,避免资源竞争
76
76
  * - **状态追踪**:清晰的成功/失败状态管理
77
77
  * - **背压处理**:避免内存溢出的队列管理
78
+ * - **并发控制**:支持配置并发处理数量,默认为 1
79
+ * - **链式调用**:支持流畅的链式 API 调用
78
80
  */
79
81
  import { catchIt } from '../catch';
80
82
  function delay(arg0) {
@@ -94,7 +96,8 @@ function delay(arg0) {
94
96
  * const queue = new FlowQueue<InputType, OutputType>(
95
97
  * {
96
98
  * retry: { strategy: 'exponential', baseDelay: 1000, maxRetries: 3 },
97
- * delay: { base: 100, jitter: true }
99
+ * delay: { base: 100, jitter: true },
100
+ * concurrency: 3 // 支持 3 个并发处理
98
101
  * },
99
102
  * async (input) => {
100
103
  * // 处理逻辑
@@ -102,13 +105,25 @@ function delay(arg0) {
102
105
  * }
103
106
  * );
104
107
  *
105
- * // 添加输入并监听输出
108
+ * // 传统方式
106
109
  * queue.input(data1, data2, data3);
107
110
  * queue.onGenerate(result => console.log('处理完成:', result));
108
- *
109
- * // 等待所有处理完成
110
111
  * queue.closeInput();
111
112
  * await queue.awaitCompletion();
113
+ *
114
+ * // 链式调用方式
115
+ * await queue
116
+ * .input(data1, data2)
117
+ * .input(data3)
118
+ * .closeInput()
119
+ * .awaitCompletion();
120
+ *
121
+ * // 重置并重新开始
122
+ * await queue
123
+ * .reset()
124
+ * .input(newData1, newData2)
125
+ * .closeInput()
126
+ * .awaitCompletion();
112
127
  * ```
113
128
  */
114
129
  export class FlowQueue {
@@ -118,7 +133,7 @@ export class FlowQueue {
118
133
  processedInputs = []; // 已处理
119
134
  successOutputs = new Map();
120
135
  erroredOutputs = new Map();
121
- isProcessing = false; // 防止并发处理
136
+ processingCount = 0; // 当前正在处理的任务数量
122
137
  retryCount = new Map(); // 记录每个输入的重试次数
123
138
  onGenerates = new Map();
124
139
  isInputClosed = false; // 标记输入是否已关闭
@@ -134,14 +149,16 @@ export class FlowQueue {
134
149
  * - 可以在处理过程中通过 this.input() 动态添加新任务
135
150
  * - 支持异步处理,避免阻塞主线程
136
151
  * - 失败时会根据重试策略自动重试
152
+ * - 支持并发处理,默认并发数为 1
137
153
  *
138
154
  * @example
139
155
  * ```typescript
140
- * // 处理嵌套文件结构的示例
156
+ * // 处理嵌套文件结构的示例(单线程)
141
157
  * const fileQueue = new FlowQueue<FileNode, ProcessedFile>(
142
158
  * {
143
159
  * retry: { strategy: 'exponential', baseDelay: 1000, maxRetries: 3 },
144
- * delay: { base: 100, jitter: true }
160
+ * delay: { base: 100, jitter: true },
161
+ * concurrency: 1 // 默认值,可省略
145
162
  * },
146
163
  * async (node) => {
147
164
  * try {
@@ -158,6 +175,17 @@ export class FlowQueue {
158
175
  * }
159
176
  * }
160
177
  * );
178
+ *
179
+ * // 并发处理示例
180
+ * const concurrentQueue = new FlowQueue<Task, Result>(
181
+ * {
182
+ * concurrency: 5, // 同时处理 5 个任务
183
+ * retry: { strategy: 'exponential', baseDelay: 1000, maxRetries: 3 }
184
+ * },
185
+ * async (task) => {
186
+ * return await processTask(task);
187
+ * }
188
+ * );
161
189
  * ```
162
190
  */
163
191
  constructor(options, processor) {
@@ -172,6 +200,8 @@ export class FlowQueue {
172
200
  this.options.delay.base = this.options.delay.base ?? 0;
173
201
  this.options.delay.jitter = this.options.delay.jitter ?? false;
174
202
  this.options.delay.jitterRange = this.options.delay.jitterRange ?? 0.1;
203
+ // 设置并发配置默认值
204
+ this.options.concurrency = this.options.concurrency ?? 1;
175
205
  }
176
206
  /**
177
207
  * 计算重试延迟时间
@@ -242,7 +272,9 @@ export class FlowQueue {
242
272
  * 调度下一个处理任务
243
273
  */
244
274
  scheduleNextProcessing() {
245
- if (this.pendingInputs.length > 0) {
275
+ // 启动尽可能多的处理任务,直到达到并发限制
276
+ const tasksToStart = Math.min(this.pendingInputs.length, this.options.concurrency - this.processingCount);
277
+ for (let i = 0; i < tasksToStart; i++) {
246
278
  // 计算任务间延迟
247
279
  const taskDelay = this.calculateTaskDelay();
248
280
  if (taskDelay > 0) {
@@ -254,10 +286,8 @@ export class FlowQueue {
254
286
  setTimeout(() => this.processFlow(), 0);
255
287
  }
256
288
  }
257
- else {
258
- // 没有更多待处理的输入,检查是否已标记为完成
259
- this.checkAndTriggerCompletion();
260
- }
289
+ // 检查是否已标记为完成
290
+ this.checkAndTriggerCompletion();
261
291
  }
262
292
  /**
263
293
  * 延迟执行重试
@@ -265,12 +295,14 @@ export class FlowQueue {
265
295
  scheduleRetry(input, delayTime) {
266
296
  this.pendingInputs.unshift(input);
267
297
  if (delayTime <= 0) {
268
- // 立即重试
269
- setTimeout(() => this.processFlow(), 0);
298
+ // 立即重试,启动调度
299
+ this.scheduleNextProcessing();
270
300
  }
271
301
  else {
272
302
  // 延迟重试
273
- setTimeout(() => this.processFlow(), delayTime);
303
+ setTimeout(() => {
304
+ this.scheduleNextProcessing();
305
+ }, delayTime);
274
306
  }
275
307
  }
276
308
  /**
@@ -278,7 +310,7 @@ export class FlowQueue {
278
310
  */
279
311
  async checkAndTriggerCompletion() {
280
312
  await delay(0); // 确保在当前执行栈完成后再检查
281
- if (this.isInputClosed && this.pendingInputs.length === 0 && !this.isProcessing && this.completionResolve) {
313
+ if (this.isInputClosed && this.pendingInputs.length === 0 && this.processingCount === 0 && this.completionResolve) {
282
314
  this.completionResolve();
283
315
  this.completionResolve = null;
284
316
  }
@@ -290,19 +322,19 @@ export class FlowQueue {
290
322
  * 可以设置失败的重试次数,如果超过最大重试次数则不再重试
291
323
  */
292
324
  async processFlow() {
293
- // 如果正在处理或没有待处理的输入,直接返回
294
- if (this.isProcessing || this.pendingInputs.length === 0) {
295
- // 检查是否已标记为完成且没有待处理的输入
325
+ // 检查并发限制
326
+ if (this.processingCount >= this.options.concurrency) {
327
+ return;
328
+ }
329
+ // 取出第一个待处理的输入
330
+ const input = this.pendingInputs.shift();
331
+ if (!input) {
296
332
  this.checkAndTriggerCompletion();
297
333
  return;
298
334
  }
299
- this.isProcessing = true;
300
- const processResult = await catchIt(async () => {
301
- // 取出第一个待处理的输入
302
- const input = this.pendingInputs.shift();
303
- if (!input) {
304
- return;
305
- }
335
+ // 增加处理计数
336
+ this.processingCount++;
337
+ try {
306
338
  // 获取当前输入的重试次数
307
339
  const currentRetries = this.retryCount.get(input) || 0;
308
340
  // 使用 processor 处理输入
@@ -319,8 +351,6 @@ export class FlowQueue {
319
351
  this.erroredOutputs.set(input, result.error);
320
352
  this.processedInputs.push(input);
321
353
  this.retryCount.delete(input);
322
- // 处理完当前输入后,继续处理下一个(如果有的话)
323
- this.scheduleNextProcessing();
324
354
  }
325
355
  }
326
356
  else {
@@ -332,17 +362,17 @@ export class FlowQueue {
332
362
  this.erroredOutputs.delete(input);
333
363
  // 通知所有注册的回调
334
364
  await this.notifyOnGenerates(result.value);
335
- // 处理完当前输入后,继续处理下一个(如果有的话)
336
- this.scheduleNextProcessing();
337
365
  }
338
- });
339
- // 处理 processFlow 中的错误
340
- if (processResult.isError()) {
341
- console.error('Error in processFlow:', processResult.error);
342
366
  }
343
- // 确保在任何情况下都重置 isProcessing 状态
344
- this.isProcessing = false;
345
- this.checkAndTriggerCompletion();
367
+ catch (error) {
368
+ console.error('Error in processFlow:', error);
369
+ }
370
+ finally {
371
+ // 减少正在处理的任务计数
372
+ this.processingCount--;
373
+ // 处理完当前输入后,尝试启动更多处理任务
374
+ this.scheduleNextProcessing();
375
+ }
346
376
  }
347
377
  /**
348
378
  * 通知所有注册的回调函数
@@ -362,8 +392,10 @@ export class FlowQueue {
362
392
  * - 在 processor 函数内部可以动态添加新的输入
363
393
  * - 避免了深度递归调用栈
364
394
  * - 支持批量添加多个输入
395
+ * - 支持链式调用
365
396
  *
366
397
  * @param inputs 要处理的输入数据
398
+ * @returns 返回 FlowQueue 实例以支持链式调用
367
399
  *
368
400
  * @example
369
401
  * ```typescript
@@ -378,13 +410,20 @@ export class FlowQueue {
378
410
  *
379
411
  * return result;
380
412
  * };
413
+ *
414
+ * // 链式调用示例
415
+ * queue
416
+ * .input(data1, data2)
417
+ * .input(data3)
418
+ * .closeInput();
381
419
  * ```
382
420
  */
383
421
  input(...inputs) {
384
422
  if (this.isInputClosed)
385
- return;
423
+ return this;
386
424
  this.pendingInputs.push(...inputs);
387
425
  this.processFlow();
426
+ return this;
388
427
  }
389
428
  /**
390
429
  * 注册输出监听器
@@ -418,7 +457,7 @@ export class FlowQueue {
418
457
  * 只读标记,代表是否当前已经 closeInput 并且所有输入都已经处理完毕
419
458
  */
420
459
  get isCompleted() {
421
- return this.isInputClosed && this.pendingInputs.length === 0 && !this.isProcessing;
460
+ return this.isInputClosed && this.pendingInputs.length === 0 && this.processingCount === 0;
422
461
  }
423
462
  /**
424
463
  * 标记当前 FlowQueue 不会再有新的输入了
@@ -427,9 +466,12 @@ export class FlowQueue {
427
466
  * - 队列将不再接受新的输入
428
467
  * - 当所有现有输入处理完成后,队列将进入完成状态
429
468
  * - 可以通过 awaitCompletion() 等待所有处理完成
469
+ * - 支持链式调用
430
470
  *
431
471
  * 在深度循环解耦场景中,这是控制处理边界的重要方法。
432
472
  *
473
+ * @returns 返回 FlowQueue 实例以支持链式调用
474
+ *
433
475
  * @example
434
476
  * ```typescript
435
477
  * // 添加所有初始数据
@@ -441,12 +483,19 @@ export class FlowQueue {
441
483
  * // 等待所有处理完成
442
484
  * await queue.awaitCompletion();
443
485
  * console.log('所有数据处理完成');
486
+ *
487
+ * // 链式调用示例
488
+ * await queue
489
+ * .input(data1, data2)
490
+ * .closeInput()
491
+ * .awaitCompletion();
444
492
  * ```
445
493
  */
446
494
  closeInput() {
447
495
  this.isInputClosed = true;
448
496
  // 使用统一的完成检查方法
449
497
  this.checkAndTriggerCompletion();
498
+ return this;
450
499
  }
451
500
  /**
452
501
  * 返回一个 Promise,代表当前已经标记为输入关闭状态、所有输入都已经处理完毕
@@ -476,8 +525,8 @@ export class FlowQueue {
476
525
  if (this.completionPromise) {
477
526
  return this.completionPromise;
478
527
  }
479
- // 如果已经标记为输入关闭且没有待处理的输入,立即返回 resolved Promise
480
- if (this.isInputClosed && this.pendingInputs.length === 0 && !this.isProcessing) {
528
+ // 如果已经标记为输入关闭且没有待处理的输入和正在处理的任务,立即返回 resolved Promise
529
+ if (this.isInputClosed && this.pendingInputs.length === 0 && this.processingCount === 0) {
481
530
  console.log('所有输入已处理完毕');
482
531
  return Promise.resolve();
483
532
  }
@@ -492,6 +541,17 @@ export class FlowQueue {
492
541
  }
493
542
  /**
494
543
  * 移除尚未处理的输入并调用 closeInput
544
+ *
545
+ * @returns 返回 FlowQueue 实例以支持链式调用
546
+ *
547
+ * @example
548
+ * ```typescript
549
+ * // 链式调用示例
550
+ * queue
551
+ * .input(data1, data2)
552
+ * .cancel()
553
+ * .reset();
554
+ * ```
495
555
  */
496
556
  cancel() {
497
557
  // 清除所有待处理的输入
@@ -500,11 +560,23 @@ export class FlowQueue {
500
560
  this.retryCount.clear();
501
561
  // 标记输入已关闭
502
562
  this.closeInput();
563
+ return this;
503
564
  }
504
565
  /**
505
566
  * 重置 FlowQueue 到初始状态
506
567
  * 清空所有数据,包括待处理、已处理、输出、重试计数等
507
568
  * 重置后可以重新开始处理
569
+ *
570
+ * @returns 返回 FlowQueue 实例以支持链式调用
571
+ *
572
+ * @example
573
+ * ```typescript
574
+ * // 链式调用示例
575
+ * queue
576
+ * .reset()
577
+ * .input(newData1, newData2)
578
+ * .closeInput();
579
+ * ```
508
580
  */
509
581
  reset() {
510
582
  // 清空所有队列和状态
@@ -514,7 +586,7 @@ export class FlowQueue {
514
586
  this.pendingInputs.length = 0;
515
587
  this.processedInputs.length = 0;
516
588
  // 重置处理状态
517
- this.isProcessing = false;
589
+ this.processingCount = 0;
518
590
  this.isInputClosed = false;
519
591
  // 重置完成状态
520
592
  if (this.completionResolve) {
@@ -522,6 +594,7 @@ export class FlowQueue {
522
594
  this.completionResolve = null;
523
595
  }
524
596
  this.completionPromise = null;
597
+ return this;
525
598
  }
526
599
  /**
527
600
  * 重试所有失败的输入