UNPKG

spincycle

Version:

A reactive message router and object manager that lets clients subscribe to object property changes on the server

440 lines (376 loc) 14.4 kB
// Generated by CoffeeScript 1.12.6 (function() { var ClientEndpoints, DB, DDAPI, EventManager, HttpMethod, MessageRouter, OStore, ObjectManager, RateLimiter, RedisMethod, ResolveModule, SpinApp, SpinFunction, SpinMeta, SpinModule, SpinTag, StatsD, SuperModel, Taginator, WsMethod, colors, defer, e, error, express, path, serveStatic, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; ObjectManager = require('./ObjectManager'); error = require('./Error').error; HttpMethod = require('./HttpMethod'); WsMethod = require('./WsMethod'); RedisMethod = require('./RedisMethod'); DB = require('./DB'); EventManager = require('./EventManager'); SuperModel = require('./SuperModel'); SpinModule = require('./SpinModule'); SpinApp = require('./SpinApp'); SpinFunction = require('./SpinFunction'); SpinTag = require('./SpinTag'); ClientEndpoints = require('./ClientEndpoints'); OStore = require('./OStore'); ResolveModule = require('./ResolveModule'); RateLimiter = require('limiter').RateLimiter; e = require('./EventManager'); express = require("express"); path = require('path'); defer = require('node-promise').defer; serveStatic = require('serve-static'); colors = require('colors/safe'); DDAPI = require('./DDAPI'); StatsD = require('node-statsd').StatsD; Taginator = require('./Taginator'); SpinMeta = require('./SpinMeta'); MessageRouter = (function() { var debug; MessageRouter.HttpMethod = HttpMethod; MessageRouter.WsMethod = WsMethod; MessageRouter.RedisMethod = RedisMethod; MessageRouter.DB = DB; MessageRouter.EventManager = EventManager; MessageRouter.SuperModel = SuperModel; MessageRouter.ObjectManager = ObjectManager; MessageRouter.ClientEndpoints = ClientEndpoints; MessageRouter.OStore = OStore; MessageRouter.ResolveModule = ResolveModule; MessageRouter.status = 'closed'; MessageRouter.dogstatsd = void 0; debug = process.env["DEBUG"]; function MessageRouter(authMgr, dburl, msgPS, app, dbtype, datadogOptions) { var q; this.authMgr = authMgr; this.app = app; if (dbtype == null) { dbtype = 'mongodb'; } this.datadogOptions = datadogOptions; this.searchForTags = bind(this.searchForTags, this); this.getTagsFor = bind(this.getTagsFor, this); this.setTag = bind(this.setTag, this); this.uniqueMetric = bind(this.uniqueMetric, this); this.gaugeMetric = bind(this.gaugeMetric, this); this.incrementMetric = bind(this.incrementMetric, this); this.routeMessage = bind(this.routeMessage, this); this.removeTarget = bind(this.removeTarget, this); this.addTarget = bind(this.addTarget, this); this.addMethod = bind(this.addMethod, this); this.close = bind(this.close, this); this.open = bind(this.open, this); this.makeRESTful = bind(this.makeRESTful, this); this.expose = bind(this.expose, this); this.register = bind(this.register, this); this.addServicePage = bind(this.addServicePage, this); this.setup = bind(this.setup, this); q = defer(); MessageRouter.DB.dburl = dburl; MessageRouter.DB.dbname = dbtype; this.resolver = new ResolveModule(); ResolveModule.modulecache['SpinModule'] = SpinModule; ResolveModule.modulecache['SpinFunction'] = SpinFunction; ResolveModule.modulecache['SpinApp'] = SpinApp; ResolveModule.modulecache['SpinTag'] = SpinTag; ResolveModule.modulecache['SpinMeta'] = SpinMeta; DB.getDataStore(dbtype).then((function(_this) { return function() { var pjson; pjson = require('../package.json'); _this.messagesPerSecond = msgPS || 100; console.log(colors.blue.inverse('-----------------------------------------------------------------------------------------------')); console.log(colors.blue.bold.inverse(' SpinCycle messageRouter constructor. Version - ' + pjson.version + ' messages per user per second limit = ' + _this.messagesPerSecond + ' ')); console.log(colors.blue.inverse('-----------------------------------------------------------------------------------------------')); if (_this.datadogOptions) { console.log('datadog options are'); console.dir(_this.datadogOptions); _this.dogstatsd = new StatsD(); DDAPI.init(_this.datadogOptions); } _this.authMgr.messagerouter = _this; _this.targets = []; _this.debugtargets = []; _this.args = []; _this.methods = []; _this.objectManager = new ObjectManager(_this); _this.objectManager.setup(); if (_this.authMgr.setup) { _this.authMgr.setup(_this); } _this.setup(); return q.resolve(_this); }; })(this)); return q; } MessageRouter.prototype.setup = function() { this.addTarget('listcommands', '<noargs>', (function(_this) { return function(msg) { var name, ref, rv, target; rv = { listcommands: '<noarg>' }; ref = _this.targets; for (name in ref) { target = ref[name]; rv[name] = _this.args[name]; } return msg.replyFunc({ status: EventManager.general.SUCCESS, info: 'list of available targets', payload: rv }); }; })(this)); if (this.datadogOptions) { this.addTarget('ddapi', 'metric,value,tags', (function(_this) { return function(msg) { var err; console.log('ddapi got call'); console.dir(msg); if (msg.metric && msg.value) { if (typeof msg.tags === 'string') { try { msg.tags = JSON.parse(msg.tags); } catch (error1) { err = error1; msg.replyFunc({ status: 'FAILURE', info: 'lossy JSON format of tags', payload: msg.metric }); return; } } _this.gaugeMetric(msg.metric, msg.value, msg.tags || {}); return msg.replyFunc({ status: 'SUCCESS', info: 'datadog metric sent', payload: msg.metric }); } else { return msg.replyFunc({ status: 'FAILURE', info: 'missing parameter(s)', payload: msg.metric }); } }; })(this)); } return setTimeout(this.addServicePage.bind(this), 1); }; MessageRouter.prototype.addServicePage = function() { var p; p = __dirname + '/spin'; if (this.app) { console.log('**************** addServicePage called -> ' + p); this.app.use('/spin', express["static"](p)); this.app.use('/spin/bower_components', express["static"](p + '/bower_components')); } else { console.log('no app argument provided to MessageRouter! Unable to set up /spin route'); } console.log('**************** exposing SpinModule and SpinFunction'); return DB.createDatabases(['SpinModule', 'SpinFunction', 'SpinApp', 'SpinTag']).then((function(_this) { return function() { console.log(' DB init done..'); _this.objectManager.expose('SpinModule'); _this.objectManager.expose('SpinFunction'); _this.objectManager.expose('SpinApp'); _this.objectManager.expose('SpinMeta'); _this.makeRESTful('SpinModule'); _this.makeRESTful('SpinFunction'); _this.makeRESTful('SpinApp'); return _this.makeRESTful('SpinMeta'); }; })(this)); }; MessageRouter.prototype.register = function(types) { var q, typenames; q = defer(); typenames = []; types.forEach((function(_this) { return function(type) { typenames.push(type.name); ResolveModule.modulecache[type.name] = type.module; _this.objectManager.expose(type.name); return _this.makeRESTful(type.name); }; })(this)); DB.createDatabases(typenames).then((function(_this) { return function() { return q.resolve(); }; })(this)); return q; }; MessageRouter.prototype.expose = function(type) { var method, name, ref, results; ref = this.methods; results = []; for (name in ref) { method = ref[name]; results.push(method.expose(type)); } return results; }; MessageRouter.prototype.makeRESTful = function(type) { var method, name, ref, results; ref = this.methods; results = []; for (name in ref) { method = ref[name]; if (name === 'express') { results.push(method.makeRESTful(type)); } else { results.push(void 0); } } return results; }; MessageRouter.prototype.open = function() { MessageRouter.status = 'open'; return console.log(colors.inverse.green(' * opening message router * ')); }; MessageRouter.prototype.close = function() { MessageRouter.status = 'closed'; return console.log('closing message router'); }; MessageRouter.prototype.addMethod = function(methodName, method) { var results, targetName; console.log('addMethod called for "' + methodName + '"'); this.methods[methodName] = method; results = []; for (targetName in this.targets) { results.push(method.registrationFunc(targetName, this.routeMessage)); } return results; }; MessageRouter.prototype.addTarget = function(targetName, args, targetFunc, props) { var method, name, ref, results; this.targets[targetName] = targetFunc; this.args[targetName] = args; ref = this.methods; results = []; for (name in ref) { method = ref[name]; if (method.registrationFunc) { results.push(method.registrationFunc(targetName, this.routeMessage, props)); } else { console.log('Spincycle did NOT find target for ' + targetName); console.log('----------------methods-------------------'); results.push(console.dir(this.methods)); } } return results; }; MessageRouter.prototype.removeTarget = function(targetName) { return this.targets[targetName] = null; }; MessageRouter.prototype.routeMessage = function(message) { var fn; if (MessageRouter.status !== 'open') { return message.replyFunc({ status: e.general.NOT_ALLOWED, info: 'Message router is not yet open', payload: { error: 'ERRCHILLMAN' } }); } else { fn = this.targets[message.target]; if (fn) { return this.authMgr.decorateMessageWithUser(message).then((function(_this) { return function(m) { if (!m.user) { console.log('** SpinCycle did not get message decorated with user property from AuthenticationManager **'); exit(-1); } if (!m.user.limiter) { m.user.limiter = new RateLimiter(parseInt(_this.messagesPerSecond), 1000); } if (m.user.limiter && m.user.limiter.removeTokens) { return m.user.limiter.removeTokens(1, function(err, remainingRequests) { if (parseInt(remainingRequests) < 1) { return m.replyFunc({ status: e.general.NOT_ALLOWED, info: 'packets over ' + _this.messagesPerSecond + '/s dropped. Have a nice day.', payload: { error: 'TOOMANYPACKETSPERSECOND' } }); } else { return fn(m); } }); } else { console.log('** user ' + m.user.name + ' have no ratelimiter or at least not one with a removeToken function!!!'); return console.dir(m.user); } }; })(this)); } else { return console.log('--- could not find registered target for message! ---'); } } }; MessageRouter.prototype.incrementMetric = function(metric, tags) { if (this.datadogOptions) { return DDAPI.writePoint(metric, tags, 'increment'); } }; MessageRouter.prototype.gaugeMetric = function(metric, val, tags) { if (this.datadogOptions) { return DDAPI.writePoint(metric, val, tags, 'gauge'); } }; MessageRouter.prototype.uniqueMetric = function(metric, val, tags) { if (this.datadogOptions) { return DDAPI.writePoint(metric, val, tags, 'unique'); } }; MessageRouter.prototype.setTag = function(type, id, tag) { var q; q = defer(); DB.getDataStore().then((function(_this) { return function(store) { return Taginator.setTag(store, type, id, tag).then(function(value) { return q.resolve(value); }); }; })(this)); return q; }; MessageRouter.prototype.getTagsFor = function(type, id) { var q; q = defer(); DB.getDataStore().then((function(_this) { return function(store) { return Taginator.getTagsFor(store, type, id).then(function(value) { return q.resolve(value); }); }; })(this)); return q; }; MessageRouter.prototype.searchForTags = function(type, tags) { var q; q = defer(); DB.getDataStore().then((function(_this) { return function(store) { return Taginator.searchForTags(store, type, tags).then(function(value) { return q.resolve(value); }); }; })(this)); return q; }; return MessageRouter; })(); module.exports = MessageRouter; }).call(this); //# sourceMappingURL=MessageRouter.js.map