Skip to content

Commit

Permalink
add the ability to pass options to web worker constructor (#400)
Browse files Browse the repository at this point in the history
  • Loading branch information
DonatJR authored Sep 13, 2023
1 parent a35f8da commit 21da4d9
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 12 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,12 @@ The following options are available:
- `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`.
- `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.
- `workerThreadOpts: Object`. For `worker` worker type. An object passed to [worker_threads.options](https://nodejs.org/api/worker_threads.html#new-workerfilename-options). See nodejs documentation for available options.
- `onCreateWorker: Function`. A callback that is called whenever a worker is being created. It can be used to allocate resources for each worker for example. The callback is passed as argument an object with the following properties:
- `forkArgs: String[]`: the `forkArgs` option of this pool
- `forkOpts: Object`: the `forkOpts` option of this pool
- `workerOpts: Object`: the `workerOpts` option of this pool
- `script: string`: the `script` option of this pool
Optionally, this callback can return an object containing one or more of the above properties. The provided properties will be used to override the Pool properties for the worker being created.
- `onTerminateWorker: Function`. A callback that is called whenever a worker is being terminated. It can be used to release resources that might have been allocated for this specific worker. The callback is passed as argument an object as described for `onCreateWorker`, with each property sets with the value for the worker being terminated.
Expand Down
27 changes: 27 additions & 0 deletions examples/browser/workerWithOptions.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<title>Worker pool in the browser</title>

<script src="../../dist/workerpool.js"></script>
</head>
<body>

<script>
// create a worker pool
const options = {
workerOpts: {
name: 'NamedWorker'
}
}
var pool = workerpool.pool('../workers/browserWorker.js', options);

pool.exec('getName')
.then(result => {
document.write('Workers in pool have the name "' + result + '" given in workerOpts');
})

</script>

</body>
</html>
7 changes: 6 additions & 1 deletion examples/workers/browserWorker.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ function fibonacci(n) {
return fibonacci(n - 2) + fibonacci(n - 1);
}

function getName() {
return self.name || 'DefaultNameWorker';
}

// create a worker and register public functions
workerpool.worker({
fibonacci: fibonacci
fibonacci: fibonacci,
getName: getName
});
13 changes: 8 additions & 5 deletions src/Pool.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ function Pool(script, options) {

this.forkArgs = Object.freeze(options.forkArgs || []);
this.forkOpts = Object.freeze(options.forkOpts || {});
this.workerOpts = Object.freeze(options.workerOpts || {});
this.workerThreadOpts = Object.freeze(options.workerThreadOpts || {})
this.debugPortStart = (options.debugPortStart || 43210);
this.nodeWorker = options.nodeWorker;
Expand Down Expand Up @@ -389,17 +390,19 @@ Pool.prototype._ensureMinWorkers = function() {
* @private
*/
Pool.prototype._createWorkerHandler = function () {
const overridenParams = this.onCreateWorker({
const overriddenParams = this.onCreateWorker({
forkArgs: this.forkArgs,
forkOpts: this.forkOpts,
workerOpts: this.workerOpts,
workerThreadOpts: this.workerThreadOpts,
script: this.script
}) || {};

return new WorkerHandler(overridenParams.script || this.script, {
forkArgs: overridenParams.forkArgs || this.forkArgs,
forkOpts: overridenParams.forkOpts || this.forkOpts,
workerThreadOpts: overridenParams.workerThreadOpts || this.workerThreadOpts,
return new WorkerHandler(overriddenParams.script || this.script, {
forkArgs: overriddenParams.forkArgs || this.forkArgs,
forkOpts: overriddenParams.forkOpts || this.forkOpts,
workerOpts: overriddenParams.workerOpts || this.workerOpts,
workerThreadOpts: overriddenParams.workerThreadOpts || this.workerThreadOpts,
debugPort: DEBUG_PORT_ALLOCATOR.nextAvailableStartingAt(this.debugPortStart),
workerType: this.workerType,
workerTerminateTimeout: this.workerTerminateTimeout,
Expand Down
9 changes: 5 additions & 4 deletions src/WorkerHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ function getDefaultWorker() {
function setupWorker(script, options) {
if (options.workerType === 'web') { // browser only
ensureWebWorker();
return setupBrowserWorker(script, Worker);
return setupBrowserWorker(script, options.workerOpts, Worker);
} else if (options.workerType === 'thread') { // node.js only
WorkerThreads = ensureWorkerThreads();
return setupWorkerThreadWorker(script, WorkerThreads, options.workerThreadOpts);
Expand All @@ -73,7 +73,7 @@ function setupWorker(script, options) {
} else { // options.workerType === 'auto' or undefined
if (environment.platform === 'browser') {
ensureWebWorker();
return setupBrowserWorker(script, Worker);
return setupBrowserWorker(script, options.workerOpts, Worker);
}
else { // environment.platform === 'node'
var WorkerThreads = tryRequireWorkerThreads();
Expand All @@ -86,9 +86,9 @@ function setupWorker(script, options) {
}
}

function setupBrowserWorker(script, Worker) {
function setupBrowserWorker(script, workerOpts, Worker) {
// create the web worker
var worker = new Worker(script);
var worker = new Worker(script, workerOpts);

worker.isBrowserWorker = true;
// add node.js API to the web worker
Expand Down Expand Up @@ -209,6 +209,7 @@ function WorkerHandler(script, _options) {
this.debugPort = options.debugPort;
this.forkOpts = options.forkOpts;
this.forkArgs = options.forkArgs;
this.workerOpts = options.workerOpts;
this.workerThreadOpts = options.workerThreadOpts
this.workerTerminateTimeout = options.workerTerminateTimeout;

Expand Down
8 changes: 8 additions & 0 deletions src/types.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/**
* @typedef {Object} WorkerOptions
* @property {'classic' | 'module'} [type]
* @property {'omit' | 'same-origin' | 'include'} [credentials]
* @property {string} [name]
*/

/**
* @typedef {Object} WorkerPoolOptions
* @property {number | 'max'} [minWorkers]
Expand All @@ -7,6 +14,7 @@
* @property {number} [workerTerminateTimeout]
* @property {*} [forkArgs]
* @property {*} [forkOpts]
* @property {WorkerOptions} [workerOpts]
* @property {Function} [onCreateWorker]
* @property {Function} [onTerminateWorker]
*/
Expand Down
6 changes: 4 additions & 2 deletions test/WorkerHandler.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -372,11 +372,13 @@ describe('WorkerHandler', function () {
describe('setupBrowserWorker', function() {
it('correctly sets up the browser worker', function() {
var SCRIPT = 'the script';
var OPTIONS = { type: 'classic', credentials: 'omit', name: 'testWorker' }; // default WorkerOption values for type and credentials, custom name
var postMessage;
var addEventListener;

function Worker(script) {
function Worker(script, options) {
assert.strictEqual(script, SCRIPT);
assert.strictEqual(options, OPTIONS);
}

Worker.prototype.addEventListener = function(eventName, callback) {
Expand All @@ -387,7 +389,7 @@ describe('WorkerHandler', function () {
postMessage = message;
};

var worker = WorkerHandler._setupBrowserWorker(SCRIPT, Worker);
var worker = WorkerHandler._setupBrowserWorker(SCRIPT, OPTIONS, Worker);

assert.ok(worker instanceof Worker);
assert.ok(typeof worker.on === 'function');
Expand Down

0 comments on commit 21da4d9

Please sign in to comment.