const jobs = {}; // In-memory store // Job Structure: // { // id: "batch-123-0", // url: "https://...", // status: "queued" | "downloading" | "ready_to_crop" | "processing" | "completed" | "error", // videoPath: "/tmp/vid.mp4", // framePath: "/tmp/frame.jpg", // outputPath: null, // error: null // } function createBatchJob(url, batchId) { const id = `${batchId}-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`; jobs[id] = { id, batchId, url, status: "queued", timestamp: Date.now() }; return id; } function getJob(id) { return jobs[id]; } function getBatchStatus(batchId) { return Object.values(jobs) .filter(j => j.batchId === batchId) .sort((a, b) => a.timestamp - b.timestamp); // Maintain order } function updateJob(id, updates) { if (jobs[id]) { Object.assign(jobs[id], updates); } } function getNextReadyJob(batchId) { return Object.values(jobs) .filter(j => j.batchId === batchId && j.status === "ready_to_crop") .sort((a, b) => a.timestamp - b.timestamp)[0]; } // Cleanup old jobs (prevent memory leak) setInterval(() => { const now = Date.now(); Object.keys(jobs).forEach(id => { if (now - jobs[id].timestamp > 2 * 60 * 60 * 1000) { // 2 hours // Ideally delete files here too delete jobs[id]; } }); }, 60000 * 30); module.exports = { createBatchJob, getJob, getBatchStatus, updateJob, getNextReadyJob };