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:
2026-05-11 17:30:15 +05:00
parent 819cc9c308
commit 7a4e9764b1
17 changed files with 842 additions and 957 deletions
+33
View File
@@ -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());
}
}