FigureWidget state desynchronization with multiple concurrent Jupyter clients
0 reputation · 07 Jan 2023, 10:31 UTC
0 reputation · 07 Jan 2023, 10:31 UTC
Goal: maintain identical figure state across all Jupyter clients connected to the same kernel when using Plotly FigureWidget for live updates.
Constraint: state synchronization relies on ipywidgets WebSocket messages; batching reduces traffic but does not guarantee ordering or deduplication when retries occur, especially with multiple subscribers.
Uncertainty: it is unclear whether Plotly automatically deduplicates write retries or if duplicate messages can cause divergent state.
Questions: Does FigureWidget internally deduplicate retried updates to prevent duplicate writes? How can developers detect state divergence between clients? What configuration options exist to enforce exactly‑once semantics?
33275 reputation · 07 Jan 2023, 18:42 UTC
Does FigureWidget deduplicate retried updates? No. FigureWidget relies entirely on the ipywidgets comm layer, which provides at-least-once delivery without ordering guarantees or message IDs. Retried WebSocket messages are applied independently by each connected client, so duplicate payloads can produce divergent figure state.
How can developers detect state divergence? Attach an observe callback on the FigureWidget's _view_name or _model_id traits and compare the state dictionary across clients via a kernel-side registry. A simpler approach: periodically hash fig.to_json() on each client and report the hash to a shared kernel dictionary keyed by comm.comm_id.
What configuration enforces exactly-once semantics? None. Neither Plotly nor ipywidgets exposes a setting for exactly-once delivery. The Jupyter protocol (5.x) lacks acknowledgments, deduplication fields, or version vectors.
The comm layer batches local trait changes via _hold_trait_notifications() but does not suppress duplicates originating from network retries or client reconnections. Each subscriber independently applies property changes; there is no server-side consensus. Plotly.js may also render optimistic updates before server acknowledgment, creating temporary visual divergence even when kernel state is consistent.
Implement a kernel-side singleton manager that assigns monotonically increasing sequence numbers to every state mutation:
on_msg handler, ignore any update whose sequence number ≤ last-applied value (idempotent apply).This pattern works because the kernel is the single source of truth; clients merely replay an ordered log.
Open two browser tabs connected to the same kernel. Create a FigureWidget and rapidly update a trace property (e.g., fig.data[0].y = new_data) from the kernel while simulating latency:
tc qdisc add dev lo root netem delay 100ms 20ms loss 5%Observe whether both tabs render identical final state. Instrument the kernel-side comm.on_msg handler to log payload hashes; disconnect/reconnect one client to force retries and check for duplicate payloads.
Which Jupyter front-end are you using (JupyterLab, classic Notebook, Jupyter Server, or a custom deployment)? Reconnection logic and WebSocket implementation differ enough to change the frequency and pattern of duplicate messages, which affects whether the sequence-number mitigation is necessary or if simpler batching suffices.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.