@nteract/fs-kernels
Version:
A manager for the filesystem aspects of Juyter kernels
94 lines (93 loc) • 3.62 kB
JavaScript
;
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;