From 479ce1b9215d181180f494bb1f389412b4c59fd8 Mon Sep 17 00:00:00 2001 From: Anthony G <1@anthony.sh> Date: Mon, 10 Aug 2026 14:49:28 +0200 Subject: [PATCH] feat: add cron cleanup and worker-check scripts --- tsconfig.json | 6 +++--- worker/cron-check.ts | 40 ++++++++++++++++++++++++++++++++++++++++ worker/cron-cleanup.ts | 29 +++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 worker/cron-check.ts create mode 100644 worker/cron-cleanup.ts diff --git a/tsconfig.json b/tsconfig.json index 17cd6ab..1acc981 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,8 +7,8 @@ "strict": true, "noEmit": true, "esModuleInterop": true, - "module": "commonjs", - "moduleResolution": "node", + "module": "node16", + "moduleResolution": "node16", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", @@ -18,5 +18,5 @@ } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], - "exclude": ["node_modules"] + "exclude": ["node_modules", "**/__tests__/**"] } diff --git a/worker/cron-check.ts b/worker/cron-check.ts new file mode 100644 index 0000000..cb86dde --- /dev/null +++ b/worker/cron-check.ts @@ -0,0 +1,40 @@ +import { existsSync, readFileSync, writeFileSync } from 'fs' +import { spawn } from 'child_process' +import path from 'path' + +const PID_FILE = path.join(__dirname, 'worker.pid') + +function isRunning(pid: number): boolean { + try { + process.kill(pid, 0) + return true + } catch { + return false + } +} + +if (existsSync(PID_FILE)) { + const pid = parseInt(readFileSync(PID_FILE, 'utf-8').trim(), 10) + if (!isNaN(pid) && isRunning(pid)) { + console.log(`[cron-check] worker already running (PID ${pid})`) + process.exit(0) + } +} + +const child = spawn( + 'node', + [ + '-r', 'ts-node/register', + '-r', 'tsconfig-paths/register', + path.join(__dirname, 'index.ts'), + ], + { detached: true, stdio: 'ignore' } +) +child.unref() + +if (child.pid) { + writeFileSync(PID_FILE, String(child.pid)) + console.log(`[cron-check] worker started (PID ${child.pid})`) +} + +process.exit(0) diff --git a/worker/cron-cleanup.ts b/worker/cron-cleanup.ts new file mode 100644 index 0000000..2fdbde1 --- /dev/null +++ b/worker/cron-cleanup.ts @@ -0,0 +1,29 @@ +import 'dotenv/config' +import { prisma } from '@/lib/prisma' +import { config } from '../config/app.config' +import { unlinkSync, existsSync } from 'fs' + +async function cleanup() { + const cutoff = new Date( + Date.now() - config.DOWNLOAD_LINK_TTL_HOURS * 60 * 60 * 1000 + ) + + const expired = await prisma.download.findMany({ + where: { status: 'DONE', completedAt: { lt: cutoff } }, + select: { id: true, filePath: true }, + }) + + for (const dl of expired) { + if (dl.filePath && existsSync(dl.filePath)) { + unlinkSync(dl.filePath) + } + await prisma.download.update({ + where: { id: dl.id }, + data: { status: 'FILE_DELETED', deletedAt: new Date() }, + }) + } + + console.log(`[cron-cleanup] removed ${expired.length} expired file(s)`) +} + +cleanup().catch(console.error).finally(() => process.exit(0))