60 lines
1.2 KiB
TypeScript
60 lines
1.2 KiB
TypeScript
'use client';
|
|
|
|
import { useEffect, useState } from 'react';
|
|
import { getTask } from '@/lib/api';
|
|
import type { Task } from '@/lib/types';
|
|
|
|
type UseTaskPollerInput = {
|
|
taskId: string | null;
|
|
intervalMs?: number;
|
|
onTerminalState?: (task: Task) => void;
|
|
};
|
|
|
|
export function useTaskPoller({ taskId, intervalMs = 2200, onTerminalState }: UseTaskPollerInput) {
|
|
const [task, setTask] = useState<Task | null>(null);
|
|
|
|
useEffect(() => {
|
|
if (!taskId) {
|
|
setTask(null);
|
|
return;
|
|
}
|
|
|
|
let stopped = false;
|
|
let timer: ReturnType<typeof setTimeout> | null = null;
|
|
|
|
const poll = async () => {
|
|
try {
|
|
const { task: latest } = await getTask(taskId);
|
|
|
|
if (stopped) {
|
|
return;
|
|
}
|
|
|
|
setTask(latest);
|
|
|
|
if (latest.status === 'completed' || latest.status === 'failed') {
|
|
onTerminalState?.(latest);
|
|
return;
|
|
}
|
|
} catch {
|
|
if (stopped) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
timer = setTimeout(poll, intervalMs);
|
|
};
|
|
|
|
void poll();
|
|
|
|
return () => {
|
|
stopped = true;
|
|
if (timer) {
|
|
clearTimeout(timer);
|
|
}
|
|
};
|
|
}, [taskId, intervalMs, onTerminalState]);
|
|
|
|
return task;
|
|
}
|