Stopping Lumino Poll when JupyterLab server stops

Hello,

JupyterLab frontend packages and few community extensions use Lumino Poll to update the state. When a JupyterLab server stops and the users do not close the browser tab, the Poll does not stop and keeps ticking. I noticed that Poll has standby mode which kicks in when browser tab is not active. However, if the browser tab is active and server is not running, the Poll does not go into standby mode. Is there any “workaround” to put the Poll in standby mode when server is not running anymore?

This is relevant in JupyterHub deployments where a “active” browser tab of a terminated server keeps making API requests due to Polls which pollute the JupyterHub logs with a lot of 4xx messages. Any thoughts @jtp @krassowski ?

Seems like we can use IINFO.isConnected to put the polling in standby mode. That should do the job!!

1 Like

Just linking the PR which introduced it if someone finds it in the future and would like an example: Add `isConnected` to `ServiceManager`, use it in `hub-extension` by vkaidalov-rft · Pull Request #10156 · jupyterlab/jupyterlab · GitHub

1 Like

Cheers @krassowski for the PR link.

I noticed something else. Actually none of the polls that are used by different components are really taking advantage of info.isConnected. So, ServiceManager is managing all other managers like TerminalManager, KernelManager, etc,. Some of these managers have polling enabled. A “default” instance of ServiceManager is being during app launch where the standby is set to default when-hidden. So, even when the server is stopped most of these API requests are being made due to active poll. Do you think we should create an instance of ServiceManager by taking IInfo.isConnected into account?

Normally the Poll has a frequency.backoff option which should also help increase the time between requests: lumino/packages/polling/src/index.ts at 20cf366a88028ca763eb80241bd1226c936f454e · jupyterlab/lumino · GitHub

Since Allow customizing the `ServiceManager` with plugins by jtpio · Pull Request #16794 · jupyterlab/jupyterlab · GitHub, a different ServiceManager can be provided via a plugin, so it could be worth exploring.

Cheers @jtp for the pointers.

Actually I was looking at the wrong source code but my initial observations were still true. So, in services-extension, different component managers (like sessions, terminals, kernels,…) are being instantiated without standby callback and eventually ServiceManager with standy callback is being instantiated with the previously created instances of component managers. As the component managers are already instantiated, the passed standby callback is never used in component managers. A straight-forward fix is to use standby callback in all the component managers which should put all polls in standby when connection is lost. For instance, in the place of

const kernelManagerPlugin: ServiceManagerPlugin<Kernel.IManager> = {
  id: '@jupyterlab/services-extension:kernel-manager',
  description: 'The kernel manager plugin.',
  autoStart: true,
  provides: IKernelManager,
  optional: [IServerSettings],
  activate: (
    _: null,
    serverSettings: ServerConnection.ISettings | undefined
  ): Kernel.IManager => {
    return new KernelManager({ serverSettings });
  }
};

we use

const kernelManagerPlugin: ServiceManagerPlugin<Kernel.IManager> = {
  id: '@jupyterlab/services-extension:kernel-manager',
  description: 'The kernel manager plugin.',
  autoStart: true,
  provides: IKernelManager,
  optional: [IServerSettings, IConnectionStatus],
  activate: (
    _: null,
    serverSettings: ServerConnection.ISettings | undefined,
    connectionStatus: IConnectionStatus | undefined,
  ): Kernel.IManager => {
    return new KernelManager({ serverSettings,
      standby: () => {
        return !connectionStatus?.isConnected || 'when-hidden';
      } });
  }
};

If you think that makes sense, I can put up a PR.

Cheers!!

1 Like

Yes this sounds reasonable. Please feel free to open the PR, thanks!

2 Likes