@d-zero/dealer 1.5.4 → 1.6.0

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.
package/README.md CHANGED
@@ -15,13 +15,9 @@ npm install @d-zero/dealer
15
15
  ```ts
16
16
  import { deal } from '@d-zero/dealer';
17
17
 
18
- await deal(items, {
19
- limit: 30,
20
- header: (progress, done, total, limit) =>
21
- progress === 1
22
- ? 'HeaderMessage: Done!'
23
- : `HeaderMessage: %earth% %dots% %block% %propeller%`,
24
- setup: (item, update, index) => {
18
+ await deal(
19
+ items,
20
+ (item, update, index, setLineHeader, push) => {
25
21
  item.setup();
26
22
  item.addListeners((state) => {
27
23
  update(`item(${index}): ${state}`);
@@ -32,7 +28,14 @@ await deal(items, {
32
28
  item.cleanup();
33
29
  };
34
30
  },
35
- });
31
+ {
32
+ limit: 30,
33
+ header: (progress, done, total, limit) =>
34
+ progress === 1
35
+ ? 'HeaderMessage: Done!'
36
+ : `HeaderMessage: %earth% %dots% %block% %propeller%`,
37
+ },
38
+ );
36
39
  ```
37
40
 
38
41
  ### deal関数
@@ -49,6 +52,7 @@ async function deal<T extends WeakKey>(
49
52
  update: (log: string) => void,
50
53
  index: number,
51
54
  setLineHeader: (lineHeader: string) => void,
55
+ push: (...items: T[]) => Promise<void>,
52
56
  ) => Promise<() => void | Promise<void>> | (() => void | Promise<void>),
53
57
  options?: DealOptions,
54
58
  ): Promise<void>;
@@ -62,6 +66,7 @@ async function deal<T extends WeakKey>(
62
66
  - `update`: ログを更新する関数
63
67
  - `index`: アイテムのインデックス
64
68
  - `setLineHeader`: ログの各行にプレフィックスを設定する関数
69
+ - `push`: 実行中にアイテムをキューに追加する関数
65
70
  - 戻り値: アイテムを開始する関数
66
71
  - `options`: 設定オプション
67
72
 
@@ -89,6 +94,7 @@ type DealOptions = DealerOptions &
89
94
  #### プロパティ
90
95
 
91
96
  - `limit?: number`: 同時実行数の制限(デフォルト: 10)
97
+ - `onPush?: (item: T) => boolean`: `push()`時のフィルタ関数。`false`を返すとそのアイテムは拒否される(例: 重複排除)
92
98
  - `header?: DealHeader`: 進捗ヘッダーを生成する関数
93
99
  - `debug?: boolean`: デバッグログを表示するかどうか
94
100
  - `interval?: number | DelayOptions`: 各処理の間隔(ミリ秒またはDelayOptions)
@@ -134,6 +140,7 @@ constructor(items: readonly T[], options?: DealerOptions)
134
140
 
135
141
  - `items`: 処理対象のアイテム
136
142
  - `options.limit`: 同時実行数の制限(デフォルト: 10)
143
+ - `options.onPush`: `push()`時のフィルタ関数
137
144
 
138
145
  #### メソッド
139
146
 
@@ -175,6 +182,16 @@ dealer.progress((progress, done, total, limit) => {
175
182
  });
176
183
  ```
177
184
 
185
+ ##### async push(...items: T[])
186
+
187
+ 実行中にアイテムをキューに追加します。追加されたアイテムには`setup()`で設定した初期化関数が自動適用されます。完了後の呼び出しは無視されます。
188
+
189
+ ```ts
190
+ await dealer.push(newItem1, newItem2);
191
+ ```
192
+
193
+ - `items`: 追加するアイテム。`onPush`が設定されている場合、`false`を返したアイテムはスキップされます。
194
+
178
195
  ##### async setup(initializer: ProcessInitializer<T>)
179
196
 
180
197
  各アイテムの初期化関数を設定します。
package/dist/deal.d.ts CHANGED
@@ -41,4 +41,4 @@ export type DealHeader = (progress: number, done: number, total: number, limit:
41
41
  * @param options - Configuration options including interval delay
42
42
  * @returns Promise that resolves when all items are processed
43
43
  */
44
- export declare function deal<T extends WeakKey>(items: readonly T[], setup: (process: T, update: (log: string) => void, index: number, setLineHeader: (lineHeader: string) => void) => Promise<() => void | Promise<void>> | (() => void | Promise<void>), options?: DealOptions): Promise<void>;
44
+ export declare function deal<T extends WeakKey>(items: readonly T[], setup: (process: T, update: (log: string) => void, index: number, setLineHeader: (lineHeader: string) => void, push: (...items: T[]) => Promise<void>) => Promise<() => void | Promise<void>> | (() => void | Promise<void>), options?: DealOptions): Promise<void>;
package/dist/deal.js CHANGED
@@ -50,7 +50,8 @@ export async function deal(items, setup, options) {
50
50
  lineHeader = header;
51
51
  };
52
52
  const update = (log) => lanes.update(index, lineHeader + log);
53
- const start = await setup(process, update, index, setLineHeader);
53
+ const push = (...newItems) => dealer.push(...newItems);
54
+ const start = await setup(process, update, index, setLineHeader, push);
54
55
  return async () => {
55
56
  await delay(options?.interval ?? 0, (determinedInterval) => {
56
57
  update(`Waiting interval: %countdown(${determinedInterval},${index}_interval)%ms`);
package/dist/dealer.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { ProcessInitializer } from './types.js';
2
2
  export interface DealerOptions {
3
3
  limit?: number;
4
+ onPush?: (item: never) => boolean;
4
5
  }
5
6
  export declare class Dealer<T extends WeakKey> {
6
7
  #private;
@@ -9,5 +10,6 @@ export declare class Dealer<T extends WeakKey> {
9
10
  finish(listener: () => void): void;
10
11
  play(): void;
11
12
  progress(listener: (progress: number, done: number, total: number, limit: number) => void): void;
13
+ push(...items: T[]): Promise<void>;
12
14
  setup(initializer: ProcessInitializer<T>): Promise<void>;
13
15
  }
package/dist/dealer.js CHANGED
@@ -3,14 +3,20 @@ export class Dealer {
3
3
  #done = new WeakSet();
4
4
  #doneCount = 0;
5
5
  #finish = () => { };
6
+ #finished = false;
7
+ #initializer = null;
6
8
  #items;
7
9
  #limit;
10
+ #nextIndex = 0;
11
+ #onPush;
12
+ #pendingInitCount = 0;
8
13
  #progress = () => { };
9
14
  #starts = new WeakMap();
10
15
  #workers = new Set();
11
16
  constructor(items, options) {
12
- this.#items = items;
17
+ this.#items = [...items];
13
18
  this.#limit = options?.limit ?? 10;
19
+ this.#onPush = options?.onPush;
14
20
  }
15
21
  debug(listener) {
16
22
  this.#debug = listener;
@@ -24,18 +30,35 @@ export class Dealer {
24
30
  progress(listener) {
25
31
  this.#progress = listener;
26
32
  }
33
+ async push(...items) {
34
+ if (this.#finished) {
35
+ return;
36
+ }
37
+ for (const item of items) {
38
+ if (this.#onPush && !this.#onPush(item)) {
39
+ continue;
40
+ }
41
+ this.#pendingInitCount++;
42
+ await this.#initializeAndDispatch(item);
43
+ }
44
+ }
27
45
  async setup(initializer) {
28
- for (const [index, item] of this.#items.entries()) {
29
- const start = await initializer(item, index);
46
+ this.#initializer = initializer;
47
+ for (const item of this.#items) {
48
+ const start = await initializer(item, this.#nextIndex++);
30
49
  this.#starts.set(item, async () => await start());
31
50
  }
32
- this.#progress(this.#doneCount / this.#items.length, this.#doneCount, this.#items.length, this.#limit);
51
+ const total = this.#items.length;
52
+ this.#progress(total === 0 ? 0 : this.#doneCount / total, this.#doneCount, total, this.#limit);
33
53
  }
34
54
  #deal() {
35
- this.#debug(`Done: ${this.#doneCount}/${this.#items.length} (Limit: ${this.#limit})`);
36
- this.#progress(this.#doneCount / this.#items.length, this.#doneCount, this.#items.length, this.#limit);
37
- if (this.#doneCount === this.#items.length) {
55
+ const total = this.#items.length;
56
+ this.#debug(`Done: ${this.#doneCount}/${total} (Limit: ${this.#limit})`);
57
+ this.#progress(total === 0 ? 0 : this.#doneCount / total, this.#doneCount, total, this.#limit);
58
+ if (total > 0 && this.#doneCount === total && this.#pendingInitCount === 0) {
59
+ this.#finished = true;
38
60
  this.#finish();
61
+ return;
39
62
  }
40
63
  while (this.#workers.size < this.#limit) {
41
64
  const worker = this.#draw();
@@ -67,4 +90,14 @@ export class Dealer {
67
90
  }
68
91
  return null;
69
92
  }
93
+ async #initializeAndDispatch(item) {
94
+ if (!this.#initializer) {
95
+ throw new Error('setup() must be called before push()');
96
+ }
97
+ const start = await this.#initializer(item, this.#nextIndex++);
98
+ this.#starts.set(item, async () => await start());
99
+ this.#items.push(item);
100
+ this.#pendingInitCount--;
101
+ this.#deal();
102
+ }
70
103
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@d-zero/dealer",
3
- "version": "1.5.4",
3
+ "version": "1.6.0",
4
4
  "description": "A tool that provides an API and CLI for parallel processing of collections and sequential logging to standard output",
5
5
  "author": "D-ZERO",
6
6
  "license": "MIT",
@@ -26,5 +26,5 @@
26
26
  "@d-zero/shared": "0.18.0",
27
27
  "ansi-colors": "4.1.3"
28
28
  },
29
- "gitHead": "008ea25926579b061e36c1f5f4f4fc7e15cb782e"
29
+ "gitHead": "a6d7b36c485bbc0782375c6e1ad0d0606f423e97"
30
30
  }