UNPKG

waterline-rabbitmq-simple

Version:

rabbitmq adapter for sails/waterline, removed a lot of functionality from sails-rabbitmq

311 lines (267 loc) 9.37 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } var _handlersPersistence = require('./handlers/persistence'); /** * Implementation of the sails-rabbitmq Adapter */ var _handlersPersistence2 = _interopRequireDefault(_handlersPersistence); var rabbit = require('rabbit.js'); var _ = require('lodash'); var Adapter = { /** * Local connections store */ connections: new Map(), /** * Adapter default configuration */ defaults: { url: 'amqp://localhost', schema: false }, /** * This method runs when a model is initially registered * at server-start-time. This is the only required method. * * @param {[type]} connection [description] * @param {[type]} collection [description] * @param {Function} cb [description] * @return {[type]} [description] */ registerConnection: function registerConnection(connection, collections, cb) { var _this = this; if (!connection.identity) return cb(new Error('Connection is missing an identity.')); if (this.connections.get(connection.identity)) return cb(new Error('Connection is already registered.')); var context = rabbit.createContext(connection.url); var config = { identity: connection.identity, context: context, models: new Map(_.pairs(collections)), userSockets: new Set(), sockets: { push: new Map() }, persistence: connection.persistence }; this.connections.set(connection.identity, config); context.on('error', function (err) { console.error(err); }); context.once('ready', function () { _this.setupConnection(connection, collections, config).then(cb)['catch'](cb); }); }, setupConnection: function setupConnection(connection, collections, config) { var _this2 = this; return Promise.all(_.map(collections, function (model) { return _this2.setupConnectionSockets(connection, model, config); })).then(function () { if (config.persistence) { return Promise.all(_.map(collections, function (model) { new _handlersPersistence2['default'](connection, model); })); } }).then(function () { return Promise.resolve(); }); }, setupConnectionSockets: function setupConnectionSockets(connection, model, config) { return Promise.all([this.getPushSocket(connection.identity, model.queueName || model.identity, { name: 'persistence' }).then(function (pushSocket) { config.sockets.push.set(model.identity, pushSocket); })]); }, /** * Fired when a model is unregistered, typically when the server * is killed. Useful for tearing-down remaining open connections, * etc. * * @param {Function} cb [description] * @return {[type]} [description] */ teardown: function teardown(conn, cb) { if (_.isFunction(conn)) { cb = conn; conn = null; } var connections = conn ? [conn].values() : this.connections.values(); var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = connections[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var c = _step.value; var _iteratorNormalCompletion2 = true; var _didIteratorError2 = false; var _iteratorError2 = undefined; try { for (var _iterator2 = c.sockets.push.values()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { var socket = _step2.value; socket.close(); } } catch (err) { _didIteratorError2 = true; _iteratorError2 = err; } finally { try { if (!_iteratorNormalCompletion2 && _iterator2['return']) { _iterator2['return'](); } } finally { if (_didIteratorError2) { throw _iteratorError2; } } } var _iteratorNormalCompletion3 = true; var _didIteratorError3 = false; var _iteratorError3 = undefined; try { for (var _iterator3 = c.userSockets.values()[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { var socket = _step3.value; socket.close(); } } catch (err) { _didIteratorError3 = true; _iteratorError3 = err; } finally { try { if (!_iteratorNormalCompletion3 && _iterator3['return']) { _iterator3['return'](); } } finally { if (_didIteratorError3) { throw _iteratorError3; } } } this.connections['delete'](c.identity); } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator['return']) { _iterator['return'](); } } finally { if (_didIteratorError) { throw _iteratorError; } } } cb(); }, /** * @override */ create: function create(connection, collection, values, cb) { this.update(connection, collection, values, values, cb); }, /** * @override */ update: function update(connection, collection, criteria, values, cb) { var config = this.connections.get(connection); var pushSocket = this.getSocket(connection, collection, 'push'); pushSocket.write(JSON.stringify(values), 'utf8'); }, /** * Setup and connect a PUSH socket for the specified model */ getPushSocket: function getPushSocket(connection, collection) { var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; var config = this.connections.get(connection); var context = config.context; var address = this.getQueueName(collection, options.name); var socket = context.socket('PUSH'); return new Promise(function (resolve, reject) { socket.connect(address, function () { resolve(socket); }); }); }, /** * Setup and connect a WORKER socket for the specified model */ getWorkerSocket: function getWorkerSocket(connection, collection) { var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; var config = this.connections.get(connection); var context = config.context; var address = this.getQueueName(collection, options.name); var socket = context.socket('WORKER'); socket.setEncoding('utf8'); socket.once('close', function () { config.userSockets['delete'](socket); }); return new Promise(function (resolve, reject) { socket.connect(address, function () { config.userSockets.add(socket); resolve(socket); }); }); }, /** * Return an extant socket of the specific type for the specified model */ getSocket: function getSocket(connectionId, collection, type) { var connection = this.connections.get(connectionId); return connection.sockets[type].get(collection); }, /** * Return the name of the AMQP exchange that is used by the specified model */ getExchangeName: function getExchangeName(model) { return '' + model; }, /** * Return the name of the AMQP queue that is used by the specified model * in conjuction with a particular type of work(er) */ getQueueName: function getQueueName(model, name) { if (_.isUndefined(name)) { throw new Error('name cannot be undefined in getQueueName'); } return '' + model; }, /** * Return AMQP routing key for a given Model instance * @return dot-delimited string of model attributes which constitutes the * queue routing key */ getRoutingKey: function getRoutingKey(connection, collection, values) { var config = this.connections.get(connection); var Model = config.models.get(collection); if (_.isUndefined(values)) { return '#'; } else if (!_.isArray(Model.routingKey)) { throw new Error('The model ' + Model.identity + ' must define a routingKey\n in order to be used with the Waterline pubsub interface'); } else { return this.parseRoutingKey(Model.routingKey, values); } }, /** * @return a rabbitmq routing key derived from a list of model attributes */ parseRoutingKey: function parseRoutingKey(routingKey, values) { return routingKey.map(function (attribute) { return values[attribute]; }).join('.'); }, /** * Return a model's connection that will be used for persistence, if it * exists. */ getPersistenceConnection: function getPersistenceConnection(connection, collection) { var config = this.connections.get(connection); var Model = config.models.get(collection); var persistenceConnections = _.without(Model.connection, connection); return persistenceConnections[0]; } }; _.bindAll(Adapter); exports['default'] = Adapter; module.exports = exports['default'];