-
Notifications
You must be signed in to change notification settings - Fork 52
Expand file tree
/
Copy pathutils.js
More file actions
95 lines (80 loc) · 2.81 KB
/
utils.js
File metadata and controls
95 lines (80 loc) · 2.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
var Promise = require('bluebird');
var execSh = require('exec-sh');
var colors = require('colors');
var async = require('async');
var _ = require('lodash');
var colors = require('colors');
// Allow to cancel bluebird promises
Promise.config({
cancellation: true
});
// Execute command as cancellable promise
function exec(task, finish) {
task.promise = new Promise(function(resolve, reject, onCancel) {
var process = execSh(task.cmd, {}, function(err, stdout, stderr) {
// Avoid issues with killing exited process
process = undefined;
// No need to reject/resolve if promise was cancelled and process was killed
if (task.promise.isCancelled()) {
return;
}
if (err) {
// Error code !== 0
console.log(('Error code: ' + err.code + ' for run #' + task.number).red);
reject(err, stdout, stderr);
}
else {
console.log(('Finished run #' + task.number).green);
resolve();
}
});
onCancel(function () {
console.log(('Cancelled run #' + task.number).yellow);
if (process) {
console.log(('Killing run #' + task.number).yellow);
// XXX: should we send SIGKILL or account for sub-processes somehow
// or is it really as simple as this
process.kill();
}
});
});
task.promise.finally(function () {
// Tell the queue that we're finished
finish();
});
}
// Create runner based on specified concurrency model
function runner(concurrencyModel) {
// async.queue does not support unlimited concurrent tasks.
// Set sane (?) default - 100 tasks for parallel mode
var concurrency = ('parallel' === concurrencyModel) ? 100 : 1;
// Create worker queue
var queue = async.queue(exec, concurrency);
var taskNumber = 1;
var run = function (cmd) {
// In queue mode: we don't want to queue more than one
// extra task to be run after filesystem stops changing
if ('queue' === concurrencyModel && queue.length()) {
console.log(('Command is already queued, skipping').blue);
return;
}
// In kill mode: cancel running task before pushing new one
if ('kill' === concurrencyModel && queue.running()) {
_.each(queue.workersList(), function (worker) {
worker.data.promise.cancel();
});
}
console.log(('Adding task #' + taskNumber + ' to the queue').inverse);
queue.push({
cmd: cmd,
number: taskNumber++
});
};
// Return new runner with run method
return {
run: run
};
}
module.exports = {
runner: runner
};