import { readonly, ref, watch } from "vue"; import type { StoreExportPayload } from "@/api"; import { GalaxyApi } from "@/api"; import type { ExportParams } from "@/components/Common/models/exportRecordModel"; import { withPrefix } from "@/utils/redirect"; import { rethrowSimple } from "@/utils/simple-error"; import { useShortTermStorageMonitor } from "./shortTermStorageMonitor"; export const DEFAULT_EXPORT_PARAMS: ExportParams = { modelStoreFormat: "rocrate.zip", includeFiles: true, includeDeleted: false, includeHidden: false, }; interface Options { exportParams: ExportParams; pollDelayInMs: number; } interface StorageRequestResponse { storage_request_id: string; } interface PrepareDownloadResult { storageRequestId: string; downloadUrl: string; } type StartPreparingDownloadCallback = (objectId: string, params: StoreExportPayload) => Promise; const DEFAULT_POLL_DELAY = 3000; const DEFAULT_OPTIONS: Options = { exportParams: DEFAULT_EXPORT_PARAMS, pollDelayInMs: DEFAULT_POLL_DELAY }; /** * Composable to simplify and reuse the logic for downloading objects using Galaxy's Short Term Storage system. */ export function useShortTermStorage() { const { waitForTask, isRunning, stopWaitingForTask } = useShortTermStorageMonitor(); const isPreparing = ref(false); watch(isRunning, (running) => { if (!running) { isPreparing.value = false; } }); const forHistory: StartPreparingDownloadCallback = async (id: string, params: StoreExportPayload) => { const { data, error } = await GalaxyApi().POST("/api/histories/{history_id}/prepare_store_download", { params: { path: { history_id: id } }, body: params, }); if (error) { rethrowSimple(error); } return data; }; const forInvocation: StartPreparingDownloadCallback = async (id: string, params: StoreExportPayload) => { const { data, error } = await GalaxyApi().POST("/api/invocations/{invocation_id}/prepare_store_download", { params: { path: { invocation_id: id } }, body: { ...params, bco_merge_history_metadata: false, }, }); if (error) { rethrowSimple(error); } return data; }; async function prepareHistoryDownload(historyId: string, options = DEFAULT_OPTIONS) { return prepareObjectDownload(forHistory, historyId, options); } async function prepareWorkflowInvocationDownload(invocationId: string, options = DEFAULT_OPTIONS) { return prepareObjectDownload(forInvocation, invocationId, options); } function getDownloadObjectUrl(storageRequestId: string) { const url = withPrefix(`/api/short_term_storage/${storageRequestId}`); return url; } function downloadObjectByRequestId(storageRequestId: string) { const url = getDownloadObjectUrl(storageRequestId); window.location.assign(url); } async function prepareObjectDownload( startPreparingDownloadAsync: StartPreparingDownloadCallback, objectId: string, options = DEFAULT_OPTIONS, ): Promise { isPreparing.value = true; const finalOptions = Object.assign(DEFAULT_OPTIONS, options); const exportParams: StoreExportPayload = { model_store_format: finalOptions.exportParams.modelStoreFormat, include_files: finalOptions.exportParams.includeFiles, include_deleted: finalOptions.exportParams.includeDeleted, include_hidden: finalOptions.exportParams.includeHidden, }; try { const response = await startPreparingDownloadAsync(objectId, exportParams); const storageRequestId = response.storage_request_id; waitForTask(storageRequestId, finalOptions.pollDelayInMs); return { storageRequestId, downloadUrl: getDownloadObjectUrl(storageRequestId), }; } catch (err) { isPreparing.value = false; } } function stopMonitoring() { stopWaitingForTask(); } return { /** * Starts preparing a history download file in the short term storage. * @param {String} historyId The ID of the history to be prepared for download * @param {Object} options Options for the download preparation */ prepareHistoryDownload, /** * Starts preparing a workflow invocation download file in the short term storage. * @param {String} invocationId The ID of the workflow invocation to be prepared for download * @param {Object} options Options for the download preparation */ prepareWorkflowInvocationDownload, /** * Starts a direct download of the object associated with the given `storageRequestId`. * For the download to succeed, the associated `storageRequestId` must be `ready` and not in failure state. * @param {String} storageRequestId The storage request ID associated to the object to be downloaded */ downloadObjectByRequestId, /** * Whether the download is still being prepared. */ isPreparing: readonly(isPreparing), /** * Given a storageRequestId it returns the download URL for that object. * @param {String} storageRequestId The storage request ID associated to the object to be downloaded */ getDownloadObjectUrl, /** * Stops monitoring the short term storage request. */ stopMonitoring, }; }