From 4eb0d3272d99eda7c3c9420ecb8e20c8fd9bb8b7 Mon Sep 17 00:00:00 2001 From: Charles Cunningham Date: Wed, 25 Mar 2026 11:26:52 -0700 Subject: [PATCH] codex: use arc-swap for shared state db Co-authored-by: Codex --- codex-rs/Cargo.lock | 1 + codex-rs/app-server/Cargo.toml | 1 + .../app-server/src/codex_message_processor.rs | 26 +++++++++---------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index 9ecf9b1de4..c2589ed8e7 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -1429,6 +1429,7 @@ version = "0.0.0" dependencies = [ "anyhow", "app_test_support", + "arc-swap", "async-trait", "axum", "base64 0.22.1", diff --git a/codex-rs/app-server/Cargo.toml b/codex-rs/app-server/Cargo.toml index 1eb09e2605..2bbfefc573 100644 --- a/codex-rs/app-server/Cargo.toml +++ b/codex-rs/app-server/Cargo.toml @@ -21,6 +21,7 @@ workspace = true [dependencies] anyhow = { workspace = true } +arc-swap = "1.8.2" async-trait = { workspace = true } base64 = { workspace = true } axum = { workspace = true, default-features = false, features = [ diff --git a/codex-rs/app-server/src/codex_message_processor.rs b/codex-rs/app-server/src/codex_message_processor.rs index 2966197883..aab03c466e 100644 --- a/codex-rs/app-server/src/codex_message_processor.rs +++ b/codex-rs/app-server/src/codex_message_processor.rs @@ -324,6 +324,7 @@ use crate::filters::source_kind_matches; use crate::thread_state::ThreadListenerCommand; use crate::thread_state::ThreadState; use crate::thread_state::ThreadStateManager; +use arc_swap::ArcSwapOption; const THREAD_LIST_DEFAULT_LIMIT: usize = 25; const THREAD_LIST_MAX_LIMIT: usize = 100; @@ -384,7 +385,7 @@ pub(crate) struct CodexMessageProcessor { pending_fuzzy_searches: Arc>>>, fuzzy_search_sessions: Arc>>, background_tasks: TaskTracker, - state_db: Mutex>, + state_db: ArcSwapOption, feedback: CodexFeedback, log_db: Option, } @@ -436,17 +437,16 @@ pub(crate) struct CodexMessageProcessorArgs { impl CodexMessageProcessor { async fn shared_state_db(&self) -> Option { - let mut state_db = self.state_db.lock().await; - match state_db.as_ref() { - Some(state_db) => Some(state_db.clone()), - None => { - let recovered = state_db::init(self.config.as_ref()).await; - if let Some(recovered) = recovered.as_ref() { - *state_db = Some(recovered.clone()); - } - recovered - } + if let Some(state_db) = self.state_db.load_full() { + return Some(state_db); } + + let recovered = state_db::init(self.config.as_ref()).await; + if let Some(recovered) = recovered.as_ref() { + self.state_db.store(Some(recovered.clone())); + } + + recovered } pub(crate) fn clear_plugin_related_caches(&self) { @@ -530,7 +530,7 @@ impl CodexMessageProcessor { pending_fuzzy_searches: Arc::new(Mutex::new(HashMap::new())), fuzzy_search_sessions: Arc::new(Mutex::new(HashMap::new())), background_tasks: TaskTracker::new(), - state_db: Mutex::new(state_db), + state_db: ArcSwapOption::new(state_db), feedback, log_db, } @@ -9124,7 +9124,7 @@ mod tests { .expect("cached state db should be reused"); assert!(Arc::ptr_eq(&first, &second)); - assert!(processor.state_db.lock().await.is_some()); + assert!(processor.state_db.load_full().is_some()); Ok(()) }