disclaw/src/index.ts
Nick Tabeling dc4a1ef241 feat(runtime): add startup lockfile to prevent double-start
Implements acquireLock() in src/runtime/lockfile.ts that writes a PID-stamped
lock file under workspaces_root, detects live vs stale locks via process.kill(pid, 0),
and returns a release function. src/index.ts acquires the lock before DB init and
releases it in the graceful-shutdown handler. Four unit tests cover acquire, duplicate-
acquire rejection, stale-lock recovery, and release.
2026-04-09 11:49:17 +02:00

47 lines
1.3 KiB
TypeScript

import * as path from "path";
import { loadEnv, loadDisclawConfig } from "./config/loader";
import { DisclawDatabase } from "./db/database";
import { startBot } from "./bot";
import { acquireLock } from "./runtime/lockfile";
const ROOT_DIR = path.resolve(__dirname, "..");
async function main(): Promise<void> {
console.log("DisClaw starting...");
// 1. Load configuration
const envConfig = loadEnv(ROOT_DIR);
const disclawConfig = loadDisclawConfig(ROOT_DIR);
console.log(
`Config loaded. Workspaces root: ${disclawConfig.workspaces_root}`
);
// 2. Acquire startup lock (before DB init)
const lockRelease = await acquireLock(
path.join(disclawConfig.workspaces_root, ".disclaw.lock")
);
// 3. Initialize database
const dbPath = path.join(ROOT_DIR, "data", "disclaw.db");
const db = new DisclawDatabase(dbPath);
console.log(`Database initialized at ${dbPath}`);
// 4. Start Discord bot
await startBot(envConfig, disclawConfig, db);
// Graceful shutdown
const shutdown = (): void => {
console.log("\nShutting down...");
db.close();
lockRelease();
process.exit(0);
};
process.on("SIGINT", shutdown);
process.on("SIGTERM", shutdown);
}
main().catch((err) => {
console.error("Fatal error:", err);
process.exit(1);
});