node-amqp icon indicating copy to clipboard operation
node-amqp copied to clipboard

multiple ready event?

Open kuno opened this issue 11 years ago • 12 comments

I notice that the connection object seems will emit ready event more than once.

For example

function run (config, callback) {
  var connection = amqp.createConnection(config);

  connnection.on('ready' , function() {
    ...
    callback.call(this);
  });
}

run({...}, function() { console.log('ready') };

I have some code which is similar to above, it seems the callback that passed to the function run, was called more than once.

Am i wrong about that?

kuno avatar Nov 01 '13 09:11 kuno

I noticed the same behavior, and as I was debugging the issue, I discovered that I was actually opening the connection three times because it would error twice and then work the third time.

This is related to the timing of interacting with exchanges and queues. You've probably attempted to bind a queue to an exchange before the queue creation has resolved (this was my problem).

Try moving any queue binding into the exchange ready callback.

mko avatar Nov 01 '13 21:11 mko

Sorry, you means, the exchange object also has a ready event, and it's much more reliable?

kuno avatar Nov 03 '13 11:11 kuno

In OSX 10.9 with RabbitMQ 3.2.1, amqp 0.1.7 and the following code:

var amqpConnectionOptions = { 
  host: 'localhost'
  , login: 'guest'
  , password: '***'
  , authMechanism: 'AMQPLAIN'
  , vhost: '/'
  , ssl: { enabled : false }
}

var connection = amqp.createConnection(amqpConnectionOptions);

// Wait for connection to become established.
connection.addListener('ready', function () {

  console.log("ready");

  // Use the default 'amq.topic' exchange
  connection.queue('web-train-pos', function(q){
      // Catch all messages
      q.bind('#');

      // // Receive messages
      // q.subscribe(function (message) {
      //   // Print messages to stdout
      //   console.log("msg: " + message);
      // });
  });
});

I get an endless number of 'ready' messages

kontrafiktion avatar Nov 24 '13 11:11 kontrafiktion

@vrvolle

Yes, in the end it cause memory leak.

As a workaround, you can either set the upper limit of listners of ready' event, or simply usingonceinsteadon`

kuno avatar Nov 25 '13 05:11 kuno

Binding once is not an acceptable workaround, that will run the callback upon the first failure, before the connection is established.

How are you guys delineating between a 'success' ready and a 'failure' ready event??

joshribakoff avatar Jul 02 '14 21:07 joshribakoff

mko already described what is happening and how to solve the issue. It might occur when you try to bind a queue to an exchange, that is not ready yet. Connect to the exchange before binding a queue to it.

Amberlamps avatar Jul 07 '14 16:07 Amberlamps

almost a year and no solution?

tungv avatar Sep 09 '14 06:09 tungv

I have the same problem. Multiple 'ready' (once every second or so) from the createConnection().

piot avatar Sep 22 '14 12:09 piot

I had the same issue but, as @mko suggested, there was a connection error.

For those who stumble across this, diagnose the issue by adding an error listener:

connection.on('error', function(e) {
  console.log("connection error...", e);
})

My issue was that I was trying to change the signature of an exchange (which apparently you can't do?). I ended up going into the web admin to fix. All good now.

footloosemoose avatar Sep 26 '14 20:09 footloosemoose

If your ready callback throws an error, it will be called again and again.

Solution is to add try/catch block to this code snippet: https://github.com/postwait/node-amqp/blob/master/lib/connection.js#L507-L515

case methods.connectionOpenOk:
      // 7. Finally they respond with connectionOpenOk
      // Whew! That's why they call it the Advanced MQP.
      if (this._readyCallback) {
       try{ // <--------------------------------------- Solution
            this._readyCallback(this);
        }catch(){}
        this._readyCallback = null;
      }
      this.emit('ready');
      break;

or make sure your ready callback does not throw any error.

jdkanani avatar Aug 13 '15 07:08 jdkanani

One possible cause is that you got some error in you ready listener, which will throw an uncaught exception. The solution for that should be a try catch or process.nextTick to make sure handlers won't throw.

tungv avatar Aug 13 '15 17:08 tungv

@footloosemoose Thank you for the suggestion. My problem was indeed that. I was getting an error which I was not tracing. Strange because what I is happening with me is that as soon as I pass a confirm property to the options object I get the error 'TypeError: undefined is not a function'

connection.exchange('my.exchange', { 
                                 type: 'direct', 
                                 autoDelete: false, 
                                 durable: true, 
                                 confirm: true 
                           }, function(ex) { });

Any ideas as to why this might be?

mmick66 avatar Nov 01 '15 10:11 mmick66