fix(news): auto-retry news fetch when backend Celery task is in-flight
When a bill page opens with no stored articles, the backend queues a fetch_news_for_bill Celery task and returns immediately. Added a retry loop (up to 3x, 6 s apart) driven off newsArticles state so articles populate without a manual refresh. Fixed broken useEffect dependency ([billId] → [newsArticles]) that caused the timer to never fire. News is now fetched via a separate useBillNews query (staleTime: 0) independent of the cached bill detail response. Co-Authored-By: Jack Levy
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import { use } from "react";
|
||||
import { use, useEffect, useRef } from "react";
|
||||
import Link from "next/link";
|
||||
import { ArrowLeft, ExternalLink, User } from "lucide-react";
|
||||
import { useBill, useBillTrend } from "@/lib/hooks/useBills";
|
||||
import { useBill, useBillNews, useBillTrend } from "@/lib/hooks/useBills";
|
||||
import { BriefPanel } from "@/components/bills/BriefPanel";
|
||||
import { ActionTimeline } from "@/components/bills/ActionTimeline";
|
||||
import { TrendChart } from "@/components/bills/TrendChart";
|
||||
@@ -17,6 +17,23 @@ export default function BillDetailPage({ params }: { params: Promise<{ id: strin
|
||||
|
||||
const { data: bill, isLoading } = useBill(billId);
|
||||
const { data: trendData } = useBillTrend(billId, 30);
|
||||
const { data: newsArticles, refetch: refetchNews } = useBillNews(billId);
|
||||
|
||||
// When the bill page is opened with no stored articles, the backend queues
|
||||
// a Celery news-fetch task that takes a few seconds to complete.
|
||||
// Retry up to 3 times (every 6 s) so articles appear without a manual refresh.
|
||||
// newsRetryRef resets on bill navigation so each bill gets its own retry budget.
|
||||
const newsRetryRef = useRef(0);
|
||||
useEffect(() => { newsRetryRef.current = 0; }, [billId]);
|
||||
useEffect(() => {
|
||||
if (newsArticles === undefined || newsArticles.length > 0) return;
|
||||
if (newsRetryRef.current >= 3) return;
|
||||
const timer = setTimeout(() => {
|
||||
newsRetryRef.current += 1;
|
||||
refetchNews();
|
||||
}, 6000);
|
||||
return () => clearTimeout(timer);
|
||||
}, [newsArticles]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
if (isLoading) {
|
||||
return <div className="text-center py-20 text-muted-foreground">Loading bill...</div>;
|
||||
@@ -85,7 +102,7 @@ export default function BillDetailPage({ params }: { params: Promise<{ id: strin
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<TrendChart data={trendData} />
|
||||
<NewsPanel articles={bill.news_articles} />
|
||||
<NewsPanel articles={newsArticles} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -31,7 +31,7 @@ export function useBillNews(id: string) {
|
||||
return useQuery({
|
||||
queryKey: ["bill-news", id],
|
||||
queryFn: () => billsAPI.getNews(id),
|
||||
staleTime: 10 * 60 * 1000,
|
||||
staleTime: 0, // Always fetch fresh — news arrives async after brief generation
|
||||
enabled: !!id,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user