regard
Version:
Sugar-interface to access multiple data sources.
141 lines (110 loc) • 3.23 kB
JavaScript
var _ = require('lodash'),
Amqp = require('amqplib'),
Connector = require('../connector');
exports = module.exports = RabbitmqConnector;
var Methods = exports.Methods = [
'consume', 'produce'
];
var KEY = exports.KEY = Connector.generateKey(__filename);
var SETTINGS = exports.SETTINGS = {
method: 'consume'
};
var brokers = {};
function RabbitmqConnector() {
if (!(this instanceof RabbitmqConnector)) {
return new RabbitmqConnector();
}
Connector.call(this, KEY, SETTINGS);
bindHandlers(this);
}
RabbitmqConnector.prototype = _.create(Connector.prototype);
RabbitmqConnector.prototype.checkPath = canAcceptPath;
RabbitmqConnector.prototype.checkMethod = canAcceptMethod;
RabbitmqConnector.prototype.onCreateEndpoint = createClient;
function bindHandlers($this) {
$this.handler(Connector.DEFAULT_HANDLER, handleRequest, beforeRequest);
_.forEach(Methods, function bindHandler(method) {
$this.handler(method, handleRequest, function beforeHandler(request) {
return _.partial(beforeRequest, request, method).apply($this, _.slice(arguments, 1));
});
});
}
function canAcceptPath(path) {
return _.startsWith(path, 'amqp://');
}
function canAcceptMethod(method) {
return _.isString(method) && _.includes(Methods, method);
}
function createClient(endpoint) {
var uri = endpoint.path,
opts = endpoint.context;
if (endpoint.root) {
brokers[endpoint.name] = Amqp.connect(uri);
} else {
endpoint.context.queue = queueNameFromUri(uri);
brokers[endpoint.name] = brokers[endpoint.parent.name];
}
}
function beforeRequest(request) {
var args = _.cloneDeep(_.slice(arguments, 1)),
method = args.shift(),
queue;
if (_.isString(method) && !canAcceptMethod(method)) {
queue = method;
method = undefined;
} else {
if (_.isString(args[0])) {
queue = args.shift();
}
}
if (!_.isUndefined(method)) {
request.context.method = method;
request.handler = method;
}
if (_.isString(queue) && !_.isEmpty(queue)) {
request.context.queue = queue;
}
request.args = args;
return request;
}
function queueNameFromUri(uri) {
return _(uri).split('/').pop();
}
function handleRequest(request, resolve, reject) {
var broker = brokers[request.endpoint.name],
queue = request.context.queue,
method = request.handler,
args = request.args,
processing;
broker
.then(function (conn) {
return conn.createChannel();
})
.then(function (ch) {
var ok = ch.assertQueue(queue, request.context.options);
if (method === 'produce') {
var msg = args.shift();
if (_.isPlainObject(msg)) {
msg = JSON.stringify(msg);
}
var result = ch.sendToQueue(queue, new Buffer(msg.toString()));
resolve(result);
} else {
ok.then(function () {
var cb = args.shift();
return ch.consume(queue, function (msg) {
if (_.isFunction(cb)) {
cb(msg);
}
if (msg === null) {
reject();
} else {
resolve(msg);
ch.ack(msg);
}
})
});
}
})
.catch(reject);
}