├── .gitignore ├── README.md ├── node-parent-thread-rxjs.js ├── node-worker-thread-rxjs.js ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repository contains a demonstration of the `worker_threads` module that is now standard in **Node 11.7.0**. To make things interesting, I am using **Rxjs** `Observable` stream messages from the worker thread. 2 | 3 | This demo requires **Node 11.7.0** or higher. 4 | 5 | To run the demo, run `npm install` then `npm start`. 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /node-parent-thread-rxjs.js: -------------------------------------------------------------------------------- 1 | const Rxjs = require('rxjs'); 2 | const RxjsOperators = require('rxjs/operators'); 3 | const { Worker } = require('worker_threads'); 4 | 5 | console.log("\nNode multi-threading demo using worker_threads module in Node 11.7.0\n"); 6 | 7 | const COMPLETE_SIGNAL = 'COMPLETE'; 8 | 9 | function runTask(workerData, completedOnTime) { 10 | return Rxjs.Observable.create(observer => { 11 | const worker = new Worker('./node-worker-thread-rxjs.js', { workerData }); 12 | worker.on('message', message => observer.next(message)); 13 | worker.on('error', error => observer.error(error)); 14 | worker.on('exit', code => { 15 | if (code !== 0) { 16 | observer.error(`Worker stopped with exit code ${code}`); 17 | } else { 18 | completedOnTime(); 19 | observer.next(COMPLETE_SIGNAL); 20 | observer.complete(); 21 | } 22 | }); 23 | }); 24 | } 25 | 26 | const MAX_WAIT_TIME = 3; 27 | const WORKER_TIME = 10; 28 | 29 | function main() { 30 | completedOnTime = false; 31 | 32 | console.log(`[Main] Starting worker from process ${process.pid}`); 33 | 34 | const worker$ = runTask(WORKER_TIME, () => completedOnTime = true); 35 | 36 | // receive messages from worker until it completes but only wait for MAX_WAIT_TIME 37 | worker$.pipe( 38 | RxjsOperators.takeWhile(message => message !== COMPLETE_SIGNAL), 39 | RxjsOperators.takeUntil(Rxjs.timer(MAX_WAIT_TIME * 1000)) 40 | ).subscribe( 41 | result => console.log(`[Main] worker says: ${result}`), 42 | error => console.error(`[Main] worker error: ${error}`), 43 | () => { 44 | if (!completedOnTime) { 45 | console.log(`[Main] worker could not complete its work in the allowed ${MAX_WAIT_TIME}s, exiting Node process`); 46 | process.exit(0); 47 | } else { 48 | console.log(`[Main] worker completed its work in the allowed ${WORKER_TIME}s`); 49 | } 50 | } 51 | ); 52 | } 53 | 54 | main(); -------------------------------------------------------------------------------- /node-worker-thread-rxjs.js: -------------------------------------------------------------------------------- 1 | const { workerData, parentPort } = require('worker_threads'); 2 | 3 | parentPort.postMessage(`starting heavy duty work from process ${process.pid} that will take ${workerData}s to complete`); 4 | 5 | timeLimit = workerData; 6 | timer = 0; 7 | 8 | // simulate a long-running process with updates posted back on a regular interval 9 | do { 10 | setTimeout( 11 | (count) => { 12 | parentPort.postMessage(`heavy duty work in progress...${count + 1}s`); 13 | if (count === timeLimit) { 14 | parentPort.postMessage('done heavy duty work'); 15 | } 16 | }, 17 | 1000 * timer, 18 | timer); 19 | } while (++timer !== timeLimit); 20 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-worker-threads-demo", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "rxjs": { 8 | "version": "6.3.3", 9 | "resolved": "https://repo.dcts.tdbank.com:9443/content/groups/npm-all/rxjs/-/rxjs-6.3.3.tgz", 10 | "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", 11 | "requires": { 12 | "tslib": "^1.9.0" 13 | } 14 | }, 15 | "tslib": { 16 | "version": "1.9.3", 17 | "resolved": "https://repo.dcts.tdbank.com:9443/content/groups/npm-all/tslib/-/tslib-1.9.3.tgz", 18 | "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-worker-threads-demo", 3 | "version": "1.0.0", 4 | "description": "A demonstration of Node worker_threads module now available in Node 11.7.0 with Rxjs Observables.", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node --experimental-modules --no-warnings node-parent-thread-rxjs.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "Brian De Sousa", 11 | "license": "ISC", 12 | "dependencies": { 13 | "rxjs": "^6.3.3" 14 | } 15 | } 16 | --------------------------------------------------------------------------------