piscina icon indicating copy to clipboard operation
piscina copied to clipboard

MessageChannel messages don't work in both directions

Open NickHeiner opened this issue 3 years ago • 3 comments

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

NickHeiner avatar Jul 19 '21 19:07 NickHeiner

Hmm... will have to investigate. @addaleax, any ideas?

jasnell avatar Jul 19 '21 20:07 jasnell

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');
};

tuanzisama avatar Oct 02 '21 15:10 tuanzisama

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.

addaleax avatar Oct 04 '21 08:10 addaleax