Merge pull request #50 from Routstr/feat/update-restart

feat(update): restart daemons after update
This commit is contained in:
redshift
2026-07-08 08:52:13 +00:00
committed by GitHub
2 changed files with 129 additions and 2 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "routstrd",
"version": "0.3.6",
"version": "0.3.7",
"module": "src/index.ts",
"type": "module",
"private": false,
@@ -24,7 +24,7 @@
},
"dependencies": {
"@cashu/cashu-ts": "^4.3.0",
"@routstr/sdk": "^0.3.14",
"@routstr/sdk": "^0.3.15",
"applesauce-core": "^5.1.0",
"applesauce-relay": "^5.1.0",
"applesauce-wallet-connect": "^6.0.0",
+127
View File
@@ -103,6 +103,130 @@ async function installCocodOrExit(): Promise<void> {
console.log("cocod installed successfully.");
}
/**
* Restart the routstrd and cocod daemons after an update so the new
* binaries take effect immediately. Failures are collected and reported
* but never roll back the update itself.
*/
async function restartDaemonsAfterUpdate(): Promise<void> {
const config = await loadConfig();
const isRemote = !!config.daemonUrl;
const failures: string[] = [];
// --- routstrd daemon ---
if (isRemote) {
console.log("\nUsing remote daemon — skipping routstrd daemon restart.");
} else {
try {
const wasRunning = await isDaemonRunning();
if (!wasRunning) {
console.log("\nroutstrd daemon was not running — skipping restart.");
} else {
console.log("\nRestarting routstrd daemon...");
// Graceful stop — the /stop endpoint closes the HTTP server
// (draining active connections) then exits.
await callDaemon("/stop", { method: "POST" });
for (let i = 0; i < 50; i++) {
await new Promise((resolve) => setTimeout(resolve, 100));
if (!(await isDaemonRunning())) break;
}
if (await isDaemonRunning()) {
throw new Error("routstrd did not stop within 5 seconds");
}
console.log("routstrd daemon stopped.");
console.log("Starting routstrd daemon...");
await startDaemon({
port: String(config.port || 8008),
provider: config.provider || undefined,
});
console.log("routstrd daemon restarted.");
}
} catch (error) {
const msg = error instanceof Error ? error.message : String(error);
failures.push(`routstrd daemon: ${msg}`);
}
}
// --- cocod daemon ---
try {
const cocodExecutable = resolveCocodExecutable(config.cocodPath);
// Check whether cocod is currently running.
const pingProc = Bun.spawn([cocodExecutable, "ping"], {
stdout: "ignore",
stderr: "ignore",
});
const cocodWasRunning = (await pingProc.exited) === 0;
if (!cocodWasRunning) {
console.log("\ncocod daemon was not running — skipping restart.");
} else {
console.log("\nRestarting cocod daemon...");
const stopProc = Bun.spawn([cocodExecutable, "stop"], {
stdout: "inherit",
stderr: "inherit",
});
const stopCode = await stopProc.exited;
if (stopCode !== 0) {
throw new Error(`cocod stop exited with code ${stopCode}`);
}
console.log("cocod daemon stopped.");
// Start cocod in the background (detached, like the wallet client does).
const env = { ...process.env };
const startProc = Bun.spawn([cocodExecutable, "daemon"], {
stdout: "ignore",
stderr: "ignore",
stdin: "ignore",
detached: true,
env,
});
startProc.unref?.();
// Poll until cocod responds to ping (max ~10 s).
let started = false;
for (let i = 0; i < 100; i++) {
await new Promise((resolve) => setTimeout(resolve, 100));
const poll = Bun.spawn([cocodExecutable, "ping"], {
stdout: "ignore",
stderr: "ignore",
});
if ((await poll.exited) === 0) {
started = true;
break;
}
}
if (!started) {
throw new Error("cocod did not come back up within 10 seconds");
}
console.log("cocod daemon restarted.");
}
} catch (error) {
const msg = error instanceof Error ? error.message : String(error);
failures.push(`cocod daemon: ${msg}`);
}
// --- report ---
if (failures.length > 0) {
console.error("\n⚠ Some daemons failed to restart:");
for (const f of failures) {
console.error(` - ${f}`);
}
console.error(
"The update was applied but may not take effect until daemons are manually restarted.",
);
process.exit(1);
}
console.log("\n✓ All daemons restarted successfully.");
}
async function requireLocalDaemon(): Promise<void> {
const config = await loadConfig();
if (config.daemonUrl) {
@@ -264,6 +388,9 @@ program
console.log("cocod updated successfully.\n");
console.log("Both routstrd and cocod have been updated!");
// Restart daemons so the new binaries take effect immediately.
await restartDaemonsAfterUpdate();
});
program