Follow a running production every few seconds
A started production kept showing "AI picks new topics" for a minute or more: each schedule's status was read once a minute, and the refresh right after starting got the read kept from before the start. That read is now dropped when a production starts, and while the latest production is under way its status is read every five seconds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -397,9 +397,9 @@ export function planProgress(plan: ContentPlan) {
|
||||
// from the last half minute, or one still on its way, answers both. forgetReads drops them after an action.
|
||||
const PRODUCTION_FRESH = 30_000
|
||||
const productionReads = new Map<number, { at: number; read: Promise<ProductionStatus> }>()
|
||||
export function productionStatus(id: number): Promise<ProductionStatus> {
|
||||
export function productionStatus(id: number, maxAge = PRODUCTION_FRESH): Promise<ProductionStatus> {
|
||||
const kept = productionReads.get(id)
|
||||
if (kept && Date.now() - kept.at < PRODUCTION_FRESH) return kept.read
|
||||
if (kept && Date.now() - kept.at < maxAge) return kept.read
|
||||
const read = request<ProductionStatus>(`${AGENTS}/${id}/content`)
|
||||
productionReads.set(id, { at: Date.now(), read })
|
||||
read.catch(() => { if (productionReads.get(id)?.read === read) productionReads.delete(id) })
|
||||
|
||||
@@ -7,8 +7,8 @@ import { toast } from '../components/Toast'
|
||||
import { describeRule } from '../express/parse'
|
||||
import { locale, t, type Key } from '../i18n'
|
||||
import {
|
||||
archiveSchedule, confirmProduction, isMine, isRunSchedule, knowledgeReadiness, listRuns, listSchedules, scheduleOwners, pauseSchedule, PLAN_ACTIVE, productionStatus, quoteProduction, resumeSchedule,
|
||||
planProgress, productionError, runNow as startRun, updateTopic, type ContentPlan, type Owners, type RunSummary, type Schedule,
|
||||
archiveSchedule, confirmProduction, forgetProductionReads, isMine, isRunSchedule, knowledgeReadiness, listRuns, listSchedules, scheduleOwners, pauseSchedule, PLAN_ACTIVE, productionStatus, quoteProduction, resumeSchedule,
|
||||
planProgress, productionError, runNow as startRun, updateTopic, type ContentPlan, type Owners, type ProductionStatus, type RunSummary, type Schedule,
|
||||
} from '../express/schedules'
|
||||
|
||||
const STUDIO_URL: string = import.meta.env.VITE_STUDIO_URL
|
||||
@@ -152,13 +152,20 @@ function ScheduleRow({ schedule, owners }: { schedule: Schedule; owners?: Owners
|
||||
}
|
||||
|
||||
// Content schedules report this week's progress from the engine's production period. Each row
|
||||
// asks for its own, so it is read once a minute; starting a production refreshes it at once.
|
||||
const useProduction = (agentId: number) => useQuery({
|
||||
queryKey: ['production', agentId],
|
||||
queryFn: () => productionStatus(agentId),
|
||||
refetchInterval: 60_000,
|
||||
staleTime: 60_000,
|
||||
// asks for its own, so it is read once a minute; while its latest production is under way it is
|
||||
// read every few seconds, so each step shows as it happens. Starting a production refreshes it at once.
|
||||
const LIVE_POLL = 5000
|
||||
const isLive = (s: ProductionStatus | undefined) => !!s?.plans[0] && PLAN_ACTIVE.has(s.plans[0].status)
|
||||
function useProduction(agentId: number) {
|
||||
const queryClient = useQueryClient()
|
||||
const key = ['production', agentId]
|
||||
return useQuery({
|
||||
queryKey: key,
|
||||
queryFn: () => productionStatus(agentId, isLive(queryClient.getQueryData<ProductionStatus>(key)) ? LIVE_POLL : undefined),
|
||||
refetchInterval: q => (isLive(q.state.data) ? LIVE_POLL : 60_000),
|
||||
staleTime: q => (isLive(q.state.data) ? LIVE_POLL : 60_000),
|
||||
})
|
||||
}
|
||||
|
||||
function ProductionLine({ agentId, active }: { agentId: number; active: boolean }) {
|
||||
const status = useProduction(agentId)
|
||||
@@ -218,6 +225,8 @@ function ProducePanel({ schedule: { agent, rule }, onClose }: { schedule: Schedu
|
||||
const start = useMutation({
|
||||
mutationFn: (plan: ContentPlan) => confirmProduction(agent.id, plan),
|
||||
onSuccess: () => {
|
||||
// The read kept from before the start still shows no production; it must not answer the refresh.
|
||||
forgetProductionReads()
|
||||
queryClient.invalidateQueries({ queryKey: ['production', agent.id] })
|
||||
queryClient.invalidateQueries({ queryKey: ['results'] })
|
||||
onClose()
|
||||
|
||||
Reference in New Issue
Block a user