/server/combine.js
JavaScript | 162 lines | 87 code | 26 blank | 49 comment | 10 complexity | bdf885d1a0f3a2db794f076983ac6bfd MD5 | raw file
Possible License(s): MIT
- var util = require('util'),
- events = require('events'),
- fs = require('fs'),
- path = require('path'),
- _ = require('underscore'),
- Backbone = require('backbone'),
- logger = require('./logging').logger;
- // Location of reapers
- var REAPER_DIR = path.join(__dirname, 'reapers');
- /**
- * Combine for collecting reaper data
- */
- function Combine(config) {
- events.EventEmitter.call(this);
- // List of Reapers
- this.reapers = [];
- // Collected actions from reapers
- this.actions = new ActionsCollection();
- this.actions.on('add', function(action, collection, index) {
- this.emit('action', action);
- }.bind(this));
- // Try to load configured reapers
- if (config.reapers) {
- config.reapers.forEach(function(spec) {
- var reaper = createReaper(spec);
- this.addReaper(reaper);
- }, this);
- }
- }
- util.inherits(Combine, events.EventEmitter);
- /**
- * Harvest Actions from a data set, provided by a reaper
- */
- Combine.prototype.harvest = function(data, reaper) {
- // Add a custom ID for recognizing the action and
- // prevent ID collisions from other systems.
- data.pid = data.id + '@' + reaper.source;
- // Add a prefixed type to the action
- data.ptype = reaper.source + '#' + data.type;
- // Add timestamp of the action date for convenience
- if ('string' === typeof(data.date)) {
- data.date = moment(data.date).toDate();
- }
- data.timestamp = data.date.getTime();
- // Add the action model
- this.actions.add(new ActionModel(data));
- };
- /**
- * Add a reaper. This will keep watch for `data` events on the
- * reaper and pass this information to the `harvest` method.
- */
- Combine.prototype.addReaper = function(reaper) {
- // Watch for reaper data
- reaper.on('data', this.harvest.bind(this));
- // Keep a reference to the reaper
- this.reapers.push(reaper);
- return this;
- };
- /**
- * Start harvesting
- */
- Combine.prototype.start = function() {
- this.reapers.forEach(function(reaper) {
- reaper.start();
- });
- };
- // # getActionCount
- // ================
- // @TODO Add filter method to count subsets
- Combine.prototype.getActionCount = function(filter) {
- return this.actions.length;
- };
- // # getActionSet
- // ============
- // Get a subset of the Combine actions.
- Combine.prototype.getActionSet = function(number, startAt) {
- startAt = startAt - 1 || 0;
- if (0 > startAt) {
- startAt = 0;
- }
- // Get the actions
- var actions = this.actions.toArray();
- // If a number is specified return a subset
- if (_.isNumber(number)) {
- actions = actions.slice(startAt, number);
- }
- return actions;
- };
- /**
- * Create a reaper instance based on a small specification
- */
- function createReaper(spec) {
- // @TODO Check if reaper file exists
- // @TODO Crash gracefully
- // Load the reaper from disk
- var Reaper = require(path.join(REAPER_DIR, spec.module));
- // Return a new instance
- return new Reaper(spec.config);
- }
- // # ActionModel
- // =============
- // Model for data received from a reaper
- var ActionModel = Backbone.Model.extend();
- // # ActionsCollection
- // ===================
- // Collection for storing Action Models
- var ActionsCollection = Backbone.Collection.extend({
- model: ActionModel,
- comparator: function(a, b) {
- var aTime = a.get('date'),
- bTime = b.get('date');
- if (aTime > bTime) { return -1; }
- else if (aTime < bTime) { return 1; }
- else { return 0; }
- },
- // Override the default add method to add duplicate id check
- add: function(models, options) {
- if (!_.isArray(models)) {
- models = [models];
- }
- // Filter duplicate models
- models = models.filter(function(model) {
- return (0 === this.where({ id: model.get('id') }).length);
- }.bind(this));
- // Pass through to the prototype add method
- Backbone.Collection.prototype.add.call(this, models, options);
- }
- });
- // our awesome export products
- exports = module.exports = {
- "Combine": Combine,
- "reaper": {},
- "create": function(options) {
- return new Combine(options);
- }
- };