feat(lock): implémentation lock inter-process app-data-dir V1 — acquisition non-bloquante avec RAII

This commit is contained in:
2026-07-27 13:57:58 +02:00
parent 865f90eafd
commit 0b83b5bbd2
3 changed files with 246 additions and 0 deletions

View File

@ -128,6 +128,13 @@ pub fn run_from_args(args: Vec<String>) -> ExitCode {
return ExitCode::from(2);
}
};
let _app_data_lock = match backend::acquire_app_data_dir_lock(&config.app_data_dir) {
Ok(lock) => lock,
Err(err) => {
eprintln!("idea --serve: {}", serve_app_data_lock_message(&err));
return ExitCode::from(1);
}
};
match tokio::runtime::Builder::new_multi_thread()
.enable_all()
@ -147,6 +154,19 @@ pub fn run_from_args(args: Vec<String>) -> ExitCode {
}
}
fn serve_app_data_lock_message(err: &backend::AppDataDirLockError) -> String {
match err {
backend::AppDataDirLockError::Contended { lock_path } => format!(
"app-data dir is already locked at {}; another IdeA instance is using this app-data-dir",
lock_path.display()
),
backend::AppDataDirLockError::Io { lock_path, source } => format!(
"failed to access app-data lock at {}: {source}",
lock_path.display()
),
}
}
/// Configuration shared by the standalone and embedded web-server entry points.
#[derive(Clone, Debug)]
pub struct ServerConfig {
@ -5036,6 +5056,31 @@ mod tests {
}
}
#[test]
fn idea_serve_lock_failure_stops_before_backend_store_writes() {
let app_data_dir =
std::env::temp_dir().join(format!("idea-server-lock-{}", Uuid::new_v4()));
let web_root = create_web_root();
let _guard = backend::acquire_app_data_dir_lock(&app_data_dir).unwrap();
let code = run_from_args(vec![
"--app-data-dir".to_owned(),
app_data_dir.to_string_lossy().into_owned(),
"--web-root".to_owned(),
web_root.to_string_lossy().into_owned(),
]);
assert_eq!(code, ExitCode::from(1));
let mut entries = std::fs::read_dir(&app_data_dir)
.unwrap()
.map(|entry| entry.unwrap().file_name().to_string_lossy().into_owned())
.collect::<Vec<_>>();
entries.sort();
assert_eq!(entries, vec!["idea.lock"]);
let _ = std::fs::remove_dir_all(app_data_dir);
let _ = std::fs::remove_dir_all(web_root);
}
#[test]
fn default_app_data_dir_uses_tauri_identifier_with_env_precedence() {
let _lock = ENV_LOCK.lock().unwrap();