nteract / vdom

🎄 Virtual DOM for Python
https://github.com/nteract/vdom/blob/master/docs/mimetype-spec.md
BSD 3-Clause "New" or "Revised" License
222 stars 35 forks source link

[WIP] Use single global comm for event handlers #86

Closed gnestor closed 5 years ago

gnestor commented 5 years ago

When using the new event handler feature in vdom, it's easy to run into the following issue:

[E 14:25:56.106 LabApp] Uncaught exception GET /api/kernels/9b07598f-f972-4154-ba02-24cb223a0891/channels?session_id=88cc0759-6744-4d7e-b503-a266628ea10b&token=4431ca05d2bf9e8fb5e2ad681db65b61716cf52fee8b2f8e (::1)
    HTTPServerRequest(protocol='http', host='localhost:8888', method='GET', uri='/api/kernels/9b07598f-f972-4154-ba02-24cb223a0891/channels?session_id=88cc0759-6744-4d7e-b503-a266628ea10b&token=4431ca05d2bf9e8fb5e2ad681db65b61716cf52fee8b2f8e', version='HTTP/1.1', remote_ip='::1')
    Traceback (most recent call last):
      File "/Users/grant/anaconda/lib/python3.6/site-packages/tornado/websocket.py", line 546, in _run_callback
        result = callback(*args, **kwargs)
      File "/Users/grant/anaconda/lib/python3.6/site-packages/notebook/services/kernels/handlers.py", line 276, in open
        self.create_stream()
      File "/Users/grant/anaconda/lib/python3.6/site-packages/notebook/services/kernels/handlers.py", line 130, in create_stream
        self.channels[channel] = stream = meth(self.kernel_id, identity=identity)
      File "/Users/grant/anaconda/lib/python3.6/site-packages/jupyter_client/multikernelmanager.py", line 33, in wrapped
        r = method(*args, **kwargs)
      File "/Users/grant/anaconda/lib/python3.6/site-packages/jupyter_client/ioloop/manager.py", line 22, in wrapped
        socket = f(self, *args, **kwargs)
      File "/Users/grant/anaconda/lib/python3.6/site-packages/jupyter_client/connect.py", line 563, in connect_stdin
        return self._create_connected_socket('stdin', identity=identity)
      File "/Users/grant/anaconda/lib/python3.6/site-packages/jupyter_client/connect.py", line 543, in _create_connected_socket
        sock = self.context.socket(socket_type)
      File "/Users/grant/anaconda/lib/python3.6/site-packages/zmq/sugar/context.py", line 146, in socket
        s = self._socket_class(self, socket_type, **kwargs)
      File "/Users/grant/anaconda/lib/python3.6/site-packages/zmq/sugar/socket.py", line 59, in __init__
        super(Socket, self).__init__(*a, **kw)
      File "zmq/backend/cython/socket.pyx", line 328, in zmq.backend.cython.socket.Socket.__init__
    zmq.error.ZMQError: Too many open files

as a result of connecting to too many comms. This is because each event handler was registering its own comm channel.

The simple solution is to register a single, global comm channel for all vdom components to use and include a unique id in the payloads. This PR makes the necessary changes in vdom.

The changes to vdom involve using a constant vdom as the comm target name and maintaining a map of unique handler_ids and handler functions.

gnestor commented 5 years ago

I was able to fix the "zmq.error.ZMQError: Too many open files" issue by modifying the session logic in @jupyterlab/vdom-extension, so this PR may not be necessary, unless there is a benefit to using one global comm channel for all vdom event handling.