UNPKG

@nteract/fs-kernels

Version:

A manager for the filesystem aspects of Juyter kernels

94 lines (93 loc) 3.62 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const pidusage_1 = __importDefault(require("pidusage")); const rxjs_1 = require("rxjs"); const operators_1 = require("rxjs/operators"); const messaging_1 = require("@nteract/messaging"); const spawnteract_1 = require("./spawnteract"); class Kernel { constructor(launchedKernel) { this.process = launchedKernel.spawn; this.connectionInfo = launchedKernel.config; this.kernelSpec = launchedKernel.kernelSpec; this.connectionFile = launchedKernel.connectionFile; this.channels = launchedKernel.channels; } shutdownEpic(timeoutMs = 2000) { const request = messaging_1.shutdownRequest({ restart: false }); // Try to make a shutdown request // If we don't get a response within X time, force a shutdown // Either way do the same cleanup const shutDownHandling = this.channels.pipe( /* Get the first response to our message request. */ messaging_1.childOf(request), messaging_1.ofMessageType("shutdown_reply"), operators_1.first(), // If we got a reply, great! :) operators_1.map((msg) => { return { status: "shutting down", content: msg.content }; }), /** * If we don't get a response within timeoutMs, then throw an error. */ operators_1.timeout(timeoutMs), operators_1.catchError(err => rxjs_1.of({ error: err, status: "error" })), /** * Even if we don't receive a shutdown_reply from the kernel to our * shutdown_request, we will go forward with cleaning up the RxJS * subject and killing the kernel process. */ operators_1.mergeMap(async (event) => { // End all communication on the channels this.channels.complete(); await this.shutdownProcess(); const finalResponse = { status: "shutdown" }; if (event.status === "error") { finalResponse.error = event.error; finalResponse.status = "error"; } return rxjs_1.of(finalResponse); }), operators_1.catchError(err => // Catch all, in case there were other errors here rxjs_1.of({ error: err, status: "error" }))); // On subscription, send the message return rxjs_1.Observable.create((observer) => { const subscription = shutDownHandling.subscribe(observer); this.channels.next(request); return subscription; }); } async shutdownProcess() { spawnteract_1.cleanup(this.connectionFile); if (!this.process.killed && this.process.pid) { process.kill(this.process.pid); } this.process.removeAllListeners(); } async shutdown(timeoutMs = 2000) { const observable = this.shutdownEpic(timeoutMs); return observable.toPromise(); } async getUsage() { return await pidusage_1.default(this.process.pid); } } exports.Kernel = Kernel; async function launchKernel(input) { let launchedKernel; if (typeof input === "string") { launchedKernel = await spawnteract_1.launch(input); } else { launchedKernel = await spawnteract_1.launchSpec(input); } return new Kernel(launchedKernel); } exports.launchKernel = launchKernel;