gate-executor
Advanced tools
Comparing version 0.2.3 to 0.3.0
@@ -31,5 +31,9 @@ /* Copyright (c) 2014-2015 Richard Rodger, MIT License */ | ||
error: function(err){ | ||
error: function(err) { | ||
self.emit('error',err) | ||
}, | ||
clear: function() { | ||
self.emit('clear') | ||
}, | ||
},options) | ||
@@ -54,4 +58,5 @@ | ||
var gated = false | ||
var waiters = [] | ||
var gated = false | ||
var waiters = [] | ||
var inflight = 0 | ||
@@ -72,3 +77,3 @@ var runtrace = !!options.trace | ||
tr('ungate') | ||
tr('ungate',gated,inflight) | ||
gated = false | ||
@@ -84,4 +89,14 @@ | ||
function work( task, done ) { | ||
tr('work',task.id,task.desc) | ||
tr('work',gated,inflight,task.id,task.desc) | ||
function check_clear() { | ||
inflight-- | ||
//console.log(inflight, waiters.length, q.length()) | ||
if( 0 == inflight && 0 === waiters.length && 0 === q.length() ) { | ||
tr('clear',gated,inflight) | ||
options.clear() | ||
} | ||
} | ||
setImmediate( function(){ | ||
@@ -96,3 +111,3 @@ var completed = false | ||
tr('timeout',task.id,task.desc) | ||
tr('timeout',gated,inflight,task.id,task.desc) | ||
task.time.end = now() | ||
@@ -105,3 +120,10 @@ | ||
done(err); | ||
try { | ||
done(err,null) | ||
} | ||
catch(e) { | ||
options.error(error(e,options.msg_codes.callback,task)) | ||
} | ||
check_clear() | ||
},options.timeout) | ||
@@ -118,5 +140,5 @@ } | ||
completed = true | ||
if( timedout ) return; | ||
if( timedout ) return | ||
tr('done',task.id,task.desc,Date.now()-task_start) | ||
tr('done',gated,inflight,task.id,task.desc,Date.now()-task_start) | ||
task.time.end = now() | ||
@@ -130,2 +152,3 @@ | ||
args[0] = error(err,options.msg_codes.error,task) | ||
args[1] = args[1] || null | ||
} | ||
@@ -141,2 +164,4 @@ | ||
} | ||
check_clear() | ||
}) | ||
@@ -151,3 +176,3 @@ } | ||
try { | ||
done(et) | ||
done(et,null) | ||
} | ||
@@ -158,2 +183,4 @@ catch(e) { | ||
} | ||
check_clear() | ||
} | ||
@@ -165,4 +192,6 @@ }) | ||
self.execute = function( task ) { | ||
inflight++ | ||
if( task.gate ) { | ||
tr('gate',task.id,task.desc) | ||
tr('gate',gated,inflight,task.id,task.desc) | ||
gated = true | ||
@@ -172,6 +201,7 @@ q.push(task, task.cb) | ||
else if( gated && !task.ungate ) { | ||
tr('wait',task.id,task.desc) | ||
tr('wait',gated,inflight,task.id,task.desc) | ||
waiters.push( task ) | ||
} | ||
else { | ||
tr('run',gated,inflight,task.id,task.desc) | ||
work( task, task.cb ) | ||
@@ -178,0 +208,0 @@ } |
{ | ||
"name": "gate-executor", | ||
"version": "0.2.3", | ||
"version": "0.3.0", | ||
"description": "Execute functions that return via callback in order, but pause if a function is marked as a gate.", | ||
"main": "gate-executor.js", | ||
"scripts": { | ||
"test": "./test.sh", | ||
"cov": "lab -s -P test -r html > test/coverage.html", | ||
"test": "lab -v -P test -t 90", | ||
"build": "./build.sh" | ||
@@ -19,2 +20,5 @@ }, | ||
"author": "Richard Rodger (http://richardrodger.com)", | ||
"contributors": [ | ||
"Jacob Pruitt (http://javascriptjake.com)" | ||
], | ||
"license": "MIT", | ||
@@ -26,9 +30,10 @@ "bugs": { | ||
"dependencies": { | ||
"lodash": "2.4.2", | ||
"async": "0.9.2", | ||
"eraro": "0.4.1" | ||
"async": "1.5.2", | ||
"eraro": "0.4.1", | ||
"lodash": "4.0.0" | ||
}, | ||
"contributors": [ | ||
"Jacob Pruitt (http://javascriptjake.com)" | ||
] | ||
"devDependencies": { | ||
"code": "2.1.0", | ||
"lab": "8.2.0" | ||
} | ||
} |
# gate-executor | ||
[![npm version][npm-badge]][npm-url] | ||
[![Build Status][travis-badge]][travis-url] | ||
[![Coverage Status][coveralls-badge]][coveralls-url] | ||
[![Dependency Status][david-badge]][david-url] | ||
[![Gitter chat][gitter-badge]][gitter-url] | ||
#### Execute functions that return via callback in order, but pause if a function is marked as a gate. | ||
Current Version: 0.2.3 | ||
Tested on: Node 0.10, 0.11, 0.12, iojs. | ||
[](https://travis-ci.org/rjrodger/gate-executor) | ||
[Annotated Source](http://rjrodger.github.io/gate-executor/doc/gate-executor.html) | ||
@@ -31,5 +31,2 @@ | ||
[](https://gitter.im/rjrodger/gate-executor) | ||
# Usage | ||
@@ -81,1 +78,11 @@ | ||
[npm-badge]: https://badge.fury.io/js/gate-executor.svg | ||
[npm-url]: https://badge.fury.io/js/gate-executor | ||
[travis-badge]: https://api.travis-ci.org/rjrodger/gate-executor.svg | ||
[travis-url]: https://travis-ci.org/rjrodger/gate-executor | ||
[coveralls-badge]:https://coveralls.io/repos/rjrodger/gate-executor/badge.svg?branch=master&service=github | ||
[coveralls-url]: https://coveralls.io/github/rjrodger/gate-executor?branch=master | ||
[david-badge]: https://david-dm.org/rjrodger/gate-executor.svg | ||
[david-url]: https://david-dm.org/rjrodger/gate-executor | ||
[gitter-badge]: https://badges.gitter.im/rjrodger/gate-executor.svg | ||
[gitter-url]: https://gitter.im/rjrodger/gate-executor |
/* Copyright (c) 2014-2015 Richard Rodger, MIT License */ | ||
"use strict"; | ||
var util = require('util') | ||
// mocha gate-executor.test.js | ||
var Lab = require('lab') | ||
var Code = require('code') | ||
var util = require('util') | ||
var assert = require('assert') | ||
var lab = exports.lab = Lab.script() | ||
var describe = lab.describe | ||
var it = lab.it | ||
var expect = Code.expect | ||
var _ = require('lodash') | ||
var executor = require('..') | ||
// timerstub broken on node 0.11 | ||
// var timerstub = require('timerstub') | ||
// timerstub broken on node >0.10 | ||
//var timerstub = require('timerstub') | ||
@@ -28,7 +31,6 @@ var timerstub = { | ||
describe('executor', function(){ | ||
it('happy', function(fin) { | ||
if( ~process.version.indexOf('0.11.') ) return fin(); | ||
it('happy', function(done) { | ||
if( ~process.version.indexOf('0.11.') ) return done(); | ||
@@ -92,16 +94,16 @@ var e0 = executor({ | ||
timerstub.setTimeout( function(){ | ||
timerstub.setTimeout(function(){ | ||
//console.log( util.inspect(printlog).replace(/\s+/g,' ') ) | ||
assert.equal("[ 'a', 'ERROR: Error: gate-executor: B',"+ | ||
" 'cG', 'd', 'eG', 'fG', 'g', 'h',"+ | ||
" 'ERROR: Error: gate-executor: [TIMEOUT]', 'j', 'k' ]", | ||
util.inspect(printlog).replace(/\s+/g,' ')) | ||
expect(printlog).to.deep.equal([ 'a', 'ERROR: Error: gate-executor: B', | ||
'cG', 'd', 'eG', 'fG', 'g', 'h', | ||
'ERROR: Error: gate-executor: [TIMEOUT]', 'j', 'k' ]) | ||
},400) | ||
timerstub.wait(450,fin) | ||
timerstub.wait(450, done) | ||
}) | ||
it('no-callback',function(fin){ | ||
it('no-callback', function (done){ | ||
var e1 = executor({ | ||
@@ -117,4 +119,4 @@ trace:true, | ||
timerstub.wait(90,function(){ | ||
assert.ok(t1) | ||
fin() | ||
expect(t1).to.be.true() | ||
done() | ||
}) | ||
@@ -124,3 +126,3 @@ }) | ||
it('ignore-gate',function(fin){ | ||
it('ignore-gate', function (done){ | ||
var e1 = executor({ | ||
@@ -134,9 +136,9 @@ trace:true, | ||
e1.execute({id:'a', fn:function(done){ seq+='a';done() }}) | ||
e1.execute({id:'a',fn:function(done){seq+='a';done()}}) | ||
e1.execute({id:'b',gate:true,fn:function(done){ | ||
seq+='b' | ||
e1.execute({id:'b', gate: true, fn: function(done){ | ||
seq += 'b' | ||
e1.execute({id:'c',ungate:true,fn:function(done2){ | ||
seq+='c' | ||
e1.execute({id:'c', ungate:true, fn: function(done2){ | ||
seq += 'c' | ||
@@ -147,10 +149,9 @@ done2() | ||
e1.execute({id:'d',gate:true,fn:function(done3){ | ||
e1.execute({id: 'd', gate:true, fn:function(done3){ | ||
seq+='d' | ||
timerstub.setTimeout(done3,20) | ||
}}) | ||
}}) | ||
e1.execute({id:'e',fn:function(done){seq+='e';done()}}) | ||
e1.execute({id:'e',fn:function(done){ seq+='e';done()}}) | ||
@@ -160,7 +161,230 @@ timerstub.wait(40,function(){ | ||
assert.equal('abcde',seq) | ||
fin() | ||
expect(seq).to.equal('abcde') | ||
done() | ||
}) | ||
}) | ||
it('timeouts', function (fin) { | ||
var e1 = executor({ | ||
trace:true, | ||
timeout:100, | ||
stubs:timerstub | ||
}) | ||
var log = [] | ||
function mfn (id,t) { | ||
return function(done) { | ||
log.push(id) | ||
if( t ) { | ||
setTimeout(function(){done(null,id)},t) | ||
} | ||
else done(null,id) | ||
} | ||
} | ||
function mcb (id) { | ||
return function(err,out) { | ||
//console.log('c',id,err,out) | ||
log.push('c'+id+'~'+(err&&err.timeout)+'~'+out) | ||
} | ||
} | ||
var cI = 0 | ||
e1.on('clear', function () { | ||
cI++ | ||
log.push('c'+cI) | ||
//console.log(cI, e1.tracelog) | ||
//console.log(log) | ||
if( 2 === cI ) { | ||
//console.log(log) | ||
expect(log).to.deep.equal( | ||
[ 0, | ||
1, | ||
'c0~null~0', | ||
'c1~true~null', | ||
'c1', | ||
5, | ||
'c5~null~5', | ||
2, | ||
'c2~null~2', | ||
3, | ||
'c3~true~null', | ||
6, | ||
'c6~null~6', | ||
4, | ||
'c4~null~4', | ||
7, | ||
'c7~null~7', | ||
'c2' ] | ||
) | ||
fin() | ||
} | ||
}) | ||
// seq: 0,1 | ||
e1.execute({id:0,fn:mfn(0,50),cb:mcb(0)}) | ||
e1.execute({id:1,fn:mfn(1,200),cb:mcb(1)}) | ||
setTimeout( function() { | ||
// seq: 5,2,3,6,4,7 | ||
e1.execute({id:2,gate:true,fn:mfn(2,10),cb:mcb(2)}) | ||
e1.execute({id:3,gate:true,fn:mfn(3,200),cb:mcb(3)}) | ||
e1.execute({id:4,fn:mfn(4),cb:mcb(4)}) | ||
e1.execute({id:5,ungate:true,fn:mfn(5),cb:mcb(5)}) | ||
e1.execute({id:6,gate:true,fn:mfn(6,10),cb:mcb(6)}) | ||
e1.execute({id:7,fn:mfn(7),cb:mcb(7,10)}) | ||
}, 200) | ||
}) | ||
it('determinism', function (fin) { | ||
var e1 = executor({ | ||
trace:true, | ||
timeout:100, | ||
stubs:timerstub | ||
}) | ||
var log = [] | ||
function mfn (id,t) { | ||
return function(done) { | ||
log.push(id) | ||
if( t ) { | ||
setTimeout(done,t) | ||
} | ||
else done() | ||
} | ||
} | ||
var cI = 0 | ||
e1.on('clear', function () { | ||
cI++ | ||
log.push('c'+cI) | ||
//console.log(cI, e1.tracelog) | ||
if( 4 === cI ) { | ||
//console.log(log) | ||
expect(log).to.deep.equal( | ||
[ 0, 1, 'c1', 2, 3, 'c2', 4, 6, 5, 'c3', 9, 7, 10, 8, 'c4' ] | ||
) | ||
fin() | ||
} | ||
}) | ||
// seq: 0,1 | ||
e1.execute({id:0,fn:mfn(0)}) | ||
e1.execute({id:1,fn:mfn(1)}) | ||
setTimeout( function() { | ||
// seq: 2,3 | ||
e1.execute({id:2,fn:mfn(2,40)}) | ||
e1.execute({id:3,fn:mfn(3,20)}) | ||
setTimeout( function() { | ||
// seq: 4,6,5 | ||
e1.execute({id:4,gate:true,fn:mfn(4)}) | ||
e1.execute({id:5,fn:mfn(5)}) | ||
e1.execute({id:6,gate:true,fn:mfn(6)}) | ||
setTimeout( function() { | ||
// seq: 9,7,10,8 | ||
e1.execute({id:7,gate:true,fn:mfn(7)}) | ||
e1.execute({id:8,fn:mfn(8)}) | ||
e1.execute({id:9,ungate:true,fn:mfn(9)}) | ||
e1.execute({id:10,gate:true,fn:mfn(10)}) | ||
},100) | ||
},100) | ||
},100) | ||
}) | ||
it('errors', function (fin) { | ||
var e1 = executor({ | ||
trace:true, | ||
timeout:100, | ||
stubs:timerstub | ||
}) | ||
var log = [] | ||
e1.on('error',function(err) { | ||
log.push('EE~'+err.message) | ||
}) | ||
var MODE = { | ||
ok:0, | ||
throw:1, | ||
cberr:2 | ||
} | ||
function mfn (mode,id,t) { | ||
return function(done) { | ||
log.push(id) | ||
if( MODE.throw === mode ) { | ||
throw new Error('AAA') | ||
} | ||
var err = MODE.cberr === mode ? new Error('BBB') : null | ||
if( t ) { | ||
setTimeout(function(){done(err,id)},t) | ||
} | ||
else done(err,id) | ||
} | ||
} | ||
function mcb (mode,id) { | ||
return function(err,out) { | ||
//console.log('c',id,err,out) | ||
log.push('c'+id+'~'+(err&&err.message)+'~'+out) | ||
if( MODE.throw === mode ) throw new Error('CCC') | ||
} | ||
} | ||
var cI = 0 | ||
e1.on('clear', function () { | ||
cI++ | ||
log.push('c'+cI) | ||
//console.log(cI, e1.tracelog) | ||
//console.log(log) | ||
if( 1 === cI ) { | ||
//console.log(log) | ||
expect(log).to.deep.equal( | ||
[ 0, | ||
'c0~null~0', | ||
1, | ||
'c1~gate-executor: AAA~null', | ||
2, | ||
'c2~gate-executor: BBB~2', | ||
3, | ||
'c3~null~3', | ||
'EE~gate-executor: CCC', | ||
'c1' ] | ||
) | ||
fin() | ||
} | ||
}) | ||
// seq: 0,1 | ||
e1.execute({id:0,fn:mfn(MODE.ok,0),cb:mcb(MODE.ok,0)}) | ||
e1.execute({id:1,fn:mfn(MODE.throw,1),cb:mcb(MODE.ok,1)}) | ||
e1.execute({id:2,fn:mfn(MODE.cberr,2),cb:mcb(MODE.ok,2)}) | ||
e1.execute({id:3,fn:mfn(MODE.ok,3),cb:mcb(MODE.throw,3)}) | ||
}) | ||
}) |
Sorry, the diff of this file is not supported yet
571708
1198
87
2
+ Addedasync@1.5.2(transitive)
+ Addedlodash@4.0.0(transitive)
- Removedasync@0.9.2(transitive)
Updatedasync@1.5.2
Updatedlodash@4.0.0