batch-cluster
Advanced tools
Comparing version 5.0.1 to 5.1.0
@@ -20,2 +20,8 @@ # Changelog | ||
## v5.1.0 | ||
- ✨ `ChildProcessFactory` supports thunks that return either a `ChildProcess` or | ||
`Promise<ChildProcess>` | ||
- 📦 Update deps | ||
## v5.0.1 | ||
@@ -22,0 +28,0 @@ |
@@ -11,3 +11,3 @@ export declare function delay(millis: number, unref?: boolean): Promise<void>; | ||
*/ | ||
export declare function serial<T>(f: () => Promise<T>): (() => Promise<T | undefined>); | ||
export declare function serial<T>(f: () => Promise<T>): () => Promise<T | undefined>; | ||
/** | ||
@@ -14,0 +14,0 @@ * Return a thunk that will call the underlying thunk at most every `minDelayMs` |
@@ -23,3 +23,3 @@ /// <reference types="node" /> | ||
*/ | ||
readonly processFactory: () => ChildProcess; | ||
readonly processFactory: () => ChildProcess | Promise<ChildProcess>; | ||
} | ||
@@ -26,0 +26,0 @@ /** |
@@ -100,48 +100,56 @@ "use strict"; | ||
_this.onIdle = Async_1.serial(function () { return __awaiter(_this, void 0, void 0, function () { | ||
var minStart, readyProcs, execNextTask, proc_1; | ||
var minStart, readyProcs, execNextTask, proc_1, _a; | ||
var _this = this; | ||
return __generator(this, function (_a) { | ||
if (this._ended) | ||
return [2 /*return*/]; | ||
minStart = Date.now() - this.opts.maxProcAgeMillis; | ||
Array_1.filterInPlace(this._procs, function (proc) { | ||
var old = proc.start < minStart && _this.opts.maxProcAgeMillis > 0; | ||
var worn = proc.taskCount >= _this.opts.maxTasksPerProcess; | ||
var broken = proc.exited; | ||
if (proc.idle && (old || worn || broken)) { | ||
proc.end(true, old ? "old" : worn ? "worn" : "broken"); | ||
return false; | ||
} | ||
else { | ||
return true; | ||
} | ||
}); | ||
readyProcs = this._procs.filter(function (proc) { return proc.ready; }); | ||
execNextTask = function () { | ||
var idleProc = readyProcs.shift(); | ||
if (idleProc == null) | ||
return; | ||
var task = _this.tasks.shift(); | ||
if (task == null) | ||
return; | ||
if (!idleProc.execTask(task)) { | ||
Logger_1.logger().warn("BatchCluster.onIdle(): execTask for " + | ||
task.command + | ||
" to pid " + | ||
idleProc.pid + | ||
" returned false, re-enqueing."); | ||
_this.enqueueTask(task); | ||
} | ||
return true; | ||
}; | ||
while (!this._ended && execNextTask()) { } | ||
if (!this._ended && | ||
this.tasks.length > 0 && | ||
this._procs.length < this.opts.maxProcs) { | ||
proc_1 = new BatchProcess_1.BatchProcess(this.opts.processFactory(), this.opts, this.observer); | ||
proc_1.exitedPromise.then(function () { return _this._tasksPerProc.push(proc_1.taskCount); }); | ||
this._procs.push(proc_1); | ||
this._spawnedProcs++; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
if (this._ended) | ||
return [2 /*return*/]; | ||
minStart = Date.now() - this.opts.maxProcAgeMillis; | ||
Array_1.filterInPlace(this._procs, function (proc) { | ||
var old = proc.start < minStart && _this.opts.maxProcAgeMillis > 0; | ||
var worn = proc.taskCount >= _this.opts.maxTasksPerProcess; | ||
var broken = proc.exited; | ||
if (proc.idle && (old || worn || broken)) { | ||
proc.end(true, old ? "old" : worn ? "worn" : "broken"); | ||
return false; | ||
} | ||
else { | ||
return true; | ||
} | ||
}); | ||
readyProcs = this._procs.filter(function (proc) { return proc.ready; }); | ||
execNextTask = function () { | ||
var idleProc = readyProcs.shift(); | ||
if (idleProc == null) | ||
return; | ||
var task = _this.tasks.shift(); | ||
if (task == null) | ||
return; | ||
if (!idleProc.execTask(task)) { | ||
Logger_1.logger().warn("BatchCluster.onIdle(): execTask for " + | ||
task.command + | ||
" to pid " + | ||
idleProc.pid + | ||
" returned false, re-enqueing."); | ||
_this.enqueueTask(task); | ||
} | ||
return true; | ||
}; | ||
while (!this._ended && execNextTask()) { } | ||
if (!(!this._ended && | ||
this.tasks.length > 0 && | ||
this._procs.length < this.opts.maxProcs)) return [3 /*break*/, 2]; | ||
_a = BatchProcess_1.BatchProcess.bind; | ||
return [4 /*yield*/, this.opts.processFactory()]; | ||
case 1: | ||
proc_1 = new (_a.apply(BatchProcess_1.BatchProcess, [void 0, _b.sent(), | ||
this.opts, | ||
this.observer]))(); | ||
proc_1.exitedPromise.then(function () { return _this._tasksPerProc.push(proc_1.taskCount); }); | ||
this._procs.push(proc_1); | ||
this._spawnedProcs++; | ||
_b.label = 2; | ||
case 2: return [2 /*return*/]; | ||
} | ||
return [2 /*return*/]; | ||
}); | ||
@@ -148,0 +156,0 @@ }); }); |
@@ -75,7 +75,13 @@ "use strict"; | ||
this.proc.on("disconnect", function () { return _this.onExit("disconnect"); }); | ||
this.proc.stdin.on("error", function (err) { return _this.onError("stdin.error", err); }); | ||
this.proc.stdout.on("error", function (err) { return _this.onError("stdout.error", err); }); | ||
this.proc.stdout.on("data", function (d) { return _this.onStdout(d); }); | ||
this.proc.stderr.on("error", function (err) { return _this.onError("stderr.error", err); }); | ||
this.proc.stderr.on("data", function (err) { return _this.onStderr(err); }); | ||
Object_1.map(this.proc.stdin, function (stdin) { | ||
stdin.on("error", function (err) { return _this.onError("stdin.error", err); }); | ||
}); | ||
Object_1.map(this.proc.stdout, function (stdout) { | ||
stdout.on("error", function (err) { return _this.onError("stdout.error", err); }); | ||
stdout.on("data", function (d) { return _this.onStdout(d); }); | ||
}); | ||
Object_1.map(this.proc.stderr, function (stderr) { | ||
stderr.on("error", function (err) { return _this.onError("stderr.error", err); }); | ||
stderr.on("data", function (err) { return _this.onStderr(err); }); | ||
}); | ||
this.startupTask = new Task_1.Task(opts.versionCommand, function (ea) { return ea; }); | ||
@@ -203,2 +209,3 @@ this.startupTask.promise | ||
BatchCluster_1.logger().trace(this.name + ".execTask(): starting", { cmd: cmd }); | ||
// If this is null, we've got bigger problems: | ||
this.proc.stdin.write(cmd); | ||
@@ -225,3 +232,3 @@ return true; | ||
cmd = Object_1.map(this.opts.exitCommand, function (ea) { return String_1.ensureSuffix(ea, "\n"); }); | ||
if (!this.proc.stdin.writable) return [3 /*break*/, 2]; | ||
if (!(this.proc.stdin && this.proc.stdin.writable)) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, Stream_1.end(this.proc.stdin, cmd)]; | ||
@@ -246,5 +253,5 @@ case 1: | ||
Error_1.tryEach([ | ||
function () { return _this.proc.stdin.end(); }, | ||
function () { return _this.proc.stdout.destroy(); }, | ||
function () { return _this.proc.stderr.destroy(); }, | ||
function () { return Object_1.map(_this.proc.stdin, function (ea) { return ea.end(); }); }, | ||
function () { return Object_1.map(_this.proc.stdout, function (ea) { return ea.destroy(); }); }, | ||
function () { return Object_1.map(_this.proc.stderr, function (ea) { return ea.destroy(); }); }, | ||
function () { return _this.proc.disconnect(); } | ||
@@ -251,0 +258,0 @@ ]); |
{ | ||
"name": "batch-cluster", | ||
"version": "5.0.1", | ||
"version": "5.1.0", | ||
"description": "Manage a cluster of child processes", | ||
@@ -22,4 +22,8 @@ "main": "dist/BatchCluster.js", | ||
"test": "mocha --opts .mocha.opts", | ||
"predocs": "typedoc --options ./.typedoc.js", | ||
"docs": "echo batch-cluster.js.org > ./docs/CNAME && touch ./docs/.nojekyll && yarn serve docs" | ||
"docs:1": "typedoc --options .typedoc.js", | ||
"docs:2": "echo batch-cluster.js.org > docs/CNAME", | ||
"docs:3": "cp .serve.json docs/serve.json", | ||
"docs:4": "touch docs/.nojekyll", | ||
"docs:5": "yarn serve docs", | ||
"docs": "bash -c 'for i in {1..5} ; do yarn docs:$i ; done'" | ||
}, | ||
@@ -35,4 +39,4 @@ "author": "Matthew McEachen <matthew-batchcluster@mceachen.org>", | ||
"@types/chai-string": "^1.4.1", | ||
"@types/mocha": "^5.2.5", | ||
"@types/node": "^10.12.10", | ||
"@types/mocha": "^5.2.6", | ||
"@types/node": "^11.10.1", | ||
"chai": "^4.2.0", | ||
@@ -42,13 +46,13 @@ "chai-as-promised": "^7.1.1", | ||
"chai-withintoleranceof": "^1.0.1", | ||
"mocha": "^5.2.0", | ||
"prettier": "^1.15.2", | ||
"rimraf": "^2.6.2", | ||
"mocha": "^6.0.2", | ||
"prettier": "^1.16.4", | ||
"rimraf": "^2.6.3", | ||
"seedrandom": "^2.4.4", | ||
"serve": "^10.1.1", | ||
"source-map-support": "^0.5.9", | ||
"serve": "^10.1.2", | ||
"source-map-support": "^0.5.10", | ||
"timekeeper": "^2.1.2", | ||
"typedoc": "^0.13.0", | ||
"typescript": "^3.2.1", | ||
"wtfnode": "^0.7.3" | ||
"typedoc": "^0.14.2", | ||
"typescript": "^3.3.3333", | ||
"wtfnode": "^0.8.0" | ||
} | ||
} |
@@ -5,5 +5,8 @@ # batch-cluster | ||
[](https://badge.fury.io/js/batch-cluster) | ||
[](https://www.npmjs.com/package/batch-cluster) | ||
[](https://travis-ci.org/mceachen/batch-cluster.js) | ||
[](https://ci.appveyor.com/project/mceachen/batch-cluster-js/branch/master) | ||
[](https://github.com/mceachen/batch-cluster.js/issues) | ||
[](https://lgtm.com/projects/g/mceachen/batch-cluster.js/context:javascript) | ||
[](https://snyk.io/test/github/mceachen/batch-cluster.js?targetFile=package.json) | ||
@@ -10,0 +13,0 @@ Many command line tools, like |
2146
81
147970
47