Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs: Add Worker API Documentation #474

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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