Struggling with kernel messaging

I am trying to have my backend send messages to the frontend via kernel messaging. However, the frontend cannot receive comm messages from the backend. I consolidated my code to a barebones communication example. Here is my code:

backend handlers.py:

import json
from jupyter_server.base.handlers import APIHandler
from jupyter_server.utils import url_path_join
import tornado
from ipykernel.comm import Comm

comm = Comm(target_name="commtest")

class RouteHandler(APIHandler):
    @tornado.web.authenticated
    def get(self):
        # Sending a comm message, but frontend does not get it
        comm.send({"msg": "Hello from the backend on GET request!"})

        self.finish(json.dumps({
            "data": "This is /commtest/get-example endpoint!"
        }))


def setup_handlers(web_app):
    host_pattern = ".*$"
    base_url = web_app.settings["base_url"]
    route_pattern = url_path_join(base_url, "commtest", "get-example")
    handlers = [(route_pattern, RouteHandler)]
    web_app.add_handlers(host_pattern, handlers)

Frontend index.ts:

activate: (app: JupyterFrontEnd, tracker: INotebookTracker | null) => {
    if (tracker) {
      tracker.widgetAdded.connect((sender, nbPanel: NotebookPanel) => {
        const session = nbPanel.sessionContext;

        const registerCommTarget = () => {
          console.log('Session kernel:', session.session?.kernel);
        
          if (session.session?.kernel) {
            session.session.kernel.registerCommTarget('commtest', (comm, open_msg) => {
              comm.send({ msg: 'Hello from frontend!' });
              // This log statement is never shown, indicating message not received
              comm.onMsg = msg => {
                console.log('Message received from backend:', msg.content.data);
              };
            });
          } else {
            console.error('No kernel found for the session.');
          }
        };

        session.ready.then(() => {
          registerCommTarget();

          session.kernelChanged.connect((_, args) => {
            if (args.newValue == null) {
              return;
            }
            session.ready.then(() => {
              registerCommTarget();
            });
          });
        });
      });
    } else {
      console.error('Notebook tracker is not available.');
    }

    const fetchData = () => {
      requestAPI<any>('get-example')
        .then(data => {
          console.log(data);
        })
        .catch(reason => {
          console.error(
            `The commtest server extension appears to be missing.\n${reason}`
          );
        });
    };

    setTimeout(fetchData, 5000);
  }

How do I get the backend comm to send messages to the frontend? Appreciate any input!

The backend handlers.py does not represent a kernel but jupyter-server. jupyter-server does spawn kernels, but this is a complex task much deeper in the code.

There are two-three typical architectures:

1 Like

You may be interested in reading though:

1 Like