Background
BackendManager::with_backends acquires the Arc<Mutex<FusionBackends<SemanticBackendProvider>>> and holds it for the full duration of handler.rs line 91:
.with_backends(|backends| self.router.route(&request, &mut writer, backends));
For the observe graph-slice handler this means the lock is held across:
- Filesystem reads (
read_slice_source)
- Up to 256 tree-sitter extraction calls (
discover_same_file_cards)
- LSP network calls for semantic enrichment (
enrich_card_if_requested)
This prevents concurrent request handling and risks lock poisoning if any of these blocking operations panics.
Task
- Narrow the lock duration so it is held only while accessing shared mutable backend state, not across blocking I/O or network operations.
- Identify whether tree-sitter extraction and LSP enrichment can be performed outside the lock by cloning or arc-ing the relevant client handles.
- Add a concurrent-request integration test that submits two
observe graph-slice requests simultaneously and asserts both complete within an acceptable timeout.
- Add timeout handling to
with_backends (or its callers) to surface lock contention rather than hanging indefinitely.
Context
Identified as out of scope during review of PR #106.
Raised by @leynos.
Background
BackendManager::with_backendsacquires theArc<Mutex<FusionBackends<SemanticBackendProvider>>>and holds it for the full duration ofhandler.rsline 91:For the
observe graph-slicehandler this means the lock is held across:read_slice_source)discover_same_file_cards)enrich_card_if_requested)This prevents concurrent request handling and risks lock poisoning if any of these blocking operations panics.
Task
observe graph-slicerequests simultaneously and asserts both complete within an acceptable timeout.with_backends(or its callers) to surface lock contention rather than hanging indefinitely.Context
Identified as out of scope during review of PR #106.
Raised by
@leynos.