dansimpson / amqp-js

A push enabled AMQP Client for Javascript
120 stars 10 forks source link

Can't reconnect after a disconnect - channels not re-opened #8

Closed andrewrjones closed 12 years ago

andrewrjones commented 12 years ago

I wan't my web app to be able to reconnect to my AMQP server after it has been disconnected (for example, after putting their laptop to sleep).

So I listened to the disconnect event, and then planned to keep trying to reconnect after a number of seconds.

However, when I try to reconnect, by calling connect on the MQ object, it reconnects to the AMQP server but does not open the channels, therefore not getting any new data.

Heres what my code looks like:

MQ.on('disconnect', function(){
    // possibly use a setTimeout
    MQ.connect();
});

I test this by going to the Rabbit MQ admin console and force-disconnecting my client.

I have tried alternatives to connect, such as onLoad, etc, but still no solution.

dansimpson commented 12 years ago

So the client reconnects to the server, but the pre-disconnect state is lost?

andrewrjones commented 12 years ago

Sorry, what do you mean by pre-disconnect state?

Looking at the JavaScript object in Firebug, everything looks like it should. The configuration is still set up correctly. All the event listeners that were added are still there and are being called.

dansimpson commented 12 years ago

What is happening is: on first connect, the client sends commands to the server informing the server of subscriptions to topics, binding to queues, etc. On disconnect, the server loses all knowledge (state) of those bindings and subscriptions for the client. The client needs to rebuild state on the server by re-sending every command. So, here is an untested possible solution for you application:

var reconnect = false;

MQ.on('connect', function(){
  if(reconnect) {
    // clear the local state, killing callbacks in the process
    // note this is unclean, as it's a memory leak, albeit small
    MQ.queues = {};
    MQ.exchanges = {};
  }

  // your application setup, what you do when you connect
  // subscribe, bind, etc
  MQ.queue("...").bind()...
});

MQ.on('disconnect', function(){
  // set the flag so you know to reset state
  reconnect = true;
  MQ.connect();
});

I think that should do it. Please follow up with code if it does not. A cleaner solution would be in the js lib which allows to "re-establish" state and I will see what I can do.

andrewrjones commented 12 years ago

Thanks a lot, your solution worked perfectly!

I appreciate your help with this.

dansimpson commented 12 years ago

No problem!