Skip to content

cluster: worker doesn't react on message #39854

Closed

Description

@relloccate

Hi there.

I have a problem:
The Worker doesn't react on "message" event from the Primary with: type: "module" enabled in package.json
But the Primary is react on "message" event from the worker

Without type: "module" both works.

win10 x64 (node v14.17.5 and v16.7.0)
Guys, any fixes? Thanks.

Example:

import cluster from 'cluster';

if (cluster.isMaster) {
    const worker = cluster.fork();

    worker.on('message', message => {
        // will log the message
        console.log(message);
    });

    worker.send('From Master');
} else {
    process.on('message', message => {
        // will not log the message
        console.log(message);
    });

    process.send('From Worker');
}

Doesn't work ONLY with enabled node.js imports.

Activity

  1. PurnashisHazra commented on Aug 23, 2021

    @PurnashisHazra

    Could you create a repo which replicates this problem? Can I take this issue up?

  2. relloccate commented on Aug 23, 2021

    @relloccate
    Author

    Could you create a repo which replicates this problem? Can I take this issue up?

    The example above, just a minimal and illustrative example. Pretty simple to test on your PC. Sorry, I did not understand why you need a repo.

  3. PurnashisHazra commented on Aug 23, 2021

    @PurnashisHazra

    Just with some tests and all for easy debugging . Nevermind, I'll take up this issue

  4. added
    clusterIssues and PRs related to the cluster subsystem.
    esmIssues and PRs related to the ECMAScript Modules implementation.
    on Aug 24, 2021
  5. Linkgoron commented on Aug 27, 2021

    @Linkgoron
    Contributor

    This is probably a duplicate of #37782 and #39140

    e.g. this works:

    import cluster from 'cluster';
    
    if (cluster.isMaster) {
        const worker = cluster.fork();
        worker.on('message', message => {
            console.log(message);
        });
        setTimeout(() => {
            worker.send('From Master');
        }, 1000);
    } else {
        process.on('message', message => {
            console.log(message);
        });
    
        process.send('From Worker');
    }

    tl;dr of the other issues, there's a minor race condition (read: bug) because modules are now loaded asynchronously and when starting a module messages are missed as you don't register in time to get them. The safest way to start without a race condition is to get a ping from the child and then you know you're safe. e.g. POC:

    import cluster from 'cluster';
    import { once } from 'events';
    
    if (cluster.isMaster) {
        const worker = cluster.fork();
    
        let firstMessage = true
        worker.on('message', message => {
            if (firstMessage) {
                firstMessage = false;
            } else {
                console.log(message);
            }
        });
        await once(worker, 'message');
        worker.send('From Master');
    } else {
        process.on('message', message => {
            console.log(message);
        });
    
        process.send('IM READY');
        process.send('From Worker');
    }
  6. relloccate commented on Aug 27, 2021

    @relloccate
    Author

    Yes, i saw #37782 after.
    "modules are now loaded asynchronously" - With babel or no ESM it works correctly without any timeouts.
    Anyway thank you, i did it and it worked.

    My Solution:

    import cluster from 'cluster';
    
    if (cluster.isMaster) {
        const worker = cluster.fork();
    
        worker.on('message', message => {
            if (message === 'getPayload') {
                worker.send({ payload: 'something' });
            }
        });
    } else {
        process.on('message', ({ payload }) => {
            console.log(payload);
        });
    
        process.send('getPayload');
    }
  7. relloccate commented on Aug 27, 2021

    @relloccate
    Author

    Dupe of #37782

  8. Linkgoron commented on Aug 27, 2021

    @Linkgoron
    Contributor

    Yes, i saw #37782 after.
    "modules are now loaded asynchronously" - With babel or no ESM it works correctly without any timeouts.

    Just to clarify - when I said modules what I meant was that ESM modules (as in type: module or .mjs) are loaded asynchronously (e.g. for top-level await etc), while using CommonJS is still synchronous - not that all code is now loaded asynchronously.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    clusterIssues and PRs related to the cluster subsystem.esmIssues and PRs related to the ECMAScript Modules implementation.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions