full sync

This commit is contained in:
larssand
2026-03-14 09:51:35 +01:00
commit 3b0af41466
41 changed files with 102303 additions and 0 deletions

153
scripts/serverctl.js Normal file
View File

@@ -0,0 +1,153 @@
const fs = require("fs");
const path = require("path");
const { spawn } = require("child_process");
const ROOT = path.join(__dirname, "..");
const DATA_DIR = path.join(ROOT, "data");
const LOG_DIR = path.join(ROOT, "logs");
const PID_FILE = path.join(DATA_DIR, "server.pid");
const OUT_LOG = path.join(LOG_DIR, "server.out.log");
const ERR_LOG = path.join(LOG_DIR, "server.err.log");
fs.mkdirSync(DATA_DIR, { recursive: true });
fs.mkdirSync(LOG_DIR, { recursive: true });
const command = process.argv[2] || "status";
if (command === "start") {
start();
} else if (command === "stop") {
stop();
} else if (command === "restart") {
restart();
} else if (command === "status") {
status();
} else {
console.error(`Unknown command: ${command}`);
process.exit(1);
}
function start() {
const pid = readPid();
if (pid && isRunning(pid)) {
console.log(`Live Event server already running with PID ${pid}`);
console.log(`Logs: ${OUT_LOG}`);
return;
}
cleanupStalePid();
const stdoutFd = fs.openSync(OUT_LOG, "a");
const stderrFd = fs.openSync(ERR_LOG, "a");
const child = spawn(process.execPath, ["server.js"], {
cwd: ROOT,
detached: true,
windowsHide: true,
stdio: ["ignore", stdoutFd, stderrFd],
env: {
...process.env,
RC_TIMING_PID_FILE: PID_FILE,
},
});
child.unref();
fs.writeFileSync(PID_FILE, `${child.pid}\n`);
console.log(`Live Event server started in background`);
console.log(`PID: ${child.pid}`);
console.log(`Logs: ${OUT_LOG}`);
}
async function stop() {
const pid = readPid();
if (!pid) {
console.log("Live Event server is not running");
return;
}
if (!isRunning(pid)) {
cleanupStalePid();
console.log("Removed stale pid file");
return;
}
try {
process.kill(pid, "SIGTERM");
} catch (error) {
console.error(`Could not stop PID ${pid}: ${error instanceof Error ? error.message : String(error)}`);
process.exit(1);
}
const stopped = await waitForExit(pid, 5000);
if (!stopped && process.platform !== "win32") {
try {
process.kill(pid, "SIGKILL");
} catch {
// ignore
}
await waitForExit(pid, 1000);
}
cleanupStalePid();
console.log(`Live Event server stopped`);
}
async function restart() {
await stop();
start();
}
function status() {
const pid = readPid();
if (pid && isRunning(pid)) {
console.log(`Live Event server is running`);
console.log(`PID: ${pid}`);
console.log(`Logs: ${OUT_LOG}`);
return;
}
cleanupStalePid();
console.log("Live Event server is not running");
}
function readPid() {
if (!fs.existsSync(PID_FILE)) {
return null;
}
const raw = fs.readFileSync(PID_FILE, "utf8").trim();
const pid = Number(raw);
return Number.isFinite(pid) && pid > 0 ? pid : null;
}
function isRunning(pid) {
try {
process.kill(pid, 0);
return true;
} catch {
return false;
}
}
function cleanupStalePid() {
const pid = readPid();
if (!pid || !isRunning(pid)) {
fs.rmSync(PID_FILE, { force: true });
}
}
function waitForExit(pid, timeoutMs) {
return new Promise((resolve) => {
const started = Date.now();
const timer = setInterval(() => {
if (!isRunning(pid)) {
clearInterval(timer);
resolve(true);
return;
}
if (Date.now() - started >= timeoutMs) {
clearInterval(timer);
resolve(false);
}
}, 150);
});
}