Skip to content

Commit

Permalink
docs: add Worker API Documentation (#474)
Browse files Browse the repository at this point in the history
* docs: update abort listener info

* docs: add worker api section, move abort listener docs, add comment header to worker api

* doc: add abortListenerTimeout docs

* ref: fix last commit

* doc: cleanup

* doc: change comment on abort listener example in README
  • Loading branch information
joshLong145 authored Oct 17, 2024
1 parent e9b7767 commit 6bf949e
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 34 deletions.
94 changes: 63 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ The following options are available:
- In case of `'process'`, `child_process` will be used. Only available in a node.js environment.
- In case of `'thread'`, `worker_threads` will be used. If `worker_threads` are not available, an error is thrown. Only available in a node.js environment.
- `workerTerminateTimeout: number`. The timeout in milliseconds to wait for a worker to cleanup it's resources on termination before stopping it forcefully. Default value is `1000`.
- `abortListenerTimeout: number`. The timeout in milliseconds to wait for abort listener's before stopping it forcefully, triggering cleanup. Default value is `1000`.
- `forkArgs: String[]`. For `process` worker type. An array passed as `args` to [child_process.fork](https://nodejs.org/api/child_process.html#child_processforkmodulepath-args-options)
- `forkOpts: Object`. For `process` worker type. An object passed as `options` to [child_process.fork](https://nodejs.org/api/child_process.html#child_processforkmodulepath-args-options). See nodejs documentation for available options.
- `workerOpts: Object`. For `web` worker type. An object passed to the [constructor of the web worker](https://html.spec.whatwg.org/multipage/workers.html#dom-worker). See [WorkerOptions specification](https://html.spec.whatwg.org/multipage/workers.html#workeroptions) for available options.
Expand Down Expand Up @@ -393,7 +394,62 @@ workerpool.worker({
});
```

Tasks may configure an `abort handler` to perform cleanup operations when `timeout` or `cancel` is called on a `task`. the `abortListenerTimeout` option can be configured to control when cleanup should be aborted in the case an `abortHandler` never resolves. This timeout trigger will cause the given worker to be cleaned up. Allowing a new worker to be created if need be.
### Events

You can send data back from workers to the pool while the task is being executed using the `workerEmit` function:

`workerEmit(payload: any) : unknown`

This function only works inside a worker **and** during a task.

Example:

```js
// file myWorker.js
const workerpool = require('workerpool');

function eventExample(delay) {
workerpool.workerEmit({
status: 'in_progress',
});

workerpool.workerEmit({
status: 'complete',
});

return true;
}

// create a worker and register functions
workerpool.worker({
eventExample: eventExample,
});
```

To receive those events, you can use the `on` option of the pool `exec` method:

```js
pool.exec('eventExample', [], {
on: function (payload) {
if (payload.status === 'in_progress') {
console.log('In progress...');
} else if (payload.status === 'complete') {
console.log('Done!');
}
},
});
```

### Worker API
Workers have access to a `worker` api which contains the following methods

- `emit: (payload: unknown | Transfer): void`
- `addAbortListener: (listener: () => Promise<void>): void`


Worker termination may be recoverable through `abort listeners` which are registered through `worker.addAbortListener`. If all registered listeners resolve then the worker will not be terminated, allowing for worker reuse in some cases.

NOTE: For operations to successfully clean up, a worker implementation should be *async*. If the worker thread is blocked, then the worker will be killed.

```js
function asyncTimeout() {
Expand All @@ -402,11 +458,9 @@ function asyncTimeout() {
let timeout = setTimeout(() => {
resolve();
}, 5000);

// An abort listener allows for cleanup for a given worker
// such that it may be resused for future tasks
// if an execption is thrown within scope of the handler
// the worker instance will be destroyed.

// Register a listener which will resolve before the time out
// above triggers.
me.worker.addAbortListener(async function () {
clearTimeout(timeout);
resolve();
Expand All @@ -425,25 +479,17 @@ workerpool.worker(
);
```

### Events

You can send data back from workers to the pool while the task is being executed using the `workerEmit` function:

`workerEmit(payload: any) : unknown`

This function only works inside a worker **and** during a task.

Example:
Events may also be emitted from the `worker` api through `worker.emit`

```js
// file myWorker.js
const workerpool = require('workerpool');

function eventExample(delay) {
workerpool.workerEmit({
status: 'in_progress',
this.worker.emit({
status: "in_progress",
});

workerpool.workerEmit({
status: 'complete',
});
Expand All @@ -457,20 +503,6 @@ workerpool.worker({
});
```

To receive those events, you can use the `on` option of the pool `exec` method:

```js
pool.exec('eventExample', [], {
on: function (payload) {
if (payload.status === 'in_progress') {
console.log('In progress...');
} else if (payload.status === 'complete') {
console.log('Done!');
}
},
});
```

### Utilities

Following properties are available for convenience:
Expand Down
11 changes: 8 additions & 3 deletions src/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,18 @@ var worker = {
// works in both node.js and the browser
var publicWorker = {
/**
*
* @param {() => Promise<void>} listener
*/
* Registers listeners which will trigger when a task is timed out or cancled. If all listeners resolve, the worker executing the given task will not be terminated.
* *Note*: If there is a blocking operation within a listener, the worker will be terminated.
* @param {() => Promise<void>} listener
*/
addAbortListener: function(listener) {
worker.abortListeners.push(listener);
},

/**
* Emit an event from the worker thread to the main thread.
* @param {any} payload
*/
emit: worker.emit
};

Expand Down

0 comments on commit 6bf949e

Please sign in to comment.