import { ref, onUnmounted } from 'vue' import { getStatus } from '@/api/backtest' import { useAuthStore } from '@/stores/auth' export type TaskState = 'pending' | 'running' | 'done' | 'failed' | 'unknown' /** * Track a task's status + stage via polling (2s) and WebSocket (real-time). * Auto-stops on unmount. */ export function useTask(taskId: string) { const status = ref('unknown') const stage = ref('') let timer: ReturnType | null = null let ws: WebSocket | null = null async function poll(): Promise { try { const s = await getStatus(taskId) status.value = s.status as TaskState stage.value = s.stage } catch { /* transient — keep last known state */ } } function start(): void { poll() timer = setInterval(poll, 2000) const proto = window.location.protocol === 'https:' ? 'wss' : 'ws' const auth = useAuthStore() const url = `${proto}://${window.location.host}/api/v1/ws/task/${taskId}?token=${auth.token}` try { ws = new WebSocket(url) ws.onmessage = (ev) => { try { const msg = JSON.parse(ev.data) if (msg.stage) stage.value = msg.stage if (msg.status) status.value = msg.status } catch { /* ignore non-JSON keepalive frames */ } } } catch { /* WS optional — polling covers it */ } } onUnmounted(() => { if (timer) clearInterval(timer) if (ws) ws.close() }) return { status, stage, start } }