@travetto/worker 5.0.0-rc.8 → 5.0.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
@@ -16,7 +16,7 @@ yarn add @travetto/worker
16
16
  This module provides the necessary primitives for handling dependent workers. A worker can be an individual actor or could be a pool of workers. Node provides ipc (inter-process communication) functionality out of the box. This module builds upon that by providing enhanced event management, richer process management, as well as constructs for orchestrating a conversation between two processes.
17
17
 
18
18
  ## Execution Pools
19
- With respect to managing multiple executions, [WorkPool](https://github.com/travetto/travetto/tree/main/module/worker/src/pool.ts#L34) is provided to allow for concurrent operation, and processing of jobs concurrently. To manage the flow of jobs, [WorkQueue](https://github.com/travetto/travetto/tree/main/module/worker/src/queue.ts#L6) is provided to support a wide range of use cases. [WorkQueue](https://github.com/travetto/travetto/tree/main/module/worker/src/queue.ts#L6) allows for manual control of iteration, which is useful for event driven work loads.
19
+ With respect to managing multiple executions, [WorkPool](https://github.com/travetto/travetto/tree/main/module/worker/src/pool.ts#L32) is provided to allow for concurrent operation, and processing of jobs concurrently. To manage the flow of jobs, [AsyncQueue](https://github.com/travetto/travetto/tree/main/module/runtime/src/queue.ts#L6) is used to support a wide range of use cases. [AsyncQueue](https://github.com/travetto/travetto/tree/main/module/runtime/src/queue.ts#L6) allows for manual control of iteration, which is useful for event driven work loads.
20
20
 
21
21
  ## IPC Support
22
22
  Within the `comm` package, there is support for two primary communication elements: [ChildCommChannel](https://github.com/travetto/travetto/tree/main/module/worker/src/comm/child.ts#L6) and [ParentCommChannel](https://github.com/travetto/travetto/tree/main/module/worker/src/comm/parent.ts#L10). Usually [ParentCommChannel](https://github.com/travetto/travetto/tree/main/module/worker/src/comm/parent.ts#L10) indicates it is the owner of the sub process. [ChildCommChannel](https://github.com/travetto/travetto/tree/main/module/worker/src/comm/child.ts#L6) indicates that it has been created/spawned/forked by the parent and will communicate back to it's parent. This generally means that a [ParentCommChannel](https://github.com/travetto/travetto/tree/main/module/worker/src/comm/parent.ts#L10) can be destroyed (i.e. killing the subprocess) where a [ChildCommChannel](https://github.com/travetto/travetto/tree/main/module/worker/src/comm/child.ts#L6) can only exit the process, but the channel cannot be destroyed.
package/__index__.ts CHANGED
@@ -5,5 +5,4 @@ export * from './src/comm/types';
5
5
  export * from './src/support/barrier';
6
6
  export * from './src/support/timeout';
7
7
  export * from './src/support/error';
8
- export * from './src/queue';
9
8
  export * from './src/pool';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@travetto/worker",
3
- "version": "5.0.0-rc.8",
3
+ "version": "5.0.0",
4
4
  "description": "Process management utilities, with a focus on inter-process communication",
5
5
  "keywords": [
6
6
  "exec",
@@ -25,7 +25,7 @@
25
25
  "directory": "module/worker"
26
26
  },
27
27
  "dependencies": {
28
- "@travetto/runtime": "^5.0.0-rc.8",
28
+ "@travetto/runtime": "^5.0.0",
29
29
  "generic-pool": "^3.9.0"
30
30
  },
31
31
  "travetto": {
@@ -89,9 +89,8 @@ export class ProcessCommChannel<T extends NodeJS.Process | ChildProcess, V = unk
89
89
  async destroy(): Promise<void> {
90
90
  if (this.#proc) {
91
91
  console.debug('Killing', { pid: this.#parentId, id: this.id });
92
- if (this.#proc !== process) {
93
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
94
- (this.#proc as ChildProcess).kill();
92
+ if (!('argv' in this.#proc)) {
93
+ this.#proc.kill();
95
94
  }
96
95
  this.#proc = undefined;
97
96
  }
package/src/pool.ts CHANGED
@@ -1,9 +1,7 @@
1
1
  import os from 'node:os';
2
2
  import { Options, Pool, createPool } from 'generic-pool';
3
3
 
4
- import { Env, Util } from '@travetto/runtime';
5
-
6
- import { WorkQueue } from './queue';
4
+ import { Env, Util, AsyncQueue } from '@travetto/runtime';
7
5
 
8
6
  type ItrSource<I> = Iterable<I> | AsyncIterable<I>;
9
7
 
@@ -67,10 +65,10 @@ export class WorkPool {
67
65
  },
68
66
  validate: async (x: Worker<I, O>) => x.active ?? true
69
67
  }, {
70
- max: WorkPool.DEFAULT_SIZE,
71
- min: 1,
72
68
  evictionRunIntervalMillis: 5000,
73
69
  ...(opts ?? {}),
70
+ max: opts?.max ?? WorkPool.DEFAULT_SIZE,
71
+ min: opts?.min ?? 1,
74
72
  });
75
73
 
76
74
 
@@ -143,7 +141,7 @@ export class WorkPool {
143
141
  * Process a given input source as an async iterable
144
142
  */
145
143
  static runStream<I, O>(worker: WorkerInput<I, O>, input: ItrSource<I>, opts?: WorkPoolConfig<I, O>): AsyncIterable<O> {
146
- const itr = new WorkQueue<O>();
144
+ const itr = new AsyncQueue<O>();
147
145
  const res = this.run(worker, input, {
148
146
  ...opts,
149
147
  onComplete: (ev, inp, finishIdx) => {
@@ -163,7 +161,7 @@ export class WorkPool {
163
161
  value: O;
164
162
  total: number;
165
163
  }> {
166
- const itr = new WorkQueue<{ idx: number, value: O, total: number }>();
164
+ const itr = new AsyncQueue<{ idx: number, value: O, total: number }>();
167
165
  const res = this.run(worker, input, {
168
166
  ...opts,
169
167
  onComplete: (ev, inp, finishIdx) => {
@@ -3,8 +3,7 @@ import { TimeSpan, Util } from '@travetto/runtime';
3
3
  import { Timeout } from './timeout';
4
4
 
5
5
  function canCancel(o: unknown): o is { cancel(): unknown } {
6
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
7
- return !!o && 'cancel' in (o as object);
6
+ return !!o && (typeof o === 'object') && 'cancel' in o && typeof o.cancel === 'function';
8
7
  }
9
8
 
10
9
  /**
@@ -14,17 +13,16 @@ export class Barrier {
14
13
  /**
15
14
  * Listen for an unhandled event, as a promise
16
15
  */
17
- static listenForUnhandled(): Promise<unknown> & { cancel: () => void } {
18
- const uncaught = Util.resolvablePromise<unknown>();
16
+ static listenForUnhandled(): Promise<unknown> & { cancel?: () => void } {
17
+ const uncaught = Util.resolvablePromise<Promise<unknown> & { cancel?: () => void }>();
19
18
  const onError = (err: Error): void => { Util.queueMacroTask().then(() => uncaught.reject(err)); };
20
19
  process.on('unhandledRejection', onError).on('uncaughtException', onError);
21
20
  const cancel = (): void => {
22
21
  process.off('unhandledRejection', onError).off('unhandledException', onError);
23
- uncaught.resolve(undefined); // Close the promise
22
+ uncaught.resolve(undefined!); // Close the promise
24
23
  };
25
24
  Object.defineProperty(uncaught.promise, 'cancel', { value: cancel });
26
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
27
- return uncaught.promise as unknown as ReturnType<(typeof Barrier)['listenForUnhandled']>;
25
+ return uncaught.promise;
28
26
  }
29
27
 
30
28
  #support: string[] = [];
package/src/queue.ts DELETED
@@ -1,85 +0,0 @@
1
- import { Util } from '@travetto/runtime';
2
-
3
- /**
4
- * WorkQueue, a manual async iterator. Items are added manually, and consumed asynchronously
5
- */
6
- export class WorkQueue<X> implements AsyncIterator<X>, AsyncIterable<X> {
7
-
8
- #queue: X[] = [];
9
- #done = false;
10
- #ready = Util.resolvablePromise();
11
- #size: number;
12
-
13
- /**
14
- * Initial set of items
15
- */
16
- constructor(initial: Iterable<X> = [], signal?: AbortSignal) {
17
- this.#queue.push(...initial);
18
- this.#size = this.#queue.length;
19
- signal?.addEventListener('abort', () => this.close());
20
- if (signal?.aborted) {
21
- this.close();
22
- }
23
- }
24
-
25
- // Allow for iteration
26
- [Symbol.asyncIterator](): AsyncIterator<X> {
27
- return this;
28
- }
29
-
30
- /**
31
- * Wait for next event to fire
32
- */
33
- async next(): Promise<IteratorResult<X>> {
34
- while (!this.#done && !this.#queue.length) {
35
- await this.#ready.promise;
36
- this.#ready = Util.resolvablePromise();
37
- }
38
- return { value: (this.#queue.length ? this.#queue.shift() : undefined)!, done: this.#done };
39
- }
40
-
41
- /**
42
- * Queue next event to fire
43
- * @param {boolean} immediate Determines if item(s) should be append or prepended to the queue
44
- */
45
- add(item: X, immediate = false): void {
46
- this.#queue[immediate ? 'unshift' : 'push'](item);
47
- this.#size += 1;
48
- this.#ready.resolve();
49
- }
50
-
51
- /**
52
- * Queue a list of data to stream
53
- * @param {boolean} immediate Determines if item(s) should be append or prepended to the queue
54
- */
55
- addAll(items: Iterable<X>): void {
56
- const copy = [...items];
57
- this.#queue.push(...copy);
58
- this.#size += copy.length;
59
- this.#ready.resolve();
60
- }
61
-
62
- /**
63
- * Close the iterator
64
- */
65
- close(): void {
66
- this.#done = true;
67
- this.#ready.resolve();
68
- }
69
-
70
- /**
71
- * Throw an error from the queue, rejecting and terminating immediately
72
- */
73
- async throw(e?: Error): Promise<IteratorResult<X>> {
74
- this.#done = true;
75
- this.#ready.reject(e);
76
- return { value: undefined, done: this.#done };
77
- }
78
-
79
- /**
80
- * Get size, will change as items are added
81
- */
82
- get size(): number {
83
- return this.#size;
84
- }
85
- }