piscina
piscina copied to clipboard
MessageChannel messages don't work in both directions
When I use worker_threads
directly, I'm able to set up a bidirectional communication between the parent and workers:
// parent.js
const { MessageChannel, Worker } = require('worker_threads');
const subChannel = new MessageChannel();
subChannel.port2.on('message', (val) => {
console.log('parent got message', val)
subChannel.port2.postMessage('response from parent to ' + val);
});
const worker = new Worker(require.resolve('./message-channel-demo-worker'));
worker.postMessage({ hereIsYourPort: subChannel.port1 }, [subChannel.port1]);
// message-channel-demo-worker.js
const {
MessagePort, parentPort
} = require('worker_threads');
parentPort.once('message', (value) => {
value.hereIsYourPort.postMessage('the worker is sending this');
value.hereIsYourPort.once('message', (val) => console.log('worker got message', val));
});
On Node 14, this produces:
parent got message the worker is sending this
worker got message response from parent to the worker is sending this
However, when I introduce Piscina, the worker thread never gets the message from parent:
// parent-piscina.js
const Piscina = require('piscina');
const { MessageChannel } = require('worker_threads');
const piscina = new Piscina({
filename: require.resolve('./piscina-message-demo-worker'),
});
const channel = new MessageChannel();
channel.port2.on('message', (message) => {
console.log('parent got:', message);
channel.port2.postMessage('response from parent');
});
piscina.runTask({ port: channel.port1 }, [channel.port1]);
// piscina-message-demo-worker.js
module.exports = ({ port }) => {
port.once('message', (val) => console.log('worker got', val));
port.postMessage('hello from the worker pool');
};
On Node 14, this hangs at:
parent got: hello from the worker pool
Am I doing this wrong?
Possibly related: https://github.com/piscinajs/piscina/issues/133
Hmm... will have to investigate. @addaleax, any ideas?
I got a same problem.
When i try to find answer, put a useless code console.log(123);
in worker.js. It's work!
I still don't know how this works.
Example:
// piscina-message-demo-worker.js
module.exports = ({ port }) => {
// put a useless console.
console.log(123);
port.once('message', (val) => console.log('worker got', val));
port.postMessage('hello from the worker pool');
};
You’ll want useAtomics: false
if you plan to communicate with the worker thread externally, instead of using piscina’s built-in communication mechanism.
It’s going to be a bit slower in that case, but that’s probably fine.