squaremo / rabbit.js

Messaging in Node.JS made easy using RabbitMQ
Other
1.52k stars 142 forks source link

Durable topic exchange #63

Open stephenmuss opened 10 years ago

stephenmuss commented 10 years ago

I need to be able to publish to a durable topic exchange but at the moment this seems to be disallowed as per

PubSocket.prototype.connect = function(destination, callback) {
  var self = this, ch = this.ch;
  ch.assertExchange(destination,
                    this.options.routing || 'fanout',
                    {durable: false, autoDelete: false})
    .then(function(ok) {
      self.pubs.push(destination);
    }).then(callback);
};

When I connect to RabbitMQ I get the following error

Channel closed by server: 406 (PRECONDITION-FAILED) with message
"PRECONDITION_FAILED - cannot redeclare exchange 'ExchangeName'
in vhost '/' with different type, durable, internal or autodelete value"

It would be great if it were possible to do the following:

var pub = context.socket('PUBLISH', {routing: 'topic', persistent: true});
pub.connect(exchange);

I ended up updating the assertExchange code above to set durable to true but I'm not sure what the wider implications are of doing so.

I'm happy to submit a pull request if this is a feasible option.

squaremo commented 10 years ago

Is that because you are using it from another library?

stephenmuss commented 10 years ago

@squaremo it's because the consumers are actually different applications/services.

squaremo commented 10 years ago

Right. And those other applications need it to be durable, so e.g., bindings don't go away. I suppose it would make sense if a "persistent" PUBLISH socket declared its exchanges as durable. Does it belong in the socket constructor or connect though? It could be both.

stephenmuss commented 10 years ago

I thought it might make sense to appear in connect but noticed that in other places you allowed for the persistent option in the constructor. I guess it's really a matter of whether you conform to the current method of passing an option in the constructor or whether it makes more sense to allow for a durable flag in connect.

squaremo commented 10 years ago

The constructor arguments tend to just set the default for that socket, so I guess it can be in both places.

mathiaske commented 9 years ago

+1 For the current version of our application we will simply leave everything 'transient' but this could be of interest in the future.

To my knowledge connecting/re-asserting an exchange with different properties than the already existing one fails (in this case durable and transient). Is it possible to read out the properties of an exchange before connecting to it? Wouldn't this allow some kind of auto-fix/step-up-down option/function or even auto-configuration of the socket, or is my imagination simply going wild again ..

disintegrator commented 9 years ago

+1 I am currently trying to work around this but I would definitely appreciate control over the exchange's properties.

JSteunou commented 9 years ago

+1 Currently using default "amq.topic" exchange from RabbitMQ which is durable.

JoelBennett commented 9 years ago

+1 here as well.

squaremo commented 9 years ago

OK. Sorry for the long silence. I have pushed a change to master which lets you tell a socket not to try and create objects when connecting; this means you can use exchanges and queues created elsewhere with properties different to those rabbit.js would give them.

var ctx = require('rabbit.js').createContext();
var pub = ctx.socket('PUB', {noCreate: true});
pub.connect(existingExchange);

If anyone is game to try this out, would you let me know if it works for you? It's pretty sketchy but I'd like to build on it. Thank you!

mikeatlas commented 9 years ago

Thanks! This works for me with "rabbit.js": "^0.4.4",

context.socket('PUB', {noCreate: true}); for a durable exchange that already existed on my server:

Publishing to an existing durable exchange screenshot