-
Notifications
You must be signed in to change notification settings - Fork 949
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fetch the full widget state via a control Comm #3021
Fetch the full widget state via a control Comm #3021
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! This works very nicely with voila-dashboards/voila#766 and brings a very good speedup to Voila when there are many widgets.
It's also a simple addition to ipywidgets and doesn't change the normal behavior.
This was discussed today at the Jupyter widgets call. For this to get merged, we need to add documentation for this in the protocol documentation. |
ipywidgets/widgets/widget.py
Outdated
# the message is also send as buffer, so it does not get handled by jupyter_server | ||
msg = jsondumps([full_state, buffer_paths]).encode('utf8') | ||
buffers.insert(0, msg) | ||
comm.send(buffers=buffers) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the reasoning behind this sending the entire state as a "buffer" instead of sending as regular JSON? Is it to sidestep the decoding that happens in the server?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. It has a big performance impact. Although I would agree we don't want to do that and we would want to improve the server instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that is the right solution either, I think the fact that the jupyter protocol speaks JSON and the messages we send (the widget protocol) are JSON are a mere coincidence. We should not embed our widget protocol message inside the jupyter protocol as JSON, the JSON from the widget protocol should just be a string or binary buffer in the jupyter message. That way the server would not parse the JSON (it would just be a string). In this case I've chosen a buffer for performance reasons, but a single string would also suffice (i.e. json.dumps(..)). But I don't want to go too much off topic here.
Widget.close_all() | ||
w = SimpleWidget() | ||
Widget.handle_comm_opened_control(comm, {}) | ||
assert comm.messages |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally the tests would be inspecting the messages a little closer, e.g. check the buffer decoding etc.
Can we add a version metadata field for the comm_open message, like we do for the jupyter.widget channel? See https://github.com/jupyter-widgets/ipywidgets/blob/master/packages/schema/messages.md#instantiating-a-widget-object-1. This will let us experiment more freely and communicate at the start what the protocol version will be. |
For example, the working around the server performance problems by packaging the JSON in a binary buffer is probably something that can go away in a future iteration. |
d2c9083
to
16d0f57
Compare
Would it make sense to have the control channel message be a request to have the widget state be broadcast on the iopub channel? Since the data can be changing while the messages are in flight there can be a race between the response here and comm messages on iopub. Colab has had similar issues between shell and iopub- even though they are one WebSocket to the client they are still separate ZMQ sockets from the kernel and the messages can get reordered. |
To add context, the current pattern with comm messages is that comm messages from the frontend to the kernel go over the shell channel, and comm messages from the kernel to the frontend go over the iopub channel. Note that this is not a message on the control zmq channel. It's a new comm target on the existing channels (i.e., it will be coming back on iopub). |
ipywidgets/widgets/widget.py
Outdated
@@ -317,6 +318,27 @@ def _call_widget_constructed(widget): | |||
if Widget._widget_construction_callback is not None and callable(Widget._widget_construction_callback): | |||
Widget._widget_construction_callback(widget) | |||
|
|||
@classmethod | |||
def handle_comm_opened_control(cls, comm, msg): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the general consensus from the dev meeting is that this PR makes sense, but that the logic should not happen on comm open. Rather, the new comm channel can be considered a channel for the widget manager, where "get all the current widget state" would be one type of message that could be sent on it. That allows us to also use this channel for other purposes in the future without always having to transmit all the state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done :) Thanks for the review
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally agree with that, doing it on comm open was just a simple approach, and what @vidartf describes is much better! And thanks for implementing that @martinRenou !
28ddc59
to
d7e9b99
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs docs for the models message format
Added docs + made the messaging format/naming closer to the other channel |
a1010a6
to
341f215
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logic seems good to me, but I have some minor comments on code/conventions.
I also note that it might be good to have a method on the JS base manager to request the state and handle and/or parse the reply (e.g. put the buffers back in, update the state correctly). Even if we don't use it, it might be useful to have a "reference" implementation, especially if it is written such that it could be used directly by other projects (i.e. voila). It would probably make sense to add this in a follow-up PR though, so no need to add it now.
341f215
to
430013e
Compare
Makes sense! Thanks for the review, I took your comments into account |
Thanks! |
@meeseeksdev please backport to master |
Owee, I'm MrMeeseeks, Look at me. There seem to be a conflict, please backport manually. Here are approximate instructions:
And apply the correct labels and milestones. Congratulations — you did some good work! Hopefully your backport PR will be tested by the continuous integration and merged soon! Remember to remove the If these instructions are inaccurate, feel free to suggest an improvement. |
Related issues
More info voila-dashboards/voila#766