Skip to content

sendToQueue seems to block the event loop #481

Description

@aviadhadidainx

Hi.
I am struggling to understand the problem and unfortunately i couldn't find what can cause it.

My producer:

console.log("Trying to connect")
amqp.connect('amqp://localhost', function(err, conn) {
  if (err) {
    console.log(err)
  } else {
    console.log("Managed connecting.. Trying to create a channel")
  }
  conn.createChannel(function(err, ch) {
    var q = 'hello';

    ch.assertQueue(q, {durable: false});
    channel = ch
    var msg = 'helloworld'
    for (let i = 0 ; i < 50000; i++) {
      msg.start = Date.now()
      channel.sendToQueue('hello', new Buffer(JSON.stringify(msg)), {noAck: true});
      console.log(" [x] Sent %s", msg);
    }
    console.log("Finish sending")
  });
});

My consumer:

amqp.connect('amqp://localhost', function(err, conn) {
  conn.createChannel(function(err, ch) {
    var q = 'hello';

    ch.assertQueue(q, {durable: false});
    console.log(" [*] Waiting for messages in %s. To exit press CTRL+C", q);
    ch.consume(q, function(msg) {
      const jsonMsg = JSON.parse(msg.content.toString())
      console.log(" [x] Received %s, Time: %s", jsonMsg, (Date.now() - jsonMsg.start));
    }, {noAck: true});
  });
});

The problem is that only when the loop of sending is finished i see the cosumer is getting the message. The consumer is running on different nodejs server and i expect this to be non-blocking.
Tried to find any similar issues but couldn't find real answer.

Please advise
Thanks

Activity

  1. squaremo commented on Nov 18, 2018

    @squaremo
    Collaborator

    i expect this to be non-blocking

    It is non-blocking -- the loop keeps going, rather than wait for the I/O to be done. If you are spinning in a loop, no I/O will be done until your code exits; it will just accumulate in a buffer.

    The standard way to make sure you yield to the event loop is to break when you get a return value of false from sendToQueue. You can register an event handler with the channel for 'drain' to be notified when it is OK to start sending again. This is deliberately similar to the interface for writeable streams.

  2. aviadhadidainx commented on Nov 18, 2018

    @aviadhadidainx
    Author

    OK. So my mistake is that i was expected that I/O will happen regardless to the loop.
    Isn't there a different pool for I/O calls? So even if i still blocking the event loop from working the I/O should happen anyway?

  3. LynxyssCZ commented on Dec 19, 2018

    @LynxyssCZ

    Node.js is unable to perform I/O tasks when your code is keeping the event loop by performing a large chunk of synchronous code. That is by design and there is pretty much nothing that a library developer can do about it apart from forcing asynchronous API.

  4. shirshak55 commented on Nov 11, 2019

    @shirshak55

    By the way now I think you can use workers thread . Node Js 12 should support that and its always bad to run computation on event loop.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions