import { computed, type Ref, ref, watch } from "vue"; import { ERROR_STATES, TERMINAL_STATES } from "@/api/jobs"; import { type FetchDataPayload, fetchDatasetsToJobId, fetchJobErrorMessage } from "@/api/tools"; import { useResourceWatcher } from "@/composables/resourceWatcher"; import { useJobStore } from "@/stores/jobStore"; import { errorMessageAsString } from "@/utils/simple-error"; export function useJobWatcher(jobId: Ref) { const { fetchJob, getJob } = useJobStore(); const jobRequestError = ref(undefined); async function jobResourceHandler() { if (!jobId.value) { return; } jobRequestError.value = undefined; try { await fetchJob({ id: jobId.value! }); } catch (error) { jobRequestError.value = `Error requesting job: ${errorMessageAsString(error)}`; } } const job = computed(() => { if (jobId.value) { const jobIdVal = jobId.value; const job = getJob(jobIdVal); if (job) { return job; } } return undefined; }); const { startWatchingResourceIfNeeded, stopWatchingResourceIfNeeded } = useResourceWatcher(jobResourceHandler); watch( job, (job) => { if (job) { const newJobState = job.state; const isTerminal = TERMINAL_STATES.indexOf(newJobState) !== -1; if (isTerminal) { stopWatchingResourceIfNeeded(); } } else { startWatchingResourceIfNeeded(); } }, { immediate: true, }, ); return { job, jobRequestError, }; } export function useFetchJobMonitor() { const fetchJobId = ref(undefined); const { job, jobRequestError } = useJobWatcher(fetchJobId); const fetchComplete = ref(false); const fetchRequestError = ref(undefined); const jobFailedError = ref(undefined); const waitingOnFetch = ref(false); async function fetchAndWatch(payload: FetchDataPayload) { waitingOnFetch.value = true; try { const jobId = await fetchDatasetsToJobId(payload); fetchJobId.value = jobId; } catch (e) { fetchRequestError.value = `Error importing data: ${errorMessageAsString(e)}`; waitingOnFetch.value = false; } } watch(job, (newValue) => { const state = newValue?.state ?? "new"; if (TERMINAL_STATES.indexOf(state) !== -1) { if (ERROR_STATES.indexOf(state) !== -1) { jobFailedError.value = fetchJobErrorMessage(newValue!); } else { fetchComplete.value = true; } waitingOnFetch.value = false; } }); const fetchError = computed(() => { return fetchRequestError.value || jobRequestError.value || jobFailedError.value; }); return { fetchJobId, fetchAndWatch, fetchComplete, fetchError, job, waitingOnFetch, }; }