Migrate archive/unarchive to local ThreadStore (#17892)

# Summary
- implement local ThreadStore archive/unarchive operations
- implement local ThreadStore read_thread operation
- break up the various ThreadStore local method implementations into
separate files
- migrate app-server archive/unarchive and core archive fixture to use
ThreadStore (but not all read operations yet!)
- use the ThreadStore's read operation as a proxy check for thread
persistence/existence in the app server code
- move all other filesystem operations related to archive (path
validation etc) into the local thread store.

# Tests
- add dedicated local store archive/unarchive tests
This commit is contained in:
Tom
2026-04-15 13:48:09 -07:00
committed by GitHub
Unverified
parent ab715021e6
commit 50d3128269
11 changed files with 1179 additions and 776 deletions
+9 -27
View File
@@ -7,7 +7,6 @@ use crate::config::Config;
use crate::config::ConfigBuilder;
use crate::contextual_user_message::SUBAGENT_NOTIFICATION_OPEN_TAG;
use assert_matches::assert_matches;
use chrono::Utc;
use codex_features::Feature;
use codex_login::CodexAuth;
use codex_protocol::AgentPath;
@@ -24,6 +23,9 @@ use codex_protocol::protocol::TurnAbortReason;
use codex_protocol::protocol::TurnAbortedEvent;
use codex_protocol::protocol::TurnCompleteEvent;
use codex_protocol::protocol::TurnStartedEvent;
use codex_thread_store::ArchiveThreadParams;
use codex_thread_store::LocalThreadStore;
use codex_thread_store::ThreadStore;
use pretty_assertions::assert_eq;
use tempfile::TempDir;
use tokio::time::Duration;
@@ -1658,38 +1660,18 @@ async fn resume_agent_from_rollout_reads_archived_rollout_path() {
.await
.expect("child thread should exist");
persist_thread_for_tree_resume(&child_thread, "persist before archiving").await;
let rollout_path = child_thread
.rollout_path()
.expect("thread should have rollout path");
let state_db = child_thread
.state_db()
.expect("thread should have state db handle");
let _ = harness
.control
.shutdown_live_agent(child_thread_id)
.await
.expect("child shutdown should succeed");
let archived_root = harness
.config
.codex_home
.join(crate::ARCHIVED_SESSIONS_SUBDIR);
tokio::fs::create_dir_all(&archived_root)
let store = LocalThreadStore::new(codex_rollout::RolloutConfig::from_view(&harness.config));
store
.archive_thread(ArchiveThreadParams {
thread_id: child_thread_id,
})
.await
.expect("archived root should exist");
let archived_rollout_path = archived_root.join(
rollout_path
.file_name()
.expect("rollout file name should be present"),
);
tokio::fs::rename(&rollout_path, &archived_rollout_path)
.await
.expect("rollout should move to archived path");
state_db
.mark_archived(child_thread_id, archived_rollout_path.as_path(), Utc::now())
.await
.expect("state db archive update should succeed");
.expect("child thread should archive");
let resumed_thread_id = harness
.control