I believe I was misunderstanding the use of `zmq-poll` on the file descriptors
in a subprocess. It seems that polling the file descriptors doesn't seem to
work.
Currently I am sticking to running periodic timers in emacs itself to process
messages. This may slow down emacs when connecting to lots of clients that are
receiving and sending lots of messages.
What I would like to move towards is having a subprocess which connects to the
required endpoints and listens for incoming messages. When a message arrives,
it decodes it and sends it back to the parent emacs process. When I would like
to send a message, I just send the raw plist to the subprocess and it encodes
and sends it through the socket. So the subprocess will take care of
encoding/decoding messages and sending/receiving messages on sockets. Whereas
the parent emacs process will send/receive plists.
The problem appears to be that I was not waiting until the kernel was finished
handshaking with the `jupyter console` application. Kernels are currently
started using the `jupyter console` command which was causing messages not to
be received by `jupyter-kernel-client`
The jupyter v5.0 protocol specifies that for every request that is handled, a status: idle message will be sent when the request is complete. When receiving this idle message is when callbacks are removed from the table.
I think it makes more sense to prefix with `request` instead of send`. Since
`jupyter-send-execute` seems ambiguous unless you say something like
`jupyter-send-execute-request`. But if you say `jupyter-request-execute` it has
essentially the same meaning as `jupyter-send-execute-request` with the extra
word. It also works better for functions like `jupyter-request-kernel-info` as
opposed to `jupyter-send-kernel-info` which seems to imply that you are sending
the kernel info.
- All messages sent are prefixed like `jupyter-send-*`. So that an
`execute_request` maps to `jupyter-send-execute`.
- All received message handlers are prefixed with `jupyter-handle-*`. So that
an `execute_reply` message would be mapped to `jupyter-handle-execute`. Also
for IOPub messages, the handlers are also prefixed with
`jupyter-handle-<iopub message type>` so that a `stream` message would map to
`jupyter-handle-stream`.