Close anywidget comms on cell re-execution and deletion#8159
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
mscolnick
previously approved these changes
Feb 6, 2026
When a cell containing an anywidget is re-executed or deleted, the runtime invalidates cell state and removes UI elements, but no ModelClose message was ever sent to the frontend. The `MarimoComm.__del__` fallback never fires because `MarimoCommManager.comms` holds a strong reference to every comm, preventing garbage collection. This leaks frontend objects along with their event listeners. These changes adds a `CommLifecycleItem` that registers with the cell lifecycle registry when a widget comm is created. When the cell is invalidated (re-execution, deletion, or error), `dispose()` calls `comm.close()`, which broadcasts ModelClose to the frontend and unregisters from the comm manager.
433e29a to
29fe45b
Compare
mscolnick
approved these changes
Feb 6, 2026
manzt
added a commit
that referenced
this pull request
Feb 6, 2026
The anywidget refactors in #8156, #8159, and #8163 separated model lifecycle from widget binding and moved to a dedicated ModelCommand for frontend-to-backend communication. However, unlike UpdateUIElementCommand which goes through SetUIElementRequestManager's drain-and-merge path, ModelCommand was processed immediately — each rapid model update (e.g. dragging a map widget) triggered an individual cell re-execution. These changes puts `ModelCommand` on the same shared queue as `UpdateUIElementCommand` so both go through the same batching pipeline. When multiple model updates arrive in quick succession, they are now drained and merged (last-write-wins per model ID on state keys), matching the existing UI element behavior. The handler for model messages also now enqueues the resulting `UpdateUIElementCommand` back through the control queue instead of calling `set_ui_element_value` directly, so the downstream cell re-execution also benefits from batching.
manzt
added a commit
that referenced
this pull request
Feb 8, 2026
The anywidget refactors in #8156, #8159, and #8163 separated model lifecycle from widget binding and moved to a dedicated ModelCommand for frontend-to-backend communication. However, unlike UpdateUIElementCommand which goes through SetUIElementRequestManager's drain-and-merge path, ModelCommand was processed immediately — each rapid model update (e.g. dragging a map widget) triggered an individual cell re-execution. These changes puts `ModelCommand` on the same shared queue as `UpdateUIElementCommand` so both go through the same batching pipeline. When multiple model updates arrive in quick succession, they are now drained and merged (last-write-wins per model ID on state keys), matching the existing UI element behavior. The handler for model messages also now enqueues the resulting `UpdateUIElementCommand` back through the control queue instead of calling `set_ui_element_value` directly, so the downstream cell re-execution also benefits from batching.
manzt
added a commit
that referenced
this pull request
Feb 9, 2026
The anywidget refactors in #8156, #8159, and #8163 separated model lifecycle from widget binding and moved to a dedicated ModelCommand for frontend-to-backend communication. However, unlike UpdateUIElementCommand which goes through SetUIElementRequestManager's drain-and-merge path, ModelCommand was processed immediately — each rapid model update (e.g. dragging a map widget) triggered an individual cell re-execution. These changes puts `ModelCommand` on the same shared queue as `UpdateUIElementCommand` so both go through the same batching pipeline. When multiple model updates arrive in quick succession, they are now drained and merged (last-write-wins per model ID on state keys), matching the existing UI element behavior. The handler for model messages also now enqueues the resulting `UpdateUIElementCommand` back through the control queue instead of calling `set_ui_element_value` directly, so the downstream cell re-execution also benefits from batching.
manzt
added a commit
that referenced
this pull request
Feb 10, 2026
The anywidget refactors in #8156, #8159, and #8163 separated model lifecycle from widget binding and moved to a dedicated ModelCommand for frontend-to-backend communication. However, unlike UpdateUIElementCommand which goes through SetUIElementRequestManager's drain-and-merge path, ModelCommand was processed immediately — each rapid model update (e.g. dragging a map widget) triggered an individual cell re-execution. These changes puts `ModelCommand` on the same shared queue as `UpdateUIElementCommand` so both go through the same batching pipeline. When multiple model updates arrive in quick succession, they are now drained and merged (last-write-wins per model ID on state keys), matching the existing UI element behavior. The handler for model messages also now enqueues the resulting `UpdateUIElementCommand` back through the control queue instead of calling `set_ui_element_value` directly, so the downstream cell re-execution also benefits from batching.
manzt
added a commit
that referenced
this pull request
Feb 10, 2026
The anywidget refactors in #8156, #8159, and #8163 separated model lifecycle from widget binding and moved to a dedicated ModelCommand for frontend-to-backend communication. However, unlike UpdateUIElementCommand which goes through SetUIElementRequestManager's drain-and-merge path, ModelCommand was processed immediately — each rapid model update (e.g. dragging a map widget) triggered an individual cell re-execution. These changes puts `ModelCommand` on the same shared queue as `UpdateUIElementCommand` so both go through the same batching pipeline. When multiple model updates arrive in quick succession, they are now drained and merged (last-write-wins per model ID on state keys), matching the existing UI element behavior. The handler for model messages also now enqueues the resulting `UpdateUIElementCommand` back through the control queue instead of calling `set_ui_element_value` directly, so the downstream cell re-execution also benefits from batching.
manzt
added a commit
that referenced
this pull request
Feb 10, 2026
The anywidget refactors in #8156, #8159, and #8163 separated model lifecycle from widget binding and moved to a dedicated ModelCommand for frontend-to-backend communication. However, unlike UpdateUIElementCommand which goes through SetUIElementRequestManager's drain-and-merge path, ModelCommand was processed immediately — each rapid model update (e.g. dragging a map widget) triggered an individual cell re-execution. These changes puts `ModelCommand` on the same shared queue as `UpdateUIElementCommand` so both go through the same batching pipeline. When multiple model updates arrive in quick succession, they are now drained and merged (last-write-wins per model ID on state keys), matching the existing UI element behavior. The handler for model messages also now enqueues the resulting `UpdateUIElementCommand` back through the control queue instead of calling `set_ui_element_value` directly, so the downstream cell re-execution also benefits from batching.
manzt
added a commit
that referenced
this pull request
Feb 10, 2026
The anywidget refactors in #8156, #8159, and #8163 separated model lifecycle from widget binding and moved to a dedicated ModelCommand for frontend-to-backend communication. However, unlike UpdateUIElementCommand which goes through SetUIElementRequestManager's drain-and-merge path, ModelCommand was processed immediately — each rapid model update (e.g. dragging a map widget) triggered an individual cell re-execution. These changes puts `ModelCommand` on the same shared queue as `UpdateUIElementCommand` so both go through the same batching pipeline. When multiple model updates arrive in quick succession, they are now drained and merged (last-write-wins per model ID on state keys), matching the existing UI element behavior. The handler for model messages also now enqueues the resulting `UpdateUIElementCommand` back through the control queue instead of calling `set_ui_element_value` directly, so the downstream cell re-execution also benefits from batching.
manzt
added a commit
that referenced
this pull request
Feb 10, 2026
The anywidget refactors in #8156, #8159, and #8163 separated model lifecycle from widget binding and moved to a dedicated ModelCommand for frontend-to-backend communication. However, unlike UpdateUIElementCommand which goes through SetUIElementRequestManager's drain-and-merge path, ModelCommand was processed immediately — each rapid model update (e.g. dragging a map widget) triggered an individual cell re-execution. These changes puts `ModelCommand` on the same shared queue as `UpdateUIElementCommand` so both go through the same batching pipeline. When multiple model updates arrive in quick succession, they are now drained and merged (last-write-wins per model ID on state keys), matching the existing UI element behavior. The handler for model messages also now enqueues the resulting `UpdateUIElementCommand` back through the control queue instead of calling `set_ui_element_value` directly, so the downstream cell re-execution also benefits from batching.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When a cell containing an anywidget is re-executed or deleted, the runtime invalidates cell state and removes UI elements, but no ModelClose message was ever sent to the frontend.
The
MarimoComm.__del__fallback never fires becauseMarimoCommManager.commsholds a strong reference to every comm, preventing garbage collection. This leaks frontend objects along with their event listeners.These changes adds a
CommLifecycleItemthat registers with the cell lifecycle registry when a widget comm is created. When the cell is invalidated (re-execution, deletion, or error),dispose()callscomm.close(), which broadcasts ModelClose to the frontend and unregisters from the comm manager.