forked from Keelrleek/SoulStream
the freenet layer: the app supervises its own peer, so a new release no longer quietly ends it
This commit is contained in:
1 parent
733e3b57a8
commit
07227a90a7
1 file changed
+58
-2
@@ -138,6 +138,11 @@ pub struct NodeInfo {
|
||||
const TELEMETRY_ON: &str = "telemetry-enabled = true";
|
||||
const TELEMETRY_OFF: &str = "telemetry-enabled = false";
|
||||
const FIRST_BOOT_WAIT: Duration = Duration::from_secs(20);
|
||||
/// What the node returns when it has spotted a newer release and wants one.
|
||||
const EXIT_UPDATE_NEEDED: i32 = 42;
|
||||
/// How long to watch a fresh child for that exit. The check runs at startup,
|
||||
/// before any network work, so this only has to outlast process spawn.
|
||||
const UPDATE_EXIT_WAIT: Duration = Duration::from_secs(2);
|
||||
|
||||
struct NodeDirs {
|
||||
base: PathBuf,
|
||||
@@ -226,6 +231,57 @@ fn spawn_node(bin: &Path, dirs: &NodeDirs, log: &Path) -> Result<Child, String>
|
||||
.map_err(|e| format!("start the peer: {e}"))
|
||||
}
|
||||
|
||||
/// Spawn the peer and be its supervisor.
|
||||
///
|
||||
/// A node that spots a newer release exits with code 42 and waits for someone
|
||||
/// to apply it; Freenet ships that someone as a system service. We cannot use
|
||||
/// one: `freenet service install` takes no `--config-dir`/`--data-dir`, so its
|
||||
/// node would run on the default folders — a different peer with none of this
|
||||
/// app's identity — and fight ours for port 7509. The app owns the node, so
|
||||
/// the app is the supervisor.
|
||||
///
|
||||
/// Without this, an update simply ends the layer: 0.2.133 landed on
|
||||
/// 2026-09-03 and the pinned 0.2.132 exited at every launch, leaving the node
|
||||
/// permanently absent with only a line in node.log to say why. One update, one
|
||||
/// restart, no recursion — if the fresh binary asks again we let it be, rather
|
||||
/// than loop.
|
||||
fn spawn_supervised(bin: &Path, dirs: &NodeDirs, log: &Path) -> Result<Child, String> {
|
||||
let mut child = spawn_node(bin, dirs, log)?;
|
||||
let deadline = Instant::now() + UPDATE_EXIT_WAIT;
|
||||
while Instant::now() < deadline {
|
||||
match child.try_wait() {
|
||||
Ok(Some(status)) if status.code() == Some(EXIT_UPDATE_NEEDED) => {
|
||||
log::warn!("freenet node: exit 42 — a newer release is out; applying it");
|
||||
apply_update(bin)?;
|
||||
let child = spawn_node(bin, dirs, log)?;
|
||||
log::info!("freenet node: updated and restarted (pid {})", child.id());
|
||||
return Ok(child);
|
||||
}
|
||||
// Any other early exit is the caller's problem to report, and a
|
||||
// live child is the normal case.
|
||||
Ok(Some(_)) | Err(_) => break,
|
||||
Ok(None) => std::thread::sleep(Duration::from_millis(100)),
|
||||
}
|
||||
}
|
||||
Ok(child)
|
||||
}
|
||||
|
||||
/// Run the node's own updater. Blocking — this whole path is already on a
|
||||
/// blocking task, and the download takes as long as it takes.
|
||||
fn apply_update(bin: &Path) -> Result<(), String> {
|
||||
let out = quiet(Command::new(bin))
|
||||
.arg("update")
|
||||
.output()
|
||||
.map_err(|e| format!("could not run freenet update: {e}"))?;
|
||||
if !out.status.success() {
|
||||
return Err(format!(
|
||||
"freenet update failed: {}",
|
||||
String::from_utf8_lossy(&out.stderr).trim()
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn node_info(app: &tauri::AppHandle, state: &AppState) -> Result<NodeInfo, String> {
|
||||
let dirs = node_dirs(app)?;
|
||||
let bin = find_binary(app);
|
||||
@@ -272,7 +328,7 @@ async fn start_node_inner(app: &tauri::AppHandle) -> Result<Child, String> {
|
||||
let config = dirs.config.join("config.toml");
|
||||
if !config.is_file() {
|
||||
let first_log = dirs.base.join("first-boot.log");
|
||||
let mut first = spawn_node(&bin, &dirs, &first_log)?;
|
||||
let mut first = spawn_supervised(&bin, &dirs, &first_log)?;
|
||||
let deadline = Instant::now() + FIRST_BOOT_WAIT;
|
||||
while !config.is_file() && Instant::now() < deadline {
|
||||
if let Ok(Some(status)) = first.try_wait() {
|
||||
@@ -291,7 +347,7 @@ async fn start_node_inner(app: &tauri::AppHandle) -> Result<Child, String> {
|
||||
log::info!("freenet node: first boot wrote {}", config.display());
|
||||
}
|
||||
pin_telemetry_off(&config)?;
|
||||
let child = spawn_node(&bin, &dirs, &dirs.base.join("node.log"))?;
|
||||
let child = spawn_supervised(&bin, &dirs, &dirs.base.join("node.log"))?;
|
||||
log::info!("freenet node started (pid {}) from {}", child.id(), bin.display());
|
||||
Ok(child)
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user