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:
@@ -201,6 +201,11 @@ export async function settleLimited<T, R>(items: T[], limit: number, fn: (item:
|
|||||||
|
|
||||||
const PER_SCHEDULE_LIMIT = 4
|
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[] }> {
|
export async function listResults(): Promise<{ materials: Material[]; sources: FoundSource[] }> {
|
||||||
const schedules = await expressAgents({ archived: true })
|
const schedules = await expressAgents({ archived: true })
|
||||||
const content = schedules.filter(s => s.rule.type === 'content')
|
const content = schedules.filter(s => s.rule.type === 'content')
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { Icon } from '../components/Icon'
|
|||||||
import { PageHead, Skeleton, SkeletonCards } from '../components/Page'
|
import { PageHead, Skeleton, SkeletonCards } from '../components/Page'
|
||||||
import { buildGraph, CLUSTERS, type Cluster, type Graph, type GraphNode } from '../express/graph'
|
import { buildGraph, CLUSTERS, type Cluster, type Graph, type GraphNode } from '../express/graph'
|
||||||
import { describeRule } from '../express/parse'
|
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 { listSchedules } from '../express/schedules'
|
||||||
import { locale, t, type Key } from '../i18n'
|
import { locale, t, type Key } from '../i18n'
|
||||||
import { ContentCard, Preview } from './Results'
|
import { ContentCard, Preview } from './Results'
|
||||||
@@ -54,8 +54,7 @@ export function ProductionPage() {
|
|||||||
const results = useQuery({
|
const results = useQuery({
|
||||||
queryKey: ['results'],
|
queryKey: ['results'],
|
||||||
queryFn: listResults,
|
queryFn: listResults,
|
||||||
// Polled more often than on Results so a run that just started shows up under content in progress.
|
...RESULTS_POLL,
|
||||||
refetchInterval: q => (q.state.data?.materials.some(isWorking) ? 10_000 : 20_000),
|
|
||||||
})
|
})
|
||||||
const schedules = useQuery({ queryKey: ['schedules'], queryFn: listSchedules, refetchInterval: 30_000 })
|
const schedules = useQuery({ queryKey: ['schedules'], queryFn: listSchedules, refetchInterval: 30_000 })
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { Empty, PageHead, SkeletonCards, SkeletonLines, SkeletonRows } from '../
|
|||||||
import { toast } from '../components/Toast'
|
import { toast } from '../components/Toast'
|
||||||
import { describeRule, kindLabel, type ContentKind } from '../express/parse'
|
import { describeRule, kindLabel, type ContentKind } from '../express/parse'
|
||||||
import {
|
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,
|
titleOf, toMarkdown, type FoundSource, type Material, type MaterialContent, type MaterialStatus,
|
||||||
} from '../express/results'
|
} from '../express/results'
|
||||||
import { MASTERY, scormPackage } from '../express/scorm'
|
import { MASTERY, scormPackage } from '../express/scorm'
|
||||||
@@ -35,7 +35,7 @@ export function ResultsPage() {
|
|||||||
const results = useQuery({
|
const results = useQuery({
|
||||||
queryKey: ['results'],
|
queryKey: ['results'],
|
||||||
queryFn: listResults,
|
queryFn: listResults,
|
||||||
refetchInterval: q => (q.state.data?.materials.some(isWorking) ? 10_000 : 60_000),
|
...RESULTS_POLL,
|
||||||
})
|
})
|
||||||
const [tab, setTab] = useState<'content' | 'research'>('content')
|
const [tab, setTab] = useState<'content' | 'research'>('content')
|
||||||
const [query, setQuery] = useState('')
|
const [query, setQuery] = useState('')
|
||||||
|
|||||||
Reference in New Issue
Block a user