mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Distinguish rollout IDs from thread IDs (#38127)
## Why `thread/revert` preserves a thread ID while creating a new immutable rollout. Rollout persistence and filesystem fallback therefore need to distinguish the logical thread from each physical history file. ## What changed - Add a `RolloutId` alias and canonical filename parsing for both ordinary rollouts and reverted rollouts with a distinct rollout ID. - Allow the recorder to create a replacement rollout without changing the thread ID, and add lookup by either the stable thread ID or an exact rollout ID. - Index history references and compression safety checks by rollout ID so multiple rollouts for one thread remain distinct. - Preserve the rollout path selected in SQLite when filesystem repair encounters another rollout for the same thread. ## Testing Add coverage for filename round trips, replacement rollout metadata, thread and rollout lookup, reference indexing, compression, and database path preservation. GitOrigin-RevId: 14b1d0b4a9432b341a1307afc0abadd507e7ae7d
This commit is contained in:
1 parent
2230d64464
commit
4ef836f883
18 files changed
+513
-178
No files matched your search
@@ -199,6 +199,66 @@ async fn reconcile_rollout_preserves_existing_explicit_title() -> anyhow::Result
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn filesystem_repair_preserves_existing_rollout_path() -> anyhow::Result<()> {
|
||||
let home = TempDir::new().expect("temp dir");
|
||||
let thread_id = ThreadId::new();
|
||||
let initial_rollout_path = write_rollout_with_user_message(
|
||||
home.path(),
|
||||
thread_id,
|
||||
"Old",
|
||||
ThreadHistoryMode::Paginated,
|
||||
)?;
|
||||
let old_rollout_path = initial_rollout_path
|
||||
.with_file_name(format!("rollout-2026-06-01T14-26-25-{thread_id}_old.jsonl"));
|
||||
std::fs::rename(initial_rollout_path, old_rollout_path.as_path())?;
|
||||
let active_rollout_path = write_rollout_with_user_message(
|
||||
home.path(),
|
||||
thread_id,
|
||||
"Current",
|
||||
ThreadHistoryMode::Paginated,
|
||||
)?;
|
||||
let runtime = codex_state::StateRuntime::init(
|
||||
codex_state::SqliteConfig::new_for_testing(home.path().abs()),
|
||||
"test-provider".to_string(),
|
||||
)
|
||||
.await?;
|
||||
let active_metadata =
|
||||
metadata::extract_metadata_from_rollout(active_rollout_path.as_path(), "test-provider")
|
||||
.await?
|
||||
.metadata;
|
||||
runtime.upsert_thread(&active_metadata).await?;
|
||||
let active_metadata = runtime
|
||||
.get_thread(thread_id)
|
||||
.await?
|
||||
.expect("thread should exist");
|
||||
|
||||
read_repair_rollout_path(
|
||||
Some(runtime.as_ref()),
|
||||
Some(thread_id),
|
||||
/*archived_only*/ None,
|
||||
old_rollout_path.as_path(),
|
||||
)
|
||||
.await;
|
||||
assert_eq!(
|
||||
runtime.get_thread(thread_id).await?,
|
||||
Some(active_metadata.clone())
|
||||
);
|
||||
|
||||
reconcile_rollout(
|
||||
Some(runtime.as_ref()),
|
||||
old_rollout_path.as_path(),
|
||||
"test-provider",
|
||||
/*builder*/ None,
|
||||
&[],
|
||||
/*archived_only*/ None,
|
||||
/*new_thread_memory_mode*/ None,
|
||||
)
|
||||
.await;
|
||||
assert_eq!(runtime.get_thread(thread_id).await?, Some(active_metadata));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn reconcile_rollout_preserves_existing_paginated_memory_mode() -> anyhow::Result<()> {
|
||||
let home = TempDir::new().expect("temp dir");
|
||||
|
||||
Reference in new issue
Block a user