Async/await let's go!

This commit is contained in:
Zaid Abdulla committed 2019-06-05 00:17:36 -07:00
1 parent 1e6d3acd1b
commit c3501debd5
20 files changed
+2617 -2916

No files matched your search

+70 -65
View File
@@ -17,92 +17,97 @@
* along with GenieACS. If not, see <http://www.gnu.org/licenses/>.
*/
import { spawn } from "child_process";
import { spawn, ChildProcess } from "child_process";
import * as crypto from "crypto";
import * as config from "./config";
import { Fault } from "./types";
const TIMEOUT = +config.get("EXT_TIMEOUT");
const processes = {};
const processes: { [script: string]: ChildProcess } = {};
const jobs = new Map();
function messageHandler(message): void {
const func = jobs.get(message[0]);
if (func) {
jobs.delete(message[0]);
func(null, message[1], message[2]);
func({ fault: message[1], value: message[2] });
}
}
export function run(args, callback): boolean {
const scriptName = args[0];
export function run(args): Promise<{ fault: Fault; value: any }> {
return new Promise(resolve => {
const scriptName = args[0];
const id = crypto.randomBytes(8).toString("hex");
jobs.set(id, callback);
const id = crypto.randomBytes(8).toString("hex");
jobs.set(id, resolve);
if (!processes[scriptName]) {
const p = spawn("bin/genieacs-ext", [scriptName], {
stdio: ["inherit", "inherit", "inherit", "ipc"]
});
processes[scriptName] = p;
if (!processes[scriptName]) {
const p = spawn("bin/genieacs-ext", [scriptName], {
stdio: ["inherit", "inherit", "inherit", "ipc"]
});
processes[scriptName] = p;
p.on("error", err => {
if (processes[scriptName] === p) {
if (jobs.delete(id))
callback(null, { code: err.name, message: err.message });
p.on("error", err => {
if (processes[scriptName] === p) {
if (jobs.delete(id)) {
resolve({
fault: { code: err.name, message: err.message },
value: null
});
}
kill(processes[scriptName]);
delete processes[scriptName];
}
});
kill(processes[scriptName]);
delete processes[scriptName];
}
});
p.on("disconnect", () => {
if (processes[scriptName] === p) {
kill(processes[scriptName]);
delete processes[scriptName];
}
});
p.on("disconnect", () => {
if (processes[scriptName] === p) delete processes[scriptName];
});
p.on("message", messageHandler);
}
setTimeout(() => {
if (jobs.delete(id))
callback(null, { code: "timeout", message: "Extension timed out" });
}, TIMEOUT);
if (!processes[scriptName].connected) return false;
return processes[scriptName].send([id, args.slice(1)]);
}
function kill(process, callback?: () => void): void {
if (process.signalCode !== null || process.exitCode !== null) return;
const timeToKill = Date.now() + 5000;
process.kill();
const t = setInterval(() => {
if (process.signalCode !== null || process.exitCode !== null) {
clearInterval(t);
if (callback) callback();
} else if (Date.now() > timeToKill) {
process.kill("SIGKILL");
clearInterval(t);
if (callback) callback();
p.on("message", messageHandler);
}
}, 100);
setTimeout(() => {
if (jobs.delete(id)) {
resolve({
fault: { code: "timeout", message: "Extension timed out" },
value: null
});
}
}, TIMEOUT);
if (!processes[scriptName].connected) return false;
return processes[scriptName].send([id, args.slice(1)]);
});
}
export function killAll(callback?): void {
let counter = 1;
for (const n in processes) {
++counter;
kill(processes[n], () => {
if (--counter === 0 && callback) callback();
});
delete processes[n];
}
if (--counter === 0 && callback) callback();
function kill(process: ChildProcess): Promise<void> {
return new Promise(resolve => {
const timeToKill = Date.now() + 5000;
process.kill();
const t = setInterval(() => {
if (!process.connected) {
clearInterval(t);
resolve();
} else if (Date.now() > timeToKill) {
process.kill("SIGKILL");
clearInterval(t);
resolve();
}
}, 100);
});
}
export async function killAll(): Promise<void> {
await Promise.all(
Object.entries(processes).map(([k, p]) => {
delete processes[k];
return kill(p);
})
);
}