mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-10 20:32:21 +08:00
refactor(backend): declarative effects (#8128)
* refactor(core): type notice statuses behind the frozen wire contract * refactor(utils): unified retry and strategy-list helpers * refactor(feat): declarative effect registry for verge and clash patches * refactor(core): derive refresh announcements from transaction commit * refactor(core): fold tray, hotkey, autostart updates into effect ensures * refactor(utils): migrate remaining bounded retry loops * docs: add src-tauri architecture guardrails * refactor(core): coalesce burst refresh announcements * refactor(core): complete bounded service retry migration * ci(backend): add architecture ban gates * test(feat): freeze representative effect registry mappings * docs(backend): record dead wire contract entries * chore(core): document watcher exit conditions * fix(backend): preserve applied state across later failures * fix(config): retain runtime after an applied core replacement * refactor(backend): flatten refresh publication and retry policies * docs(backend): focus guardrails on architecture ownership * refactor(effects): use one execution order * fix(config): publish retained runtime and reconcile proxy settings
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use super::resolve;
|
||||
use crate::{
|
||||
config::{Config, DEFAULT_PAC, MixedPort},
|
||||
module::lightweight,
|
||||
core::lightweight,
|
||||
process::AsyncHandler,
|
||||
utils::{dirs, window_manager::WindowManager},
|
||||
};
|
||||
@@ -54,20 +54,34 @@ pub async fn check_singleton() -> Result<SingletonDisposition> {
|
||||
.context("failed to initialize singleton lock")?;
|
||||
if !try_lock_instance(&lock).context("failed to acquire singleton lock")? {
|
||||
let deadline = std::time::Instant::now() + Duration::from_secs(20);
|
||||
loop {
|
||||
if std::time::Instant::now() >= deadline {
|
||||
bail!("another app instance is starting");
|
||||
}
|
||||
// Retry the lock: during restart, the old server stops before releasing it.
|
||||
if try_lock_instance(&lock).context("failed to acquire singleton lock")? {
|
||||
break;
|
||||
}
|
||||
if let Ok(record) = read_instance_record(&record_path)
|
||||
&& notify_existing_instance(&record).await
|
||||
{
|
||||
return Ok(SingletonDisposition::Secondary);
|
||||
}
|
||||
tokio::time::sleep(Duration::from_millis(50)).await;
|
||||
use crate::utils::retry::{RetryError, RetryPolicy, retry};
|
||||
let secondary = retry(
|
||||
RetryPolicy::fixed(
|
||||
std::num::NonZeroUsize::MIN.saturating_add(400),
|
||||
Duration::from_millis(50),
|
||||
),
|
||||
|_| async {
|
||||
if std::time::Instant::now() >= deadline {
|
||||
return Err(RetryError::Stop(anyhow::anyhow!("another app instance is starting")));
|
||||
}
|
||||
// A restarting primary releases the lock after spawning us, with its server down.
|
||||
if try_lock_instance(&lock)
|
||||
.context("failed to acquire singleton lock")
|
||||
.map_err(RetryError::Stop)?
|
||||
{
|
||||
return Ok(false);
|
||||
}
|
||||
if let Ok(record) = read_instance_record(&record_path)
|
||||
&& notify_existing_instance(&record).await
|
||||
{
|
||||
return Ok(true);
|
||||
}
|
||||
Err(RetryError::Retry(anyhow::anyhow!("another app instance is starting")))
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
if secondary {
|
||||
return Ok(SingletonDisposition::Secondary);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user