mirror of
https://github.com/openai/codex.git
synced 2026-11-10 21:00:47 +00:00
Keep thread storage available when diagnostic logs fail (#60466)
## Why Failure to open the diagnostic logs database should not disable thread storage or database-only history listing. Thread deletion must still preserve saved conversations when diagnostic log cleanup cannot complete. ## What changed - Allow state initialization to continue after non-corruption errors opening the logs database, while preserving corruption recovery. - Report the original diagnostic database error after tracing is installed in the TUI and app server, and return it from log operations. - Reject thread deletion before destructive cleanup when diagnostic storage failed to initialize. - Continue periodic cleanup of legacy logs when the current logs database is unavailable. ## Testing Extend coverage for unavailable log directories, database-only history listing, startup diagnostics, deletion preserving saved conversations, corrupt log headers, and periodic legacy log cleanup during a diagnostic storage outage. GitOrigin-RevId: a5184580ae6c39ed0c4eefa8cb48ee7731a991c3
This commit is contained in:
committed by
copyberry
parent
e1cc96712f
commit
caae161dd0
@@ -5,6 +5,7 @@
|
||||
//! associated rollout is removed, under the same lifecycle lock, so queued artifact mutations cannot
|
||||
//! use deleted thread metadata. Host-owned data is cleaned after reference and writer checks,
|
||||
//! before removing rollouts, so cleanup failures remain retryable even without a state DB.
|
||||
//! Known diagnostic database failures must be rejected before any destructive cleanup.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
@@ -41,11 +42,25 @@ impl LocalThreadStore {
|
||||
&self,
|
||||
thread_ids: &[ThreadId],
|
||||
) -> ThreadStoreResult<()> {
|
||||
ensure_diagnostic_logs_available(self)?;
|
||||
let reference_index = scan_reference_index(self).await?;
|
||||
check_attached_children(&reference_index, thread_ids)
|
||||
}
|
||||
}
|
||||
|
||||
fn ensure_diagnostic_logs_available(store: &LocalThreadStore) -> ThreadStoreResult<()> {
|
||||
if let Some(error) = store
|
||||
.state_db
|
||||
.as_ref()
|
||||
.and_then(|db| db.diagnostic_logs_error())
|
||||
{
|
||||
return Err(ThreadStoreError::Internal {
|
||||
message: format!("cannot delete thread while diagnostic logs are unavailable: {error}"),
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_attached_children(
|
||||
reference_index: &RolloutReferenceIndex,
|
||||
thread_ids: &[ThreadId],
|
||||
@@ -94,6 +109,7 @@ pub(super) async fn delete_thread(
|
||||
store: &LocalThreadStore,
|
||||
params: DeleteThreadParams,
|
||||
) -> ThreadStoreResult<()> {
|
||||
ensure_diagnostic_logs_available(store)?;
|
||||
let thread_id = params.thread_id;
|
||||
let _lifecycle_guard = store.live_writer_locks.lock_lifecycle(thread_id).await;
|
||||
let _live_writer_guard = store.live_writer_locks.lock(thread_id).await;
|
||||
@@ -129,6 +145,7 @@ pub(super) async fn delete_threads(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
ensure_diagnostic_logs_available(store)?;
|
||||
let mut lock_thread_ids = thread_ids.clone();
|
||||
lock_thread_ids.sort_unstable_by_key(ToString::to_string);
|
||||
lock_thread_ids.dedup();
|
||||
|
||||
Reference in New Issue
Block a user