import { useChangeVersions } from "@agent-native/core/client/hooks"; import { useT } from "@agent-native/core/client/i18n"; import { IconAlertTriangle, IconPlayerPlay } from "@tabler/icons-react"; import { useQuery } from "@tanstack/react-query"; import { formatQueueAgeSeconds, getDispatchTaskQueueStats, type TaskQueueStats, ZERO_TASK_QUEUE_STATS, } from "../lib/task-queue"; import { cn } from "../lib/utils"; import { Skeleton } from "./ui/skeleton"; const TASK_QUEUE_QUERY_KEY = ["dispatch-task-queue"] as const; function formatNumber(value: number): string { return new Intl.NumberFormat(undefined, { notation: value >= 10_000 ? "compact" : "standard", }).format(value); } function useTaskQueueStats() { const version = useChangeVersions(["action", "screen-refresh"]); return useQuery({ queryKey: [...TASK_QUEUE_QUERY_KEY, version], queryFn: getDispatchTaskQueueStats, placeholderData: (prev) => prev, // Queue work can finish outside the action transport, so retain a bounded // fallback only here. Idle workspaces back off aggressively; active queues // keep the existing monitoring cadence. refetchInterval: (query) => { const stats = query.state.data; return stats && (stats.pending > 0 || stats.processing > 0) ? 15_000 : 300_000; }, staleTime: 5_000, }); } function QueueCell({ label, value, danger, }: { label: string; value: number; danger?: boolean; }) { return (
{formatNumber(value)}
{label}
); } export function TaskQueueHealth() { const t = useT(); const query = useTaskQueueStats(); const taskQueue = query.data ?? ZERO_TASK_QUEUE_STATS; const hasFailure = taskQueue.failed_last_hour > 0; const hasBacklog = taskQueue.pending > 5 || taskQueue.oldest_pending_age_seconds > 300; const oldestAge = formatQueueAgeSeconds(taskQueue.oldest_pending_age_seconds); const oldestAgeLabel = oldestAge === "none" ? t("dispatch.pages.queueAgeNone") : oldestAge; return (

{t("dispatch.pages.deliveryQueue")}

{hasFailure ? t("dispatch.pages.failedLastHour", { count: taskQueue.failed_last_hour, }) : t("dispatch.pages.processingCount", { count: taskQueue.processing, })}

{query.isLoading && !query.data ? (
{Array.from({ length: 4 }).map((_, index) => ( ))}
) : ( <>
{t("dispatch.pages.oldestQueued", { age: oldestAgeLabel })}
{hasFailure ? (
{t("dispatch.pages.queueFailureHint")}
) : null} {taskQueue.recent_failures.length > 0 ? (
{taskQueue.recent_failures.slice(0, 3).map((failure) => (
{failure.platform || t("dispatch.pages.unknownPlatform")} {t("dispatch.pages.attemptsCount", { count: failure.attempts, })}
{failure.error || t("dispatch.pages.noErrorMessage")}
))}
) : null} )}
); }