Merge branch 'main' of git.arvados.org:arvados-workbench2 into 20251-subprocess-panel...
[arvados-workbench2.git] / src / store / processes / processes-actions.ts
index 8a94d8cfcabb8413f522f568e660ede6084cc3e7..b26c2017f7552fa54c4d6e44f57ad398ff1b45ce 100644 (file)
@@ -17,36 +17,56 @@ import { initialize } from "redux-form";
 import { RUN_PROCESS_BASIC_FORM, RunProcessBasicFormData } from "views/run-process-panel/run-process-basic-form";
 import { RunProcessAdvancedFormData, RUN_PROCESS_ADVANCED_FORM } from "views/run-process-panel/run-process-advanced-form";
 import { MOUNT_PATH_CWL_WORKFLOW, MOUNT_PATH_CWL_INPUT } from 'models/process';
-import { CommandInputParameter, getWorkflow, getWorkflowInputs, getWorkflowOutputs } from "models/workflow";
+import { CommandInputParameter, getWorkflow, getWorkflowInputs, getWorkflowOutputs, WorkflowInputsData } from "models/workflow";
 import { ProjectResource } from "models/project";
 import { UserResource } from "models/user";
 import { CommandOutputParameter } from "cwlts/mappings/v1.0/CommandOutputParameter";
+import { ContainerResource } from "models/container";
+import { ContainerRequestResource, ContainerRequestState } from "models/container-request";
+import { FilterBuilder } from "services/api/filter-builder";
 
 export const loadProcess = (containerRequestUuid: string) =>
-    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository): Promise<Process> => {
-        const containerRequest = await services.containerRequestService.get(containerRequestUuid);
-        dispatch<any>(updateResources([containerRequest]));
+    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository): Promise<Process | undefined> => {
+        let containerRequest: ContainerRequestResource | undefined = undefined;
+        try {
+            containerRequest = await services.containerRequestService.get(containerRequestUuid);
+            dispatch<any>(updateResources([containerRequest]));
+        } catch {
+            return undefined;
+        }
 
         if (containerRequest.outputUuid) {
-            const collection = await services.collectionService.get(containerRequest.outputUuid);
-            dispatch<any>(updateResources([collection]));
+            try {
+                const collection = await services.collectionService.get(containerRequest.outputUuid, false);
+                dispatch<any>(updateResources([collection]));
+            } catch {}
         }
 
         if (containerRequest.containerUuid) {
-            const container = await services.containerService.get(containerRequest.containerUuid);
-            dispatch<any>(updateResources([container]));
-            if (container.runtimeUserUuid) {
-                const runtimeUser = await services.userService.get(container.runtimeUserUuid);
-                dispatch<any>(updateResources([runtimeUser]));
-            }
+            let container: ContainerResource | undefined = undefined;
+            try {
+                container = await services.containerService.get(containerRequest.containerUuid, false);
+                dispatch<any>(updateResources([container]));
+            } catch {}
+
+            try{
+                if (container && container.runtimeUserUuid) {
+                    const runtimeUser = await services.userService.get(container.runtimeUserUuid, false);
+                    dispatch<any>(updateResources([runtimeUser]));
+                }
+            } catch {}
+
             return { containerRequest, container };
         }
         return { containerRequest };
     };
 
-export const loadContainers = (filters: string, loadMounts: boolean = true) =>
+export const loadContainers = (containerUuids: string[], loadMounts: boolean = true) =>
     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
-        let args: any = { filters };
+        let args: any = {
+            filters: new FilterBuilder().addIn('uuid', containerUuids).getFilters(),
+            limit: containerUuids.length,
+         };
         if (!loadMounts) {
             args.select = containerFieldsNoMounts;
         }
@@ -60,6 +80,7 @@ const containerFieldsNoMounts = [
     "auth_uuid",
     "command",
     "container_image",
+    "cost",
     "created_at",
     "cwd",
     "environment",
@@ -97,12 +118,47 @@ export const cancelRunningWorkflow = (uuid: string) =>
     async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
         try {
             const process = await services.containerRequestService.update(uuid, { priority: 0 });
+            dispatch<any>(updateResources([process]));
+            if (process.containerUuid) {
+                const container = await services.containerService.get(process.containerUuid, false);
+                dispatch<any>(updateResources([container]));
+            }
             return process;
         } catch (e) {
             throw new Error('Could not cancel the process.');
         }
     };
 
+export const resumeOnHoldWorkflow = (uuid: string) =>
+    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+        try {
+            const process = await services.containerRequestService.update(uuid, { priority: 500 });
+            dispatch<any>(updateResources([process]));
+            if (process.containerUuid) {
+                const container = await services.containerService.get(process.containerUuid, false);
+                dispatch<any>(updateResources([container]));
+            }
+            return process;
+        } catch (e) {
+            throw new Error('Could not resume the process.');
+        }
+    };
+
+export const startWorkflow = (uuid: string) =>
+    async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
+        try {
+            const process = await services.containerRequestService.update(uuid, { state: ContainerRequestState.COMMITTED });
+            if (process) {
+                dispatch<any>(updateResources([process]));
+                dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Process started', hideDuration: 2000, kind: SnackbarKind.SUCCESS }));
+            } else {
+                dispatch<any>(snackbarActions.OPEN_SNACKBAR({ message: `Failed to start process`, kind: SnackbarKind.ERROR }));
+            }
+        } catch (e) {
+            dispatch<any>(snackbarActions.OPEN_SNACKBAR({ message: `Failed to start process`, kind: SnackbarKind.ERROR }));
+        }
+    };
+
 export const reRunProcess = (processUuid: string, workflowUuid: string) =>
     (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
         const process = getResource<any>(processUuid)(getState().resources);
@@ -140,13 +196,13 @@ export const reRunProcess = (processUuid: string, workflowUuid: string) =>
 /*
  * Fetches raw inputs from containerRequest mounts with fallback to properties
  * Returns undefined if containerRequest not loaded
- * Returns [] if inputs not found in mounts or props
+ * Returns {} if inputs not found in mounts or props
  */
-export const getRawInputs = (data: any): CommandInputParameter[] | undefined => {
+export const getRawInputs = (data: any): WorkflowInputsData | undefined => {
     if (!data) { return undefined; }
     const mountInput = data.mounts?.[MOUNT_PATH_CWL_INPUT]?.content;
     const propsInput = data.properties?.cwl_input;
-    if (!mountInput && !propsInput) { return []; }
+    if (!mountInput && !propsInput) { return {}; }
     return (mountInput || propsInput);
 }
 
@@ -154,6 +210,8 @@ export const getInputs = (data: any): CommandInputParameter[] => {
     // Definitions from mounts are needed so we return early if missing
     if (!data || !data.mounts || !data.mounts[MOUNT_PATH_CWL_WORKFLOW]) { return []; }
     const content  = getRawInputs(data) as any;
+    // Only escape if content is falsy to allow displaying definitions if no inputs are present
+    // (Don't check raw content length)
     if (!content) { return []; }
 
     const inputs = getWorkflowInputs(data.mounts[MOUNT_PATH_CWL_WORKFLOW].content);