import { Router } from 'express'; import { getJob } from '../db.js'; import { subscribe } from '../queue.js'; const router = Router(); // Status page (HTML) router.get('/:id', (req, res) => { const job = getJob(req.params.id); if (!job) return res.status(404).render('error', { title: '404', message: 'Job not found.' }); // Already done — redirect immediately if (job.status === 'done') return res.redirect(`/results/${job.id}`); if (job.status === 'error') { return res.render('running', { title: 'Test Failed', job, error: job.error_msg }); } res.render('running', { title: `Testing ${job.url}`, job }); }); // SSE stream router.get('/:id/stream', (req, res) => { const job = getJob(req.params.id); if (!job) { res.status(404).end(); return; } // If already done, immediately emit done event if (job.status === 'done') { res.set({ 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive', }); res.write(`event: done\ndata: ${JSON.stringify({ jobId: job.id })}\n\n`); res.end(); return; } if (job.status === 'error') { res.set({ 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive', }); res.write(`event: error\ndata: ${JSON.stringify({ message: job.error_msg })}\n\n`); res.end(); return; } res.set({ 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', Connection: 'keep-alive', 'X-Accel-Buffering': 'no', }); // Keep-alive ping every 15s const ping = setInterval(() => { res.write(': ping\n\n'); }, 15000); const unsubscribe = subscribe(job.id, (payload) => { res.write(payload); }); req.on('close', () => { clearInterval(ping); unsubscribe(); }); }); export default router;