feat: add cron cleanup and worker-check scripts
This commit is contained in:
+3
-3
@@ -7,8 +7,8 @@
|
|||||||
"strict": true,
|
"strict": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"module": "commonjs",
|
"module": "node16",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node16",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
@@ -18,5 +18,5 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules", "**/__tests__/**"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -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))
|
||||||
Reference in New Issue
Block a user