From 00f4be4a071baedc4d6c2737c832565b2124dd41 Mon Sep 17 00:00:00 2001 From: Vladimir Sibirov Date: Fri, 23 May 2014 23:52:56 +0400 Subject: [PATCH] Updated `GroupComponent` helper: - Added support for async components (via config and callback in handler's params) - Matching inputs by group name is disabled by default, because it conflicts with other grouping conventions --- spec/Helpers.coffee | 41 ++++++++++++++++++++++++++++++++++++++--- src/lib/Helpers.coffee | 28 ++++++++++++++++++++++------ 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/spec/Helpers.coffee b/spec/Helpers.coffee index fb8647209..bd91a3858 100644 --- a/spec/Helpers.coffee +++ b/spec/Helpers.coffee @@ -97,7 +97,7 @@ describe 'Component traits', -> chai.expect(data).to.deep.equal src[groups[0]] out.send data # done() if groups[0] is 333 - , ['x', 'y', 'z'], 'point' + , ['x', 'y', 'z'], 'point', {group: true} groups = [] count = 0 @@ -142,7 +142,7 @@ describe 'Component traits', -> z.send 789 z.disconnect() - it 'should process inputs for different groups independently', (done) -> + it 'should process inputs for different groups independently with group: true', (done) -> src = 1: {x: 1, y: 2, z: 3} 2: {x: 4, y: 5, z: 6} @@ -162,7 +162,7 @@ describe 'Component traits', -> helpers.GroupComponent c, (data, groups, out) -> out.send {x: data.x, y: data.y, z: data.z} - , ['x', 'y', 'z'], 'point' + , ['x', 'y', 'z'], 'point', {group: true} groups = [] @@ -190,3 +190,38 @@ describe 'Component traits', -> input.send src[tuple[0]][tuple[1]] input.endGroup() input.disconnect() + + it 'should support asynchronous handlers', (done) -> + point = + x: 123 + y: 456 + z: 789 + + helpers.GroupComponent c, (data, groups, out, callback) -> + setTimeout -> + out.send {x: data.x, y: data.y, z: data.z} + callback() + , 100 + , ['x', 'y', 'z'], 'point', {async: true, group: true} + + p.removeAllListeners() + counter = 0 + p.on 'begingroup', (grp) -> + counter++ + p.on 'endgroup', -> + counter-- + p.once 'data', (data) -> + chai.expect(data).to.deep.equal point + p.once 'disconnect', -> + chai.expect(counter).to.equal 0 + done() + + x.beginGroup 'async' + y.beginGroup 'async' + z.beginGroup 'async' + x.send point.x + y.send point.y + z.send point.z + x.endGroup() + y.endGroup() + z.endGroup() diff --git a/src/lib/Helpers.coffee b/src/lib/Helpers.coffee index 0ab7c46bc..10fc3902a 100644 --- a/src/lib/Helpers.coffee +++ b/src/lib/Helpers.coffee @@ -28,6 +28,10 @@ exports.MapComponent = (component, func, config) -> exports.GroupComponent = (component, func, inPorts='in', outPort='out', config={}) -> unless Object.prototype.toString.call(inPorts) is '[object Array]' inPorts = [inPorts] + # For async func + config.async = false unless 'async' of config + # Group requests by group ID + config.group = false unless 'group' of config for name in inPorts unless component.inPorts[name] @@ -48,15 +52,27 @@ exports.GroupComponent = (component, func, inPorts='in', outPort='out', config={ when 'begingroup' inPort.groups.push payload when 'data' - key = inPort.groups.toString() + key = if config.group then inPort.groups.toString() else '' groupedData[key] = {} unless key of groupedData groupedData[key][port] = payload # Flush the data if the tuple is complete if Object.keys(groupedData[key]).length is inPorts.length - out.beginGroup group for group in inPort.groups - func groupedData[key], inPort.groups, out - out.endGroup() for group in inPort.groups - out.disconnect() - delete groupedData[key] + groups = inPort.groups + out.beginGroup group for group in groups + if config.async + grps = groups.slice(0) + func groupedData[key], groups, out, (err) -> + if err + component.error err, groups + # For use with MultiError trait + component.fail if typeof component.fail is 'function' + out.endGroup() for group in grps + out.disconnect() + delete groupedData[key] + else + func groupedData[key], inPort.groups, out + out.endGroup() for group in inPort.groups + out.disconnect() + delete groupedData[key] when 'endgroup' inPort.groups.pop()