mirror of
https://github.com/Routstr/routstrd.git
synced 2026-08-09 03:44:38 +00:00
Merge pull request #50 from Routstr/feat/update-restart
feat(update): restart daemons after update
This commit is contained in:
+2
-2
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user