[feat] add atomic flag to handle .last_model cleanup logic safely

This commit is contained in:
2025-08-08 09:55:28 +02:00
parent 02c15ba27a
commit 96046be3a4

View File

@@ -8,11 +8,14 @@ use anyhow::{anyhow, Context, Result};
use clap::Parser; use clap::Parser;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use chrono::Local; use chrono::Local;
use std::sync::atomic::{AtomicBool, Ordering};
use whisper_rs::{FullParams, SamplingStrategy, WhisperContext, WhisperContextParameters}; use whisper_rs::{FullParams, SamplingStrategy, WhisperContext, WhisperContextParameters};
mod models; mod models;
static LAST_MODEL_WRITTEN: AtomicBool = AtomicBool::new(false);
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(name = "merge_transcripts", version, about = "Merge multiple JSON transcripts into one or transcribe audio using native whisper")] #[command(name = "merge_transcripts", version, about = "Merge multiple JSON transcripts into one or transcribe audio using native whisper")]
struct Args { struct Args {
@@ -149,6 +152,7 @@ fn find_model_file() -> Result<PathBuf> {
if p.is_file() { if p.is_file() {
// persist selection // persist selection
let _ = std::fs::write(models_dir.join(".last_model"), p.display().to_string()); let _ = std::fs::write(models_dir.join(".last_model"), p.display().to_string());
LAST_MODEL_WRITTEN.store(true, Ordering::Relaxed);
return Ok(p); return Ok(p);
} }
} }
@@ -206,6 +210,7 @@ fn find_model_file() -> Result<PathBuf> {
if candidates.len() == 1 { if candidates.len() == 1 {
let only = candidates.remove(0); let only = candidates.remove(0);
let _ = std::fs::write(models_dir.join(".last_model"), only.display().to_string()); let _ = std::fs::write(models_dir.join(".last_model"), only.display().to_string());
LAST_MODEL_WRITTEN.store(true, Ordering::Relaxed);
return Ok(only); return Ok(only);
} }
@@ -240,6 +245,7 @@ fn find_model_file() -> Result<PathBuf> {
} }
let chosen = candidates.swap_remove(sel - 1); let chosen = candidates.swap_remove(sel - 1);
let _ = std::fs::write(models_dir.join(".last_model"), chosen.display().to_string()); let _ = std::fs::write(models_dir.join(".last_model"), chosen.display().to_string());
LAST_MODEL_WRITTEN.store(true, Ordering::Relaxed);
Ok(chosen) Ok(chosen)
} }
@@ -339,18 +345,18 @@ struct LastModelCleanup {
} }
impl Drop for LastModelCleanup { impl Drop for LastModelCleanup {
fn drop(&mut self) { fn drop(&mut self) {
if LAST_MODEL_WRITTEN.load(Ordering::Relaxed) {
let _ = std::fs::remove_file(&self.path); let _ = std::fs::remove_file(&self.path);
} }
}
} }
fn main() -> Result<()> { fn main() -> Result<()> {
let args = Args::parse(); let args = Args::parse();
// Remove stale last_model from previous runs and set up cleanup on exit // Defer cleanup of .last_model until program exit (after all runs within this process)
let models_dir = Path::new("models"); let models_dir = Path::new("models");
let last_model_path = models_dir.join(".last_model"); let last_model_path = models_dir.join(".last_model");
// Best-effort cleanup at start
let _ = std::fs::remove_file(&last_model_path);
// Ensure cleanup at end of program, regardless of exit path // Ensure cleanup at end of program, regardless of exit path
let _last_model_cleanup = LastModelCleanup { path: last_model_path.clone() }; let _last_model_cleanup = LastModelCleanup { path: last_model_path.clone() };