Simplify SQLite journal mode plumbing

This commit is contained in:
jif-oai
2026-06-05 14:18:58 +02:00
parent 00e9f068e2
commit 1bad0a0804
10 changed files with 51 additions and 57 deletions
+4 -3
View File
@@ -763,9 +763,10 @@ mod tests {
) -> InProcessClientHandle {
let codex_home = TempDir::new().expect("temp dir");
let config = Arc::new(build_test_config(codex_home.path()).await);
let state_db = codex_rollout::state_db::try_init(config.as_ref())
.await
.expect("state db should initialize for in-process test");
let state_db =
codex_rollout::state_db::try_init(config.as_ref(), config.sqlite_journal_mode)
.await
.expect("state db should initialize for in-process test");
let args = InProcessStartArgs {
arg0_paths: Arg0DispatchPaths::default(),
config,
+1 -1
View File
@@ -531,7 +531,7 @@ pub async fn run_main_with_transport_options(
}
_ => None,
};
let state_db = match rollout_state_db::try_init(&config).await {
let state_db = match rollout_state_db::try_init(&config, config.sqlite_journal_mode).await {
Ok(state_db) => Some(state_db),
Err(err) => {
return Err(std::io::Error::other(format!(
+4 -10
View File
@@ -253,15 +253,6 @@ fn resolve_sqlite_home_env(resolved_cwd: &Path) -> Option<PathBuf> {
}
}
fn resolve_sqlite_journal_mode(
mode: SqliteJournalModeToml,
) -> codex_state::RuntimeSqliteJournalMode {
match mode {
SqliteJournalModeToml::Wal => codex_state::RuntimeSqliteJournalMode::Wal,
SqliteJournalModeToml::Delete => codex_state::RuntimeSqliteJournalMode::Delete,
}
}
fn resolve_cli_auth_credentials_store_mode(
configured: AuthCredentialsStoreMode,
package_version: &str,
@@ -3293,7 +3284,10 @@ impl Config {
.sqlite
.as_ref()
.and_then(|sqlite| sqlite.journal_mode)
.map(resolve_sqlite_journal_mode)
.map(|mode| match mode {
SqliteJournalModeToml::Wal => codex_state::RuntimeSqliteJournalMode::Wal,
SqliteJournalModeToml::Delete => codex_state::RuntimeSqliteJournalMode::Delete,
})
.unwrap_or_default();
let original_permission_profile = permission_profile.clone();
apply_requirement_constrained_value(
-4
View File
@@ -32,10 +32,6 @@ impl codex_rollout::RolloutConfigView for Config {
self.sqlite_home.as_path()
}
fn sqlite_journal_mode(&self) -> codex_state::RuntimeSqliteJournalMode {
self.sqlite_journal_mode
}
fn cwd(&self) -> &std::path::Path {
self.cwd.as_path()
}
+1 -1
View File
@@ -4,5 +4,5 @@ pub use codex_rollout::state_db::StateDbHandle;
use crate::config::Config;
pub async fn init_state_db(config: &Config) -> Option<StateDbHandle> {
rollout_state_db::init(config).await
rollout_state_db::init(config, config.sqlite_journal_mode).await
}
-11
View File
@@ -5,9 +5,6 @@ use std::sync::Arc;
pub trait RolloutConfigView {
fn codex_home(&self) -> &Path;
fn sqlite_home(&self) -> &Path;
fn sqlite_journal_mode(&self) -> codex_state::RuntimeSqliteJournalMode {
codex_state::RuntimeSqliteJournalMode::default()
}
fn cwd(&self) -> &Path;
fn model_provider_id(&self) -> &str;
fn generate_memories(&self) -> bool;
@@ -67,10 +64,6 @@ impl<T: RolloutConfigView + ?Sized> RolloutConfigView for &T {
(*self).sqlite_home()
}
fn sqlite_journal_mode(&self) -> codex_state::RuntimeSqliteJournalMode {
(*self).sqlite_journal_mode()
}
fn cwd(&self) -> &Path {
(*self).cwd()
}
@@ -93,10 +86,6 @@ impl<T: RolloutConfigView + ?Sized> RolloutConfigView for Arc<T> {
self.as_ref().sqlite_home()
}
fn sqlite_journal_mode(&self) -> codex_state::RuntimeSqliteJournalMode {
self.as_ref().sqlite_journal_mode()
}
fn cwd(&self) -> &Path {
self.as_ref().cwd()
}
+2 -1
View File
@@ -127,7 +127,8 @@ async fn state_db_init_backfills_before_returning() -> anyhow::Result<()> {
.join("\n");
fs::write(&rollout_path, format!("{jsonl}\n"))?;
let runtime = crate::state_db::init(&test_config(home.path()))
let config = test_config(home.path());
let runtime = crate::state_db::init(&config, codex_state::RuntimeSqliteJournalMode::default())
.await
.expect("state db should initialize");
+15 -6
View File
@@ -38,11 +38,14 @@ const STARTUP_BACKFILL_WAIT_TIMEOUT: Duration = Duration::from_secs(2);
/// This is the process entry point for local state: it opens the SQLite-backed
/// runtime, applies rollout metadata backfills as needed, and returns the
/// initialized handle.
pub async fn init(config: &impl RolloutConfigView) -> Option<StateDbHandle> {
pub async fn init(
config: &impl RolloutConfigView,
sqlite_journal_mode: codex_state::RuntimeSqliteJournalMode,
) -> Option<StateDbHandle> {
match try_init_with_roots(
config.codex_home().to_path_buf(),
config.sqlite_home().to_path_buf(),
config.sqlite_journal_mode(),
sqlite_journal_mode,
config.model_provider_id().to_string(),
)
.await
@@ -59,11 +62,14 @@ pub async fn init(config: &impl RolloutConfigView) -> Option<StateDbHandle> {
///
/// Prefer [`init`] unless the caller needs to surface the exact failure after
/// tracing or UI setup has completed.
pub async fn try_init(config: &impl RolloutConfigView) -> anyhow::Result<StateDbHandle> {
pub async fn try_init(
config: &impl RolloutConfigView,
sqlite_journal_mode: codex_state::RuntimeSqliteJournalMode,
) -> anyhow::Result<StateDbHandle> {
try_init_with_roots(
config.codex_home().to_path_buf(),
config.sqlite_home().to_path_buf(),
config.sqlite_journal_mode(),
sqlite_journal_mode,
config.model_provider_id().to_string(),
)
.await
@@ -217,7 +223,10 @@ fn emit_startup_warning(message: &str) {
///
/// Unlike [`init`], this helper does not run rollout backfill. It is for
/// optional local reads from non-owning contexts such as remote app-server mode.
pub async fn get_state_db(config: &impl RolloutConfigView) -> Option<StateDbHandle> {
pub async fn get_state_db(
config: &impl RolloutConfigView,
sqlite_journal_mode: codex_state::RuntimeSqliteJournalMode,
) -> Option<StateDbHandle> {
let state_path = codex_state::state_db_path(config.sqlite_home());
if !tokio::fs::try_exists(&state_path).await.unwrap_or(false) {
codex_state::record_fallback(
@@ -230,7 +239,7 @@ pub async fn get_state_db(config: &impl RolloutConfigView) -> Option<StateDbHand
let runtime = match codex_state::StateRuntime::init_with_journal_mode(
config.sqlite_home().to_path_buf(),
config.model_provider_id().to_string(),
config.sqlite_journal_mode(),
sqlite_journal_mode,
)
.await
{
+14 -13
View File
@@ -93,15 +93,6 @@ pub enum RuntimeSqliteJournalMode {
Delete,
}
impl RuntimeSqliteJournalMode {
fn to_sqlx(self) -> SqlxSqliteJournalMode {
match self {
Self::Wal => SqlxSqliteJournalMode::Wal,
Self::Delete => SqlxSqliteJournalMode::Delete,
}
}
}
#[derive(Clone, Copy)]
struct RuntimeDbSpec {
label: &'static str,
@@ -373,11 +364,17 @@ fn base_sqlite_options(
path: &Path,
journal_mode: RuntimeSqliteJournalMode,
) -> SqliteConnectOptions {
let (journal_mode, synchronous) = match journal_mode {
RuntimeSqliteJournalMode::Wal => (SqlxSqliteJournalMode::Wal, SqliteSynchronous::Normal),
RuntimeSqliteJournalMode::Delete => {
(SqlxSqliteJournalMode::Delete, SqliteSynchronous::Full)
}
};
SqliteConnectOptions::new()
.filename(path)
.create_if_missing(true)
.journal_mode(journal_mode.to_sqlx())
.synchronous(SqliteSynchronous::Normal)
.journal_mode(journal_mode)
.synchronous(synchronous)
.busy_timeout(Duration::from_secs(5))
.log_statements(LevelFilter::Off)
}
@@ -706,7 +703,7 @@ mod tests {
}
#[tokio::test]
async fn open_state_sqlite_honors_delete_journal_mode() {
async fn open_state_sqlite_honors_delete_journal_policy() {
let codex_home = unique_temp_dir();
tokio::fs::create_dir_all(&codex_home)
.await
@@ -726,8 +723,12 @@ mod tests {
.fetch_one(&pool)
.await
.expect("query journal mode");
let synchronous: i64 = sqlx::query_scalar("PRAGMA synchronous")
.fetch_one(&pool)
.await
.expect("query synchronous mode");
assert_eq!(journal_mode, "delete");
assert_eq!((journal_mode, synchronous), ("delete".to_string(), 2));
pool.close().await;
let _ = tokio::fs::remove_dir_all(codex_home).await;
+10 -7
View File
@@ -346,14 +346,17 @@ async fn init_state_db_for_app_server_target(
app_server_target: &AppServerTarget,
) -> std::io::Result<Option<StateDbHandle>> {
match app_server_target {
AppServerTarget::Embedded => state_db::try_init(config).await.map(Some).map_err(|err| {
std::io::Error::other(LocalStateDbStartupError::new(
codex_state::state_db_path(config.sqlite_home.as_path()),
err.to_string(),
))
}),
AppServerTarget::Embedded => state_db::try_init(config, config.sqlite_journal_mode)
.await
.map(Some)
.map_err(|err| {
std::io::Error::other(LocalStateDbStartupError::new(
codex_state::state_db_path(config.sqlite_home.as_path()),
err.to_string(),
))
}),
AppServerTarget::LocalDaemon { .. } | AppServerTarget::Remote { .. } => {
Ok(state_db::get_state_db(config).await)
Ok(state_db::get_state_db(config, config.sqlite_journal_mode).await)
}
}
}