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.
47 lines
1.3 KiB
TypeScript
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);
|
|
});
|