Initial push
This commit is contained in:
75
lib/scheduler/index.ts
Normal file
75
lib/scheduler/index.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Task scheduler using node-cron.
|
||||
* Loads enabled tasks from the DB on startup and registers them.
|
||||
*/
|
||||
|
||||
import cron, { ScheduledTask } from "node-cron";
|
||||
import { db } from "@/lib/db";
|
||||
import { scheduledTasks } from "@/lib/db/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { rconClient } from "@/lib/minecraft/rcon";
|
||||
import { sanitizeRconCommand } from "@/lib/security/sanitize";
|
||||
|
||||
const activeJobs = new Map<string, ScheduledTask>();
|
||||
|
||||
/** Load all enabled tasks from DB and schedule them. */
|
||||
export async function initScheduler(): Promise<void> {
|
||||
const tasks = await db
|
||||
.select()
|
||||
.from(scheduledTasks)
|
||||
.where(eq(scheduledTasks.isEnabled, true));
|
||||
|
||||
for (const task of tasks) {
|
||||
scheduleTask(task.id, task.cronExpression, task.command);
|
||||
}
|
||||
}
|
||||
|
||||
/** Schedule a single task. Returns false if cron expression is invalid. */
|
||||
export function scheduleTask(
|
||||
id: string,
|
||||
expression: string,
|
||||
command: string,
|
||||
): boolean {
|
||||
if (!cron.validate(expression)) return false;
|
||||
|
||||
// Stop existing job if any
|
||||
stopTask(id);
|
||||
|
||||
const job = cron.schedule(expression, async () => {
|
||||
try {
|
||||
const safeCmd = sanitizeRconCommand(command);
|
||||
await rconClient.sendCommand(safeCmd);
|
||||
await db
|
||||
.update(scheduledTasks)
|
||||
.set({ lastRun: Date.now() })
|
||||
.where(eq(scheduledTasks.id, id));
|
||||
} catch (err) {
|
||||
console.error(`[Scheduler] Task ${id} failed:`, err);
|
||||
}
|
||||
});
|
||||
|
||||
activeJobs.set(id, job);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Stop and remove a scheduled task. */
|
||||
export function stopTask(id: string): void {
|
||||
const existing = activeJobs.get(id);
|
||||
if (existing) {
|
||||
existing.stop();
|
||||
activeJobs.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
/** Stop all active jobs. */
|
||||
export function stopAllTasks(): void {
|
||||
for (const [id, job] of activeJobs.entries()) {
|
||||
job.stop();
|
||||
activeJobs.delete(id);
|
||||
}
|
||||
}
|
||||
|
||||
/** List active job IDs. */
|
||||
export function getActiveTaskIds(): string[] {
|
||||
return Array.from(activeJobs.keys());
|
||||
}
|
||||
Reference in New Issue
Block a user