UNPKG

domotz-remote-pawn

Version:

Domotz Agent

136 lines (117 loc) 4.41 kB
/** This file is part of Domotz Agent. * Copyright (C) 2016 Domotz Ltd * * Domotz Agent is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Domotz Agent is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Domotz Agent. If not, see <http://www.gnu.org/licenses/>. **/ /** * Created by Tommaso Latini <tommaso@domotz.com> on 20/09/16. */ const PROMISE = 0; const COMMAND = 1; const ARGS = 2; const OPTIONS = 3; module.exports = function(index, childProcess) { var name = 'EXECUTOR - (' + index + '):', queue = [], current = null; function getCmdForLog(command, args, options) { return command + (args ? ' ' + args.join(' ') + '' : '') + (options ? '. Options: ' + JSON.stringify(options) : ''); } function resolve(deferred, response, id) { deferred.resolve(response); clearTimeout(id); dequeue(); } function reject(deferred, error, id) { deferred.reject(error); clearTimeout(id); dequeue(); } function enqueue(task) { console.silly(name + ' Enqueue'); queue.push(task); if (!current) { dequeue(); } } function dequeue() { console.silly(name + ' Dequeue'); current = queue.shift(); if (!current) { console.debug(name + ' Empty queue.'); return; } var deferred = current[PROMISE], command = current[COMMAND], args = current[ARGS], options = current[OPTIONS], timeout = options ? options.timeout || options.ttl : null, id = null, err = null, stdout = '', stderr = '', descr = getCmdForLog(command, args, options), child = childProcess.spawn(command, args, options); console.info('%s $> %s', name, descr); if (timeout) { console.debug('%s Set timeout to %s. Spawned child pid: %s. Path: %s', name, timeout, child.pid, process.env.PATH); id = setTimeout(function () { console.verbose('Timeout expired for process: %d', child.pid); child.kill(); err = new Error(name + ' - Process "' + descr + '" killed after timeout: ' + timeout); reject(deferred, err, id); }, timeout); } else { console.debug('%s Spawned child pid: %s. Path: %s', name, child.pid, process.env.PATH); } child.stdout.on('data', function (data) { stdout += data; }); child.stderr.on('data', function (data) { stderr += data; }); child.on('error', function (err) { console.warn(name + ' Process "' + descr + '" exited with unexpected error'); reject(deferred, err, id); }); child.on('close', function (code) { console.verbose(name + ' Process "' + descr + '" terminates with code: ' + code); console.silly('STDOUT: ' + stdout); console.silly('STDERR: ' + stderr); if (code !== 0) { console.alert(name + ' Process "' + descr + '" exited with code: ' + code); err = new Error(code); } else if (stderr && !stdout) { var msg = stderr.toString('utf8').trim(); console.alert(name + ' Process "' + descr + '" ' + msg); err = new Error(msg); } if (err) { reject(deferred, err, id); } else { resolve(deferred, stdout.toString('utf8').trim(), id); } }); } function status() { var length = queue.length; return current ? length + 1 : length; } this.enqueue = enqueue; this.dequeue = dequeue; this.status = status; };