fix7: продакшен-реализация полного reconcile swap и интеграций
- Полностью переписан swap-модуль в режиме exclusive ownership\n- Добавлены verify/checks, статус фактического swap-state и drift\n- Интегрирован ensure-swap в daemon и systemd ExecStartPre\n- Усилен lock API (таймауты) и применение в traffic/firewall/swap\n- Усилен parser firewall (JSON-first + устойчивый text fallback)\n- Обновлены config validation, runtime tools и default priority\n- Синхронизированы docs и build/package hygiene\n- Удалены member Cargo.lock в пользу корневого lockfile
This commit is contained in:
@@ -2,6 +2,8 @@ use std::{
|
||||
fs::{self, OpenOptions},
|
||||
io::Write,
|
||||
path::Path,
|
||||
thread,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
pub struct FileLock {
|
||||
@@ -10,6 +12,29 @@ pub struct FileLock {
|
||||
|
||||
impl FileLock {
|
||||
pub fn acquire(path: &str) -> anyhow::Result<Self> {
|
||||
Self::acquire_timeout(path, Duration::from_secs(0))
|
||||
}
|
||||
|
||||
pub fn acquire_timeout(path: &str, timeout: Duration) -> anyhow::Result<Self> {
|
||||
let deadline = Instant::now() + timeout;
|
||||
loop {
|
||||
match Self::try_acquire_once(path) {
|
||||
Ok(lock) => return Ok(lock),
|
||||
Err(e) => {
|
||||
let msg = e.to_string();
|
||||
if !msg.contains("lock already exists") {
|
||||
return Err(e);
|
||||
}
|
||||
if Instant::now() >= deadline {
|
||||
anyhow::bail!("lock busy timeout: {path}");
|
||||
}
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_acquire_once(path: &str) -> anyhow::Result<Self> {
|
||||
let p = Path::new(path);
|
||||
if let Some(parent) = p.parent() {
|
||||
fs::create_dir_all(parent)?;
|
||||
@@ -66,4 +91,12 @@ mod tests {
|
||||
let second = FileLock::acquire(&p);
|
||||
assert!(second.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn acquire_timeout_times_out_for_live_lock() {
|
||||
let p = format!("/tmp/awg2_harness_lock_test_timeout_{}", std::process::id());
|
||||
let _first = FileLock::acquire(&p).expect("first lock");
|
||||
let second = FileLock::acquire_timeout(&p, Duration::from_millis(250));
|
||||
assert!(second.is_err());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user