Read results once a minute

Every read of results asks each video schedule for its drafts, and the
dashboard read them every 10s while anything was being made, so the
network tab filled with video-drafts requests. Poll once a minute on the
dashboard and Results page, and reuse a read under a minute old when a
page opens or regains focus. Actions still refresh results at once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Iqbal
2026-10-29 17:12:51 +07:00
parent 3478d28bb2
commit 6ac8692d0d
3 changed files with 9 additions and 5 deletions

View File

@@ -201,6 +201,11 @@ export async function settleLimited<T, R>(items: T[], limit: number, fn: (item:
const PER_SCHEDULE_LIMIT = 4
// Results cost one request per schedule (every video schedule's drafts), so they are read once a
// minute, and a page opened or refocused within that minute reuses what was read. An action on a
// result or schedule still refreshes them at once.
export const RESULTS_POLL = { refetchInterval: 60_000, staleTime: 60_000 }
export async function listResults(): Promise<{ materials: Material[]; sources: FoundSource[] }> {
const schedules = await expressAgents({ archived: true })
const content = schedules.filter(s => s.rule.type === 'content')

View File

@@ -7,7 +7,7 @@ import { Icon } from '../components/Icon'
import { PageHead, Skeleton, SkeletonCards } from '../components/Page'
import { buildGraph, CLUSTERS, type Cluster, type Graph, type GraphNode } from '../express/graph'
import { describeRule } from '../express/parse'
import { isWorking, listResults, materialKey, titleOf, type Material } from '../express/results'
import { isWorking, listResults, materialKey, RESULTS_POLL, titleOf, type Material } from '../express/results'
import { listSchedules } from '../express/schedules'
import { locale, t, type Key } from '../i18n'
import { ContentCard, Preview } from './Results'
@@ -54,8 +54,7 @@ export function ProductionPage() {
const results = useQuery({
queryKey: ['results'],
queryFn: listResults,
// Polled more often than on Results so a run that just started shows up under content in progress.
refetchInterval: q => (q.state.data?.materials.some(isWorking) ? 10_000 : 20_000),
...RESULTS_POLL,
})
const schedules = useQuery({ queryKey: ['schedules'], queryFn: listSchedules, refetchInterval: 30_000 })

View File

@@ -8,7 +8,7 @@ import { Empty, PageHead, SkeletonCards, SkeletonLines, SkeletonRows } from '../
import { toast } from '../components/Toast'
import { describeRule, kindLabel, type ContentKind } from '../express/parse'
import {
decideMaterial, download, exportPptx, fileName, isWorking, printPdf, listOf, listResults, materialContent, materialKey, questionsOf, retryMaterial, reviewSource, slidesOf, textOf,
decideMaterial, download, exportPptx, fileName, isWorking, printPdf, listOf, listResults, materialContent, RESULTS_POLL, materialKey, questionsOf, retryMaterial, reviewSource, slidesOf, textOf,
titleOf, toMarkdown, type FoundSource, type Material, type MaterialContent, type MaterialStatus,
} from '../express/results'
import { MASTERY, scormPackage } from '../express/scorm'
@@ -35,7 +35,7 @@ export function ResultsPage() {
const results = useQuery({
queryKey: ['results'],
queryFn: listResults,
refetchInterval: q => (q.state.data?.materials.some(isWorking) ? 10_000 : 60_000),
...RESULTS_POLL,
})
const [tab, setTab] = useState<'content' | 'research'>('content')
const [query, setQuery] = useState('')