Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nodejs and Express, use res.send() from a worker thread

In Nodejs, using Express as a server, I offload a heavy computation onto a worker thread.

From the main application, I call the worker thread like this:

// file: main.js

const { Worker } = require("worker_threads");

function runService(fileName, workerData) {
    return new Promise((resolve, reject) => {
        const worker = new Worker(fileName, { workerData });
        worker.on("message", resolve);
        worker.on("error", reject);
        worker.on("exit", code => {
            if (code !== 0)
                reject(new Error(`Worker stopped with exit code ${code}`));
        });
    });
}

router.get("/some_url", async function(req, res) {
    const result = await runService(
        "./path/to/worker.js",
        { query: req.query, user: req.user } // using { req } causes an error
    );
});

The worker looks like this:

// file: worker.js

const { workerData, parentPort } = require('worker_threads');
const { query, user } = workerData;

async function run() {
    const result = await generateLotsOfData(query, user);

    parentPort.postMessage(result);

    // What I would like to do here (doesn't work): res.send(result);
}

The worker generates a huge amount of data and "postMessage" causes a server error.

Is there a way to send this data from the worker thread directly to the client, using res.send() or something alike?
(instead of using postMessage and then sending from the main thread)?

like image 990
Hendrik Jan Avatar asked Aug 16 '26 07:08

Hendrik Jan


1 Answers

This sample of code works :

  1. create worker
  2. create event handler
  3. sendMessage --> wrapperWorkerThreadBigComputing
  4. sendBack message on our main thread
  5. emit server response

Api routes :

app.get('/bigComputingWithWorker', (req, res) => {
     const worker = new Worker(`${__dirname}/src/wrapperWorkerThreadBigComputing.js`);
    res.set('Content-Type', 'text/html');
      worker.once("message", count => {
        res.status(200).send(`The final count :${count}`);
    });
    worker.once("error", err => {
        console.error(err);
        res.status(400).send(`error worker thread`);
    });
     worker.postMessage({coucou : 'john'});
});

wrapperWorkerThreadBigComputing

const { parentPort } = require('node:worker_threads');

console.log("* worker created");
parentPort.once('message', (message) => {
      let big = bigComputing();
      parentPort.postMessage(big);
})

function bigComputing() {
    let i = 0;
    console.log("* start big computing")
    for (i = 0; i < 300000000; i++) {
    }
    return i;
}
like image 131
d0m00re Avatar answered Aug 17 '26 21:08

d0m00re



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!