From a81b1aa5a6f339e4abd0d65d9fa66c41083022fd Mon Sep 17 00:00:00 2001 From: Aiden McClelland Date: Fri, 13 Mar 2026 12:03:37 -0600 Subject: [PATCH] feat: wait for db commit after tunnel add/remove Add a typed DbWatch at the end of add_tunnel and remove_tunnel that waits up to 15s for the sync loop to commit the gateway state change to patch-db before returning. --- core/locales/i18n.yaml | 15 +++++++++++ core/src/net/tunnel.rs | 56 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/core/locales/i18n.yaml b/core/locales/i18n.yaml index 856617307..0b7a688a2 100644 --- a/core/locales/i18n.yaml +++ b/core/locales/i18n.yaml @@ -1379,6 +1379,21 @@ net.tor.client-error: fr_FR: "Erreur du client Tor : %{error}" pl_PL: "Błąd klienta Tor: %{error}" +# net/tunnel.rs +net.tunnel.timeout-waiting-for-add: + en_US: "timed out waiting for gateway %{gateway} to appear in database" + de_DE: "Zeitüberschreitung beim Warten auf das Erscheinen von Gateway %{gateway} in der Datenbank" + es_ES: "se agotó el tiempo esperando que la puerta de enlace %{gateway} aparezca en la base de datos" + fr_FR: "délai d'attente dépassé pour l'apparition de la passerelle %{gateway} dans la base de données" + pl_PL: "upłynął limit czasu oczekiwania na pojawienie się bramy %{gateway} w bazie danych" + +net.tunnel.timeout-waiting-for-remove: + en_US: "timed out waiting for gateway %{gateway} to be removed from database" + de_DE: "Zeitüberschreitung beim Warten auf das Entfernen von Gateway %{gateway} aus der Datenbank" + es_ES: "se agotó el tiempo esperando que la puerta de enlace %{gateway} sea eliminada de la base de datos" + fr_FR: "délai d'attente dépassé pour la suppression de la passerelle %{gateway} de la base de données" + pl_PL: "upłynął limit czasu oczekiwania na usunięcie bramy %{gateway} z bazy danych" + # net/wifi.rs net.wifi.ssid-no-special-characters: en_US: "SSID may not have special characters" diff --git a/core/src/net/tunnel.rs b/core/src/net/tunnel.rs index da0f6d84c..694434514 100644 --- a/core/src/net/tunnel.rs +++ b/core/src/net/tunnel.rs @@ -1,3 +1,5 @@ +use std::time::Duration; + use clap::Parser; use imbl_value::InternedString; use patch_db::json_ptr::JsonPointer; @@ -8,7 +10,9 @@ use ts_rs::TS; use crate::GatewayId; use crate::context::{CliContext, RpcContext}; -use crate::db::model::public::{GatewayType, NetworkInterfaceInfo, NetworkInterfaceType}; +use crate::db::model::public::{ + GatewayType, NetworkInfo, NetworkInterfaceInfo, NetworkInterfaceType, +}; use crate::net::host::all_hosts; use crate::prelude::*; use crate::util::Invoke; @@ -139,6 +143,34 @@ pub async fn add_tunnel( .result?; } + // Wait for the sync loop to fully commit gateway state (addresses, hosts) + // to the database, with a 15-second timeout. + if tokio::time::timeout(Duration::from_secs(15), async { + let mut watch = ctx + .db + .watch("/public/serverInfo/network".parse::().unwrap()) + .await + .typed::(); + loop { + if watch + .peek()? + .as_gateways() + .as_idx(&iface) + .and_then(|g| g.as_ip_info().transpose_ref()) + .is_some() + { + break; + } + watch.changed().await?; + } + Ok::<_, Error>(()) + }) + .await + .is_err() + { + tracing::warn!("{}", t!("net.tunnel.timeout-waiting-for-add", gateway = iface.as_str())); + } + Ok(iface) } @@ -224,5 +256,27 @@ pub async fn remove_tunnel( .await .result?; + // Wait for the sync loop to fully commit gateway removal to the database, + // with a 15-second timeout. + if tokio::time::timeout(Duration::from_secs(15), async { + let mut watch = ctx + .db + .watch("/public/serverInfo/network".parse::().unwrap()) + .await + .typed::(); + loop { + if watch.peek()?.as_gateways().as_idx(&id).is_none() { + break; + } + watch.changed().await?; + } + Ok::<_, Error>(()) + }) + .await + .is_err() + { + tracing::warn!("{}", t!("net.tunnel.timeout-waiting-for-remove", gateway = id.as_str())); + } + Ok(()) }