From c0a564b765b1e1559a59cdafda02273880985747 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 19 Feb 2015 18:07:48 -0300 Subject: [PATCH] Add simple funnel implementation --- lib/funnel.js | 45 ++++++++++++++++++++++++++++++++ test/funnel.js | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 lib/funnel.js create mode 100644 test/funnel.js diff --git a/lib/funnel.js b/lib/funnel.js new file mode 100644 index 00000000..e0592528 --- /dev/null +++ b/lib/funnel.js @@ -0,0 +1,45 @@ +'use strict'; + + +var bitcore = require('bitcore'); +var $ = bitcore.util.preconditions; +var _ = bitcore.deps._; +var EventEmitter = require('events').EventEmitter; +var util = require('util'); + +function Funnel() { + this.handlers = {}; +} +util.inherits(Funnel, EventEmitter); + +Funnel.prototype.process = function(e) { + var queue = []; + var done = []; + queue.push(e); + while (queue.length !== 0) { + var event = queue.shift(); + var handlers = this.handlers[event.constructor.name] || []; + handlers.forEach(function(handler) { + var responses = handler(event); + if (responses && responses.length > 0) { + queue = queue.concat(responses); + } + }); + done.push(event); + } + done.forEach(function(event) { + //that.emit(event.name, event); + }); + +}; + + +Funnel.prototype.register = function(clazz, handler) { + $.checkArgument(_.isFunction(handler)); + var name = clazz.name; + this.handlers[name] = this.handlers[name] || []; + this.handlers[name].push(handler); +}; + + +module.exports = Funnel; diff --git a/test/funnel.js b/test/funnel.js new file mode 100644 index 00000000..54672667 --- /dev/null +++ b/test/funnel.js @@ -0,0 +1,70 @@ +'use strict'; + +var chai = require('chai'); +var should = chai.should(); +var sinon = require('sinon'); + +var Funnel = require('../lib/funnel'); + +describe('Funnel', function() { + + it('instantiate', function() { + var f = new Funnel(); + should.exist(f); + }); + + describe('process', function() { + function FooEvent() {} + function BarEvent() {} + var foo = new FooEvent(); + var bar = new BarEvent(); + foo.x = 2; + bar.y = 3; + + it('no handlers registered', function() { + var f = new Funnel(); + f.process.bind(f, foo).should.not.throw(); + }); + it('simple handler gets called', function(cb) { + var f = new Funnel(); + f.register(FooEvent, function(e) { + e.x.should.equal(foo.x); + cb(); + }); + f.process(foo); + }); + it('other event does not get called', function() { + var f = new Funnel(); + var spy = sinon.spy(); + f.register(FooEvent, spy); + f.process(bar); + spy.callCount.should.equal(0); + }); + it('foo returns bar', function(cb) { + var f = new Funnel(); + f.register(FooEvent, function(e) { + var b = new BarEvent(); + b.y = e.x; + return [b]; + }); + f.register(BarEvent, function(e) { + e.y.should.equal(foo.x); + cb(); + }); + f.process(foo); + }); + it('foo returns two bars', function() { + var f = new Funnel(); + var spy = sinon.spy(); + f.register(FooEvent, function() { + var b1 = new BarEvent(); + var b2 = new BarEvent(); + return [b1, b2]; + }); + f.register(BarEvent, spy); + f.process(foo); + spy.callCount.should.equal(2); + }); + }); + +});