44 lines
2.1 KiB
TypeScript
44 lines
2.1 KiB
TypeScript
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
import { AssessorApiClient } from '../../api/assessor-api-client';
|
|
import type { AssessmentProject } from '../../domain/canonical-model';
|
|
import type { DatahubReferenceReadiness } from './datahub-processing-readiness';
|
|
|
|
const api = new AssessorApiClient();
|
|
|
|
/** Load only status summaries, with bounded concurrency and no background polling. */
|
|
export function useReferenceRecognitionStatus(projects: AssessmentProject[], connected: boolean, refreshKey: number) {
|
|
const [states, setStates] = useState<Record<string, DatahubReferenceReadiness>>({});
|
|
const pending = useRef(new Map<string, symbol>());
|
|
const reportStatus = useCallback((projectId: string, state: DatahubReferenceReadiness) => {
|
|
// A panel result must win over an older overview request for the same client.
|
|
pending.current.delete(projectId);
|
|
setStates(current => ({ ...current, [projectId]: state }));
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
let cancelled = false;
|
|
let next = 0;
|
|
pending.current.clear();
|
|
const queue = connected ? projects.map(project => ({ ...project, token: Symbol() })) : [];
|
|
for (const project of queue) pending.current.set(project.id, project.token);
|
|
setStates(Object.fromEntries(queue.map(project => [project.id, { state: 'checking' }])));
|
|
const loadNext = async () => {
|
|
while (!cancelled && next < queue.length) {
|
|
const { id: projectId, token } = queue[next++];
|
|
if (pending.current.get(projectId) !== token) continue;
|
|
let state: DatahubReferenceReadiness;
|
|
try { state = { state: 'ready', status: await api.getReferenceRecognitionStatus(projectId) }; }
|
|
catch { state = { state: 'unavailable' }; }
|
|
if (!cancelled && pending.current.get(projectId) === token) {
|
|
pending.current.delete(projectId);
|
|
setStates(current => ({ ...current, [projectId]: state }));
|
|
}
|
|
}
|
|
};
|
|
for (let worker = 0; worker < Math.min(3, queue.length); worker++) void loadNext();
|
|
return () => { cancelled = true; };
|
|
}, [projects, connected, refreshKey]);
|
|
|
|
return { states, reportStatus };
|
|
}
|