From 6c0d1c4679cf8fe153ef56bdc779c93239e1cf0f Mon Sep 17 00:00:00 2001 From: Jaret Burkett Date: Sat, 4 Jul 2026 13:22:09 -0600 Subject: [PATCH] Improve latency of the job list endpoint --- ui/src/app/api/jobs/route.ts | 11 ++++++++++- ui/src/hooks/useJobsList.tsx | 26 ++++++++++++++++++++------ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/ui/src/app/api/jobs/route.ts b/ui/src/app/api/jobs/route.ts index 11dd952..2db8f42 100644 --- a/ui/src/app/api/jobs/route.ts +++ b/ui/src/app/api/jobs/route.ts @@ -9,6 +9,7 @@ export async function GET(request: Request) { const id = searchParams.get('id'); const job_ref = searchParams.get('job_ref'); const job_type = searchParams.get('job_type'); + const only_active = searchParams.get('only_active'); try { if (id) { @@ -25,8 +26,16 @@ export async function GET(request: Request) { return NextResponse.json(job); } + const where: any = {}; + if (job_type) { + where.job_type = job_type; + } + if (only_active === 'true') { + where.status = { in: ['running', 'queued', 'stopping'] }; + } + const jobs = await prisma.job.findMany({ - where: job_type ? { job_type } : undefined, + where, orderBy: { created_at: 'desc' }, }); return NextResponse.json({ jobs: jobs }); diff --git a/ui/src/hooks/useJobsList.tsx b/ui/src/hooks/useJobsList.tsx index ad83c5c..6309b55 100644 --- a/ui/src/hooks/useJobsList.tsx +++ b/ui/src/hooks/useJobsList.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useEffect, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { Job } from '@prisma/client'; import { apiClient } from '@/utils/api'; @@ -10,14 +10,28 @@ type UseJobsListProps = { job_type?: string | null; }; -export default function useJobsList({ onlyActive = false, reloadInterval = null, job_type=null }: UseJobsListProps = {}) { +export default function useJobsList({ + onlyActive = false, + reloadInterval = null, + job_type = null, +}: UseJobsListProps = {}) { const [jobs, setJobs] = useState([]); const [status, setStatus] = useState<'idle' | 'loading' | 'success' | 'error'>('idle'); + const isFetchingRef = useRef(false); const refreshJobs = () => { + if (isFetchingRef.current) return; + isFetchingRef.current = true; setStatus('loading'); + const params: Record = {}; + if (job_type) { + params.job_type = job_type; + } + if (onlyActive) { + params.only_active = 'true'; + } apiClient - .get('/api/jobs', { params: job_type ? { job_type } : undefined }) + .get('/api/jobs', { params }) .then(res => res.data) .then(data => { console.log('Jobs:', data); @@ -25,9 +39,6 @@ export default function useJobsList({ onlyActive = false, reloadInterval = null, console.log('Error fetching jobs:', data.error); setStatus('error'); } else { - if (onlyActive) { - data.jobs = data.jobs.filter((job: Job) => ['running', 'queued', 'stopping'].includes(job.status)); - } setJobs(data.jobs); setStatus('success'); } @@ -35,6 +46,9 @@ export default function useJobsList({ onlyActive = false, reloadInterval = null, .catch(error => { console.error('Error fetching jobs:', error); setStatus('error'); + }) + .finally(() => { + isFetchingRef.current = false; }); }; useEffect(() => {