|
@@ -119,10 +119,13 @@ export class KernelConnection implements Kernel.IKernelConnection {
|
|
|
* The kernel model
|
|
|
*/
|
|
|
get model(): Kernel.IModel {
|
|
|
- return {
|
|
|
- id: this.id,
|
|
|
- name: this.name
|
|
|
- };
|
|
|
+ return (
|
|
|
+ this._model || {
|
|
|
+ id: this.id,
|
|
|
+ name: this.name,
|
|
|
+ reason: this._reason
|
|
|
+ }
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1257,10 +1260,40 @@ export class KernelConnection implements Kernel.IKernelConnection {
|
|
|
// Ensure incoming binary messages are not Blobs
|
|
|
this._ws.binaryType = 'arraybuffer';
|
|
|
|
|
|
+ let alreadyCalledOnclose = false;
|
|
|
+
|
|
|
+ const earlyClose = async (evt: Event) => {
|
|
|
+ // If the websocket was closed early, that could mean
|
|
|
+ // that the kernel is actually dead. Try getting
|
|
|
+ // information about the kernel from the API call --
|
|
|
+ // if that fails, then assume the kernel is dead,
|
|
|
+ // otherwise just follow the typical websocket closed
|
|
|
+ // protocol.
|
|
|
+ if (alreadyCalledOnclose) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ alreadyCalledOnclose = true;
|
|
|
+ this._reason = '';
|
|
|
+ this._model = undefined;
|
|
|
+ try {
|
|
|
+ const model = await restapi.getKernelModel(this._id, settings);
|
|
|
+ this._model = model;
|
|
|
+ if (model?.execution_state === 'dead') {
|
|
|
+ this._updateStatus('dead');
|
|
|
+ } else {
|
|
|
+ this._onWSClose(evt);
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ this._reason = 'Kernel died unexpectedly';
|
|
|
+ this._updateStatus('dead');
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ };
|
|
|
+
|
|
|
this._ws.onmessage = this._onWSMessage;
|
|
|
this._ws.onopen = this._onWSOpen;
|
|
|
- this._ws.onclose = this._onWSClose;
|
|
|
- this._ws.onerror = this._onWSClose;
|
|
|
+ this._ws.onclose = earlyClose;
|
|
|
+ this._ws.onerror = earlyClose;
|
|
|
};
|
|
|
|
|
|
/**
|
|
@@ -1469,6 +1502,8 @@ export class KernelConnection implements Kernel.IKernelConnection {
|
|
|
* Handle a websocket open event.
|
|
|
*/
|
|
|
private _onWSOpen = (evt: Event) => {
|
|
|
+ this._ws!.onclose = this._onWSClose;
|
|
|
+ this._ws!.onerror = this._onWSClose;
|
|
|
this._updateConnectionStatus('connected');
|
|
|
};
|
|
|
|
|
@@ -1513,7 +1548,7 @@ export class KernelConnection implements Kernel.IKernelConnection {
|
|
|
/**
|
|
|
* Handle a websocket close event.
|
|
|
*/
|
|
|
- private _onWSClose = (evt: CloseEvent) => {
|
|
|
+ private _onWSClose = (evt: Event) => {
|
|
|
if (!this.isDisposed) {
|
|
|
this._reconnect();
|
|
|
}
|
|
@@ -1529,6 +1564,7 @@ export class KernelConnection implements Kernel.IKernelConnection {
|
|
|
|
|
|
private _id = '';
|
|
|
private _name = '';
|
|
|
+ private _model: Kernel.IModel | undefined;
|
|
|
private _status: KernelMessage.Status = 'unknown';
|
|
|
private _connectionStatus: Kernel.ConnectionStatus = 'connecting';
|
|
|
private _kernelSession = '';
|
|
@@ -1573,6 +1609,7 @@ export class KernelConnection implements Kernel.IKernelConnection {
|
|
|
private _msgIdToDisplayIds = new Map<string, string[]>();
|
|
|
private _msgChain: Promise<void> = Promise.resolve();
|
|
|
private _hasPendingInput = false;
|
|
|
+ private _reason = '';
|
|
|
private _noOp = () => {
|
|
|
/* no-op */
|
|
|
};
|