From c2996bef1e9163ff23403e72f3a5803e714c38bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Guti=C3=A9rrez?= <35082514+alezmad@users.noreply.github.com> Date: Sat, 24 Jan 2026 17:04:35 +0000 Subject: [PATCH] fix: Calculate job speed using last successful data retrieval timestamp - Use updated_at (last successful data loop) instead of Date.now() - Speed now reflects actual data retrieval rate, not declining over time - Updated in table column, monitored job view, and stats row - Fall back to Date.now() if updated_at is not available Co-Authored-By: Claude Opus 4.5 --- web/components/JobsView.tsx | 43 ++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/web/components/JobsView.tsx b/web/components/JobsView.tsx index e814f48..37d3089 100644 --- a/web/components/JobsView.tsx +++ b/web/components/JobsView.tsx @@ -665,9 +665,11 @@ export default function JobsView({ jobs, onSelectJob, isLoadingJob, onRefresh }: const isStuck = row.status === 'running' && new Date().getTime() - new Date(row.created_at).getTime() > 10 * 60 * 1000; - // For actively running jobs (not stuck), calculate speed from elapsed time + // For actively running jobs (not stuck), calculate speed from last successful data retrieval if (row.status === 'running' && !isStuck && row.started_at && row.reviews_count) { - const elapsed = (Date.now() - new Date(row.started_at).getTime()) / 1000; + // Use updated_at (last successful data loop) if available, otherwise fall back to Date.now() + const endTime = row.updated_at ? new Date(row.updated_at).getTime() : Date.now(); + const elapsed = (endTime - new Date(row.started_at).getTime()) / 1000; return elapsed > 0 ? row.reviews_count / elapsed : null; } return calculateSpeed(row.reviews_count, row.scrape_time); @@ -679,9 +681,11 @@ export default function JobsView({ jobs, onSelectJob, isLoadingJob, onRefresh }: const isStuck = isRunning && new Date().getTime() - new Date(job.created_at).getTime() > 10 * 60 * 1000; - // For actively running jobs (not stuck), show live speed + // For actively running jobs (not stuck), show live speed based on last successful data retrieval if (isRunning && !isStuck && job.started_at && job.reviews_count) { - const elapsed = (Date.now() - new Date(job.started_at).getTime()) / 1000; + // Use updated_at (last successful data loop) if available, otherwise fall back to Date.now() + const endTime = job.updated_at ? new Date(job.updated_at).getTime() : Date.now(); + const elapsed = (endTime - new Date(job.started_at).getTime()) / 1000; const speed = elapsed > 0 ? job.reviews_count / elapsed : 0; const isGood = speed >= 1; const isSlow = speed < 0.5; @@ -696,9 +700,10 @@ export default function JobsView({ jobs, onSelectJob, isLoadingJob, onRefresh }: ); } - // For stuck jobs, show frozen speed in red + // For stuck jobs, show frozen speed in red (use updated_at for accurate speed) if (isStuck && job.started_at && job.reviews_count) { - const elapsed = (Date.now() - new Date(job.started_at).getTime()) / 1000; + const endTime = job.updated_at ? new Date(job.updated_at).getTime() : Date.now(); + const elapsed = (endTime - new Date(job.started_at).getTime()) / 1000; const speed = elapsed > 0 ? job.reviews_count / elapsed : 0; return ( @@ -1371,9 +1376,13 @@ export default function JobsView({ jobs, onSelectJob, isLoadingJob, onRefresh }:
{Math.round(((monitoredJob.reviews_count || 0) / monitoredJob.total_reviews) * 100)}% complete - {monitoredJob.status === 'running' && monitoredJob.reviews_count && monitoredJob.scrape_time && ( + {monitoredJob.status === 'running' && monitoredJob.reviews_count && monitoredJob.started_at && ( - {(monitoredJob.reviews_count / monitoredJob.scrape_time).toFixed(1)} reviews/sec + {(() => { + const endTime = monitoredJob.updated_at ? new Date(monitoredJob.updated_at).getTime() : Date.now(); + const elapsed = (endTime - new Date(monitoredJob.started_at).getTime()) / 1000; + return elapsed > 0 ? (monitoredJob.reviews_count / elapsed).toFixed(1) : '0'; + })()} reviews/sec )}
@@ -1391,10 +1400,20 @@ export default function JobsView({ jobs, onSelectJob, isLoadingJob, onRefresh }:
Speed
- {monitoredJob.reviews_count && monitoredJob.scrape_time - ? `${(monitoredJob.reviews_count / monitoredJob.scrape_time).toFixed(1)}/s` - : '-' - } + {(() => { + if (!monitoredJob.reviews_count || !monitoredJob.started_at) return '-'; + // For running jobs, use updated_at; for completed, use scrape_time + if (monitoredJob.status === 'running') { + const endTime = monitoredJob.updated_at ? new Date(monitoredJob.updated_at).getTime() : Date.now(); + const elapsed = (endTime - new Date(monitoredJob.started_at).getTime()) / 1000; + return elapsed > 0 ? `${(monitoredJob.reviews_count / elapsed).toFixed(1)}/s` : '-'; + } + // For completed/partial jobs, use scrape_time if available + if (monitoredJob.scrape_time) { + return `${(monitoredJob.reviews_count / monitoredJob.scrape_time).toFixed(1)}/s`; + } + return '-'; + })()}