feat: concurrent dispatch for fs/workspace WebSocket requests#37
Merged
feat: concurrent dispatch for fs/workspace WebSocket requests#37
Conversation
Previously all non-chat WS requests were processed serially in the message loop, causing head-of-line blocking when clients send multiple fs.list/fs.read/etc. requests in quick succession. Changes: - handler.py: dispatch fs/workspace methods as asyncio tasks so they run concurrently; track tasks for cleanup on disconnect - manager.py: add per-connection send_lock to prevent WebSocket frame interleaving from concurrent tasks - workspace_fs.py: add _PathLockManager with per-path write locks (sorted acquisition order to prevent deadlock); read ops remain lock-free - tests: add 5 concurrency tests covering parallel reads, serialized same-path writes, parallel different-path writes, rename deadlock safety, and lock cleanup
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.
Summary
fs.list,fs.stat,fs.read,fs.write, etc.) are now dispatched as concurrentasyncio.Tasks instead of being awaited serially in the message loop, eliminating request queuing when clients send multiple fs requests in quick succession_PathLockManagertoWorkspaceFSServicethat serializes concurrent writes to the same path while allowing different paths to write in parallel; locks are acquired in sorted order to prevent deadlock onrenamesend_lockperConnectionto serializesend_jsoncalls and prevent frame interleaving from concurrent tasksChanges
handler.py_CONCURRENT_METHODSfrozenset; message loop now usescreate_taskfor fs/workspace methods;_concurrent_tasksset tracks in-flight tasks for cleanup on disconnectmanager.pyConnectiondataclass gainssend_lock: asyncio.Lock;send_messagewrapssend_jsonwith itworkspace_fs.py_PathLockManagerclass;write/mkdir/rename/removewrapped with path locks; read methods (list/stat/read) unchangedtests/test_workspace_fs_service.pyTest Plan
test_concurrent_reads_run_in_parallel— 15 parallel read ops complete correctlytest_concurrent_writes_same_path_serialized— same-path writes do not overlap (verified via timing)test_concurrent_writes_different_paths_parallel— different-path writes run in parallel (elapsed < 120ms for 3×50ms writes)test_rename_no_deadlock— rename with two-path lock completes within 2s timeouttest_path_lock_cleanup—_PathLockManagercleans up lock entries after release