From d4e8c589b14c0e03f266dc23690e446a396a993f Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Thu, 15 Oct 2026 23:27:53 +0000 Subject: [PATCH] fix(daemon-service): write scope-set replicas on the blocking pool compare_and_swap_scope_set wrote each replica through the synchronous scope-set storage port inside the async request. On a native worker every write parked the worker on the SQLite writer. Run the replica loop on native_runtime::spawn_blocking; the loop still finishes every replica once it starts. --- .../src/invocation/lsp.rs | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/crates/tracedecay-daemon-service/src/invocation/lsp.rs b/crates/tracedecay-daemon-service/src/invocation/lsp.rs index 739adf9d9b9..92854ce28b1 100644 --- a/crates/tracedecay-daemon-service/src/invocation/lsp.rs +++ b/crates/tracedecay-daemon-service/src/invocation/lsp.rs @@ -282,21 +282,25 @@ impl DaemonInvocationService { // first durable write. Once the first compare-and-swap starts, finish // every authorized replica so the caller receives one authoritative // settlement instead of a fabricated interruption over a partial - // effect. - for storage in storages { - match storage - .compare_and_swap(request.expected_revision, &next) - .ok()? - { - tracedecay_store::runtime::ScopeSetCasOutcomeV1::Applied(_) => {} - tracedecay_store::runtime::ScopeSetCasOutcomeV1::Conflict { .. } => { - let stored = storage.read(next.scope_set_id()).ok()?; - if stored.as_ref() != Some(&next) { - return None; + // effect. The writes park their thread on the writer, so they run on + // the blocking pool. + let expected_revision = request.expected_revision; + let next = tracedecay_runtime_core::native_runtime::spawn_blocking(move || { + for storage in storages { + match storage.compare_and_swap(expected_revision, &next).ok()? { + tracedecay_store::runtime::ScopeSetCasOutcomeV1::Applied(_) => {} + tracedecay_store::runtime::ScopeSetCasOutcomeV1::Conflict { .. } => { + let stored = storage.read(next.scope_set_id()).ok()?; + if stored.as_ref() != Some(&next) { + return None; + } } } } - } + Some(next) + }) + .await + .ok()??; Some(( active_scope, MultiRootScopeSetCasResultV1 {