chore(asyncio): migrate remaining background-task sites to asyncio_utils#9596
Merged
Conversation
Follow-up to the asyncio hardening pass. Replaces hand-rolled task creation and cancel-and-await patterns with the shared helpers. - supervised_task in lsp.py (health monitor), mcp/client.py (health monitor + connection lifecycle), rtc/doc.py (loro cleaner), and middleware.py (timeout monitor). - cancel_and_wait in mcp/client.py (single-server health cancel) and terminal.py's _cancel_tasks helper.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
There was a problem hiding this comment.
No issues found across 5 files
Architecture diagram
sequenceDiagram
participant App as Application
participant U as asyncio_utils
participant Task as Background Task
Note over App,Task: supervised_task wraps asyncio.create_task
App->>U: supervised_task(coro, name="...")
U->>U: wrap in cancellable task handle
U->>U: attach exception logging
U->>Task: asyncio.create_task(wrapped_coro)
Task-->>U: Task handle
U-->>App: Task handle
Note over App,Task: cancel_and_wait replaces hand-rolled cancel+await
App->>U: cancel_and_wait(task)
U->>Task: task.cancel()
Task-->>U: CancelledError
U->>U: await task (suppresses CancelledError)
U-->>App: None
Note over App: Health monitor lifecycle (LSP, MCP, Timeout)
App->>App: start health monitor
App->>U: supervised_task(monitor(), name="lsp.health.{id}")
U-->>App: health_task
alt monitor stops normally
health_task->>App: completes
else monitor needs cancellation
App->>U: cancel_and_wait(health_task)
U-->>App: cancellation handled
end
Note over App: MCP connection lifecycle
App->>U: supervised_task(connection_lifecycle(), name="mcp.lifecycle.{name}")
U-->>App: lifecycle_task
App->>App: discover tools
App->>U: supervised_task(health_monitor(), name="mcp.health.{name}")
U-->>App: health_task
alt connection closes
App->>U: cancel_and_wait(health_task)
U-->>App: cancelled
end
Note over App: RTC cleaner
App->>App: remove client from LoroDoc
App->>U: supervised_task(clean_loro_doc(), name="rtc.cleaner.{file_key}")
U-->>App: cleaner_task
Note over App: Terminal task cleanup
App->>U: cancel_and_wait(task) (for each task)
U->>Task: cancel + await
U-->>App: done
Note over App: Timeout monitor
App->>U: supervised_task(monitor(), name="timeout.monitor")
U-->>App: monitor_task
Contributor
There was a problem hiding this comment.
Pull request overview
This PR continues the asyncio hardening work by migrating remaining ad-hoc background task creation/cancellation patterns to shared helpers in marimo._utils.asyncio_utils, aiming for more consistent exception logging, task naming, and cancellation handling.
Changes:
- Replaced several
asyncio.create_task(...)call sites withsupervised_task(...)and added descriptive task names. - Replaced local “cancel + await + suppress CancelledError” loops with
cancel_and_wait(...)in terminal and MCP single-server health cancellation. - Standardized background task handling for LSP health monitoring, RTC doc cleanup, and inactivity timeout monitoring.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
marimo/_server/rtc/doc.py |
Uses supervised_task for RTC loro doc cleaner tasks and names them for easier debugging/logging. |
marimo/_server/lsp.py |
Uses supervised_task for LSP process health monitor task with a stable name. |
marimo/_server/api/middleware.py |
Uses supervised_task for the inactivity timeout monitor task. |
marimo/_server/api/endpoints/terminal.py |
Uses cancel_and_wait to simplify and harden task cancellation/awaiting during terminal websocket cleanup. |
marimo/_server/ai/mcp/client.py |
Uses supervised_task for MCP health monitors and connection lifecycle tasks; uses cancel_and_wait for single-server health monitor cancellation. |
connection_task is awaited in disconnect_from_server(), so supervised_task's done-callback would log the exception in addition to the awaiter, producing duplicate error logs. Revert this one site to asyncio.create_task; the strong reference is already held via connection.connection_task.
Contributor
There was a problem hiding this comment.
No issues found across 5 files
Architecture diagram
sequenceDiagram
participant LSP as LSP Server
participant MCP as MCP Client
participant RTC as RTC Doc Manager
participant Middleware as Timeout Middleware
participant TTY as Terminal Session
participant AsyncUtils as asyncio_utils
Note over LSP,AsyncUtils: Background task lifecycle migration
LSP->>AsyncUtils: supervised_task(health_monitor(), name="lsp.health.{id}")
AsyncUtils-->>LSP: Task handle (with error logging + cleanup)
MCP->>AsyncUtils: supervised_task(health_monitor(), name="mcp.health.{server}")
AsyncUtils-->>MCP: Task handle
MCP->>MCP: _connection_lifecycle() uses asyncio.create_task (unsupervised)
Note over MCP: Connection lifecycle task not supervised<br/>because it is awaited during disconnect
MCP->>AsyncUtils: cancel_and_wait(health_check_tasks[server_name])
AsyncUtils->>MCP: Cancels task, awaits CancelledError
RTC->>AsyncUtils: supervised_task(cleaner(), name="rtc.cleaner.{key}")
AsyncUtils-->>RTC: Task handle
Middleware->>AsyncUtils: supervised_task(monitor(), name="timeout.monitor")
AsyncUtils-->>Middleware: Task handle
TTY->>AsyncUtils: cancel_and_wait(task) (per task in _cancel_tasks)
AsyncUtils->>TTY: Cancels each task, awaits CancelledError
alt Task fails unexpectedly
AsyncUtils->>AsyncUtils: Log error + traceback
end
alt Task cancelled
AsyncUtils->>AsyncUtils: Silently await CancelledError
end
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.
Follow-up to the asyncio hardening pass. Replaces hand-rolled task
creation and cancel-and-await patterns with the shared helpers.
monitor + connection lifecycle), rtc/doc.py (loro cleaner), and
middleware.py (timeout monitor).
terminal.py's _cancel_tasks helper.