UNPKG

amqp-hutch

Version:
255 lines (190 loc) 6.18 kB
'use strict'; var amqp = require('amqplib/callback_api'); var util = require('util'); var Emitter = require('events').EventEmitter; var AMQPConnectionError = require('./errors/amqp-connection-error'); //TODO: Replace with SSL pem file. process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0'; var CONNECTED = "CONNECTED"; var DISCONNECTED = "DISCONNECTED"; // Store Instance of Channel for later lookup. var channels = {}; var status = DISCONNECTED; function AMQPHutch() { } util.inherits(AMQPHutch, Emitter); function _isConnectionEstablished(self){ return self._conn != undefined; } function _handleConnectionEstablishError(callback){ return callback(new AMQPConnectionError('Could not Establish a Connection to RabbitMQ Server')); } /** * Exposes a state variable * * @type {string} */ AMQPHutch.prototype.status = status; /** * Configuration Accessor * * @type {undefined} */ AMQPHutch.prototype.configuration = null; /** * Initialise AMQPHutch Connection */ AMQPHutch.prototype.initialise = function(configuration) { this.configuration = configuration; this._connectionString = configuration.connectionString; this._retryWait = configuration.retryWait; this._connect(); }; /** * Publish message */ AMQPHutch.prototype.publish = function(options, payload, callback) { if (!_isConnectionEstablished(this)) return _handleConnectionEstablishError(callback); if(options.exchange){ this.publishToExchange(options.exchange.name, options.exchange.type, options, payload, callback); } }; /** * Publish message to the exchange */ AMQPHutch.prototype.publishToExchange = function(exchange, type, options, payload, callback) { if (!_isConnectionEstablished(this)) return _handleConnectionEstablishError(callback); options = options || { exchange: {}, publish: {} }; this._conn.createConfirmChannel(function(err, channel) { channel.assertExchange(exchange, type, options.exchange, function(err, ex) { if (err) return callback(err); channel.on('error', function(err) { callback(err); }); channel.publish(ex.exchange, '', new Buffer(JSON.stringify(payload)), options.publish); channel.waitForConfirms(function(err) { channel.close(); callback(err); }); }); }); }; /** * Consume Queue to Exchange wrapper. */ AMQPHutch.prototype.consume = function(options, consumer, callback) { if (!_isConnectionEstablished(this)) return _handleConnectionEstablishError(callback); var self = this; this._conn.createChannel(function(err, channel) { if (err) return callback(err); channel.assertExchange(options.exchange.name, options.exchange.type, options.exchange, function(err, ok) { if (err) return callback(err); channel.assertQueue(options.queue.name, options.queue, function(err, ok) { if (err) return callback(err); channel.bindQueue(options.queue.name, options.exchange.name, options.routingKey || '#'); channel.prefetch(options.queue.prefetch); // Store the channel instance channels[options.queue.name] = channel; channel.on('error', function() { // This will be handled by the 'close' event.npm }); channel.on('close', function() { self.emit('channelClosed', options.queue.name); delete channels[options.queue.name]; }); channel.consume(options.queue.name, function(message) { var done = function() { try { channel.ack(message); } catch(e) { // This will be thrown if the channel is closing. } }; var fail = function() { setTimeout(function() { try { channel.nack(message); } catch(e) { // This will be thrown if the channel is closing. } }, self._retryWait); }; consumer(message, done, fail); }); callback(); }, {noAck: false}); }); }); }; AMQPHutch.prototype.destroy = function(queue, exchange, callback) { if (!_isConnectionEstablished(this)) return _handleConnectionEstablishError(callback); // Load channel instance this.get(queue, function(err, channel) { if (err) return callback(err); channel.unbindQueue(queue, exchange, '', {}, function(err, ok) { if (err) return callback(err); channel.deleteQueue(queue, {}, function(err, ok) { if (err) return callback(err); channel.close(function(err) { callback(err); }); }); }); }); }; AMQPHutch.prototype.get = function(queue, callback) { if (!_isConnectionEstablished(this)) return _handleConnectionEstablishError(callback); // Load channel instance var channel = channels[queue]; if (channel) return callback(null, channel); // If we dont have one create a new one this._conn.createChannel(function(err, channel) { if (err) return callback(err); return callback(err, channel); }); }; /** * close consumer. */ AMQPHutch.prototype.close = function(queue, callback) { if (!_isConnectionEstablished(this)) return _handleConnectionEstablishError(callback); // Load channel instance var channel = channels[queue]; if (!channel) return callback(); channel.checkQueue(queue, function(err) { if (err) return callback(err); channel.close(function(err) { callback(err); }); }); }; /** * Initialise Connection */ AMQPHutch.prototype._connect = function() { var self = this; var retry = function() { setTimeout(function() { self._connect(); }, self._retryWait); }; // Establish RabbisMQ Connection amqp.connect(self._connectionString, function(err, conn) { if (err) { self.emit('error', err); return retry(); } conn.on("error", function(err) { self.emit('error', err); }); conn.on("close", function(err) { self.emit('close', err); self.status = DISCONNECTED; return retry(); }); self.status = CONNECTED; self._conn = conn; self.emit('ready', conn); }); }; module.exports = AMQPHutch;