58 lines
2.6 KiB
TypeScript
58 lines
2.6 KiB
TypeScript
import { cleanupOrphanedFiles, cleanupStaging, processFileDeletions } from "./files.js";
|
|
import { loadConfig, prepareDataDirectories, acquireInstanceLock } from "./config.js";
|
|
import { openDatabase } from "./db/index.js";
|
|
import { buildApp } from "./app.js";
|
|
import { cleanupOrphanedExports, expireExports, resumeExports } from "./exporter.js";
|
|
import { reconcileOrphanedUpdateJobs } from "./update-service.js";
|
|
|
|
const config = loadConfig();
|
|
prepareDataDirectories(config);
|
|
const releaseLock = acquireInstanceLock(config);
|
|
const database = openDatabase(config);
|
|
|
|
async function start() {
|
|
await cleanupStaging(config);
|
|
await cleanupOrphanedFiles(database.sqlite, config);
|
|
database.sqlite.prepare("DELETE FROM login_attempts WHERE window_start < ? AND (blocked_until IS NULL OR blocked_until < ?)").run(Date.now() - 24 * 60 * 60 * 1000, Date.now());
|
|
database.sqlite.prepare("DELETE FROM sessions WHERE idle_expires_at <= ? OR absolute_expires_at <= ?").run(Date.now(), Date.now());
|
|
await processFileDeletions(database.sqlite, config);
|
|
await expireExports(database.sqlite, config);
|
|
await cleanupOrphanedExports(database.sqlite, config);
|
|
await resumeExports(database.sqlite, config);
|
|
reconcileOrphanedUpdateJobs(database.sqlite, config);
|
|
const app = await buildApp(database, config);
|
|
const janitor = setInterval(() => {
|
|
void cleanupStaging(config);
|
|
void cleanupOrphanedFiles(database.sqlite, config);
|
|
database.sqlite.prepare("DELETE FROM login_attempts WHERE window_start < ? AND (blocked_until IS NULL OR blocked_until < ?)").run(Date.now() - 24 * 60 * 60 * 1000, Date.now());
|
|
database.sqlite.prepare("DELETE FROM sessions WHERE idle_expires_at <= ? OR absolute_expires_at <= ?").run(Date.now(), Date.now());
|
|
void processFileDeletions(database.sqlite, config);
|
|
void expireExports(database.sqlite, config);
|
|
void cleanupOrphanedExports(database.sqlite, config);
|
|
reconcileOrphanedUpdateJobs(database.sqlite, config);
|
|
}, 60_000);
|
|
const shutdown = async () => {
|
|
clearInterval(janitor);
|
|
await app.close().catch(() => undefined);
|
|
database.sqlite.close();
|
|
releaseLock();
|
|
};
|
|
process.once("SIGINT", () => void shutdown().finally(() => process.exit(0)));
|
|
process.once("SIGTERM", () => void shutdown().finally(() => process.exit(0)));
|
|
try {
|
|
await app.listen({ host: config.host, port: config.port });
|
|
} catch (error) {
|
|
clearInterval(janitor);
|
|
await app.close().catch(() => undefined);
|
|
throw error;
|
|
}
|
|
app.log.info(`TallyNote running at ${config.publicOrigin}`);
|
|
}
|
|
|
|
start().catch((error) => {
|
|
console.error(error);
|
|
database.sqlite.close();
|
|
releaseLock();
|
|
process.exitCode = 1;
|
|
});
|