Ver Fonte

Backport PR #11952: Fix for kernel reconnect (#11987)

Co-authored-by: Piyush Jain <pyjain@gmail.com>
MeeseeksMachine há 3 anos atrás
pai
commit
843120368a

+ 1 - 1
packages/apputils/src/sessioncontext.tsx

@@ -28,7 +28,7 @@ import { Dialog, showDialog } from './dialog';
  * #### Notes
  * The current session connection is `.session`, the current session's kernel
  * connection is `.session.kernel`. For convenience, we proxy several kernel
- * connection and and session connection signals up to the session context so
+ * connection and session connection signals up to the session context so
  * that you do not have to manage slots as sessions and kernels change. For
  * example, to act on whatever the current kernel's iopubMessage signal is
  * producing, connect to the session context `.iopubMessage` signal.

+ 34 - 12
packages/services/src/kernel/default.ts

@@ -1262,17 +1262,10 @@ export class KernelConnection implements Kernel.IKernelConnection {
 
     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) {
+    const getKernelModel = async (evt: Event) => {
+      if (this._isDisposed) {
         return;
       }
-      alreadyCalledOnclose = true;
       this._reason = '';
       this._model = undefined;
       try {
@@ -1283,13 +1276,42 @@ export class KernelConnection implements Kernel.IKernelConnection {
         } else {
           this._onWSClose(evt);
         }
-      } catch (e) {
-        this._reason = 'Kernel died unexpectedly';
-        this._updateStatus('dead');
+      } catch (err) {
+        // Try again, if there is a network failure
+        // Handle network errors, as well as cases where we are on a
+        // JupyterHub and the server is not running. JupyterHub returns a
+        // 503 (<2.0) or 424 (>2.0) in that case.
+        if (
+          err instanceof ServerConnection.NetworkError ||
+          err.response?.status === 503 ||
+          err.response?.status === 424
+        ) {
+          const timeout = Private.getRandomIntInclusive(10, 30) * 1e3;
+          setTimeout(getKernelModel, timeout, evt);
+        } else {
+          this._reason = 'Kernel died unexpectedly';
+          this._updateStatus('dead');
+        }
       }
       return;
     };
 
+    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;
+      await getKernelModel(evt);
+
+      return;
+    };
+
     this._ws.onmessage = this._onWSMessage;
     this._ws.onopen = this._onWSOpen;
     this._ws.onclose = earlyClose;