Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/codex_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ pub(crate) fn read_provider_from_config(
.unwrap_or_else(|| DEFAULT_PROVIDER.to_string()))
}

// Legacy single-store path resolver. The multi-store path now goes through
// `discover_stores` / `configured_sqlite_home`; this helper is only kept for the
// resolution unit tests, so it is gated to test builds to stay clippy-clean.
#[cfg(test)]
pub(crate) fn resolve_sqlite_path(
codex_home: &Path,
profile_override: Option<&str>,
Expand Down Expand Up @@ -188,6 +192,9 @@ fn trimmed_string(value: &str) -> Option<String> {
}
}

// Test-only sibling of `configured_sqlite_home_from` that applies the
// `codex_home` default. Production code uses `configured_sqlite_home`.
#[cfg(test)]
pub(crate) fn resolve_sqlite_home_from_config(
codex_home: &Path,
config_sqlite_home: Option<&str>,
Expand Down
5 changes: 4 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ use output::uninstall_launchd_done;
use rollout::RolloutProgressConfig;
use rollout::RolloutScope;
use rollout::prepare_bucket_padding;
use sync::DEFAULT_BACKFILL_WAIT;
use sync::ReconcileStatus;
use sync::collect_status;
use sync::reconcile_all_stores_with_backup;
Expand Down Expand Up @@ -91,10 +92,11 @@ fn run() -> Result<ExitCode> {
cli.profile.as_deref(),
rollout_scope,
DEFAULT_BUCKET_PADDING_BYTES,
DEFAULT_BACKFILL_WAIT,
progress,
)?;
print_multi_sync_summary(locale, sync_complete_title(locale), &summary);
if sqlite_only && summary.touches_app_store(&codex_home) {
if sqlite_only && summary.app_store_updated(&codex_home) {
eprintln!("{}", sqlite_only_app_warning(locale));
}
Ok(exit_code_for(summary.status()))
Expand All @@ -121,6 +123,7 @@ fn run() -> Result<ExitCode> {
cli.profile.as_deref(),
RolloutScope::AllRows,
padding_bytes,
DEFAULT_BACKFILL_WAIT,
Some(RolloutProgressConfig { locale }),
)?;
print_multi_sync_summary(locale, bucket_switch_complete_title(locale), &summary);
Expand Down
79 changes: 16 additions & 63 deletions src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::service::ServiceInstallSummary;
use crate::service::ServiceManager;
use crate::sync::MultiReconcileSummary;
use crate::sync::ReconcileStatus;
use crate::sync::ReconcileSummary;
use crate::sync::StatusSummary;
use crate::sync::StoreOutcome;

Expand Down Expand Up @@ -128,66 +127,6 @@ pub(crate) fn rollout_progress_message(
}
}

pub(crate) fn print_sync_summary(locale: Locale, title: &str, summary: &ReconcileSummary) {
println!("{title}");
println!(
"{}: {}",
status_target_provider_label(locale),
summary.provider
);
println!(
"{}: {}",
sync_rows_updated_label(locale),
summary.changed_rows
);
if summary.checked_rollouts > 0 || summary.changed_rollouts > 0 {
println!(
"{}: {}",
sync_rollouts_checked_label(locale),
summary.checked_rollouts
);
println!(
"{}: {}",
sync_rollouts_updated_label(locale),
summary.changed_rollouts
);
if summary.prepared_rollouts > 0 {
println!(
"{}: {}",
sync_rollouts_prepared_label(locale),
summary.prepared_rollouts
);
}
if summary.skipped_rollouts > 0 {
println!(
"{}: {}",
sync_rollouts_skipped_label(locale),
summary.skipped_rollouts
);
}
}
println!(
"{}: {}",
status_total_threads_label(locale),
summary.total_rows
);
println!(
"{}: {} ms",
sync_elapsed_label(locale),
summary.elapsed.as_millis()
);
if let Some(backup_path) = &summary.backup_path {
println!("{}: {}", sync_backup_label(locale), backup_path.display());
}
if let Some(journal_path) = &summary.rollout_journal_path {
println!(
"{}: {}",
sync_rollout_journal_label(locale),
journal_path.display()
);
}
}

pub(crate) fn print_multi_sync_summary(
locale: Locale,
title: &str,
Expand Down Expand Up @@ -252,6 +191,9 @@ pub(crate) fn print_multi_sync_summary(
);
}
}
StoreOutcome::Skipped => {
println!(" {}", sync_store_skipped_label(locale));
}
StoreOutcome::Failed { error } => {
println!(" {}: {}", sync_store_failed_label(locale), error);
}
Expand Down Expand Up @@ -941,15 +883,26 @@ pub(crate) fn sync_store_failed_label(locale: Locale) -> &'static str {
}
}

pub(crate) fn sync_store_skipped_label(locale: Locale) -> &'static str {
match locale {
Locale::En => {
"Skipped — a Codex backfill has not completed; threadripper avoids racing the rebuild. Re-run once Codex finishes (if it keeps skipping, check whether the backfill is stuck)."
}
Locale::ZhHans => {
"已跳过 —— Codex backfill 尚未完成;threadripper 不与重建竞态。待 Codex 完成后重跑(若持续跳过,请检查 backfill 是否卡住)。"
}
}
}

pub(crate) fn reconcile_status_line(locale: Locale, status: ReconcileStatus) -> String {
match (status, locale) {
(ReconcileStatus::Full, Locale::En) => "Result: all stores updated.".to_string(),
(ReconcileStatus::Full, Locale::ZhHans) => "结果:所有库均已更新。".to_string(),
(ReconcileStatus::Partial, Locale::En) => {
"Result: PARTIAL — some stores updated, at least one failed (see above). Re-run after resolving the failure.".to_string()
"Result: PARTIAL — some stores updated, at least one was skipped or failed (see above). Re-run after it is resolved.".to_string()
}
(ReconcileStatus::Partial, Locale::ZhHans) => {
"结果:部分成功 —— 部分库已更新,至少一个失败(见上)。解决后请重跑。".to_string()
"结果:部分成功 —— 部分库已更新,至少一个被跳过或失败(见上)。解决后请重跑。".to_string()
}
(ReconcileStatus::Failed, Locale::En) => {
"Result: FAILED — no store could be updated.".to_string()
Expand Down
1 change: 1 addition & 0 deletions src/rollout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ enum RolloutChangeMode {
InPlace,
}

#[cfg(test)]
pub(crate) fn reconcile_rollout_metadata_from_sqlite_with_progress(
sqlite_path: &Path,
_codex_home: &Path,
Expand Down
9 changes: 8 additions & 1 deletion src/state_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ pub(crate) fn inspect_sqlite_distribution(
/// callers can treat "no backfill machinery" and "complete" distinctly. Opens
/// read-only to avoid contending with an in-progress rebuild.
pub(crate) fn read_backfill_status(sqlite_path: &Path) -> Result<Option<String>> {
read_backfill_status_with_timeout(sqlite_path, Duration::from_millis(2_000))
}

pub(crate) fn read_backfill_status_with_timeout(
sqlite_path: &Path,
busy_timeout: Duration,
) -> Result<Option<String>> {
if !sqlite_path.exists() {
return Ok(None);
}
Expand All @@ -60,7 +67,7 @@ pub(crate) fn read_backfill_status(sqlite_path: &Path) -> Result<Option<String>>
OpenFlags::SQLITE_OPEN_READ_ONLY | OpenFlags::SQLITE_OPEN_NO_MUTEX,
)
.with_context(|| format!("failed to open {}", sqlite_path.display()))?;
connection.busy_timeout(Duration::from_millis(2_000))?;
connection.busy_timeout(busy_timeout)?;
let has_table: Option<i64> = connection
.query_row(
"SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'backfill_state'",
Expand Down
Loading