1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import { Dispatch } from "redux";
6 import { RootState } from '~/store/store';
7 import { ServiceRepository } from '~/services/services';
8 import { updateResources } from '~/store/resources/resources-actions';
9 import { FilterBuilder } from '~/services/api/filter-builder';
10 import { ContainerRequestResource } from '~/models/container-request';
11 import { Process } from './process';
12 import { dialogActions } from '~/store/dialog/dialog-actions';
13 import { snackbarActions, SnackbarKind } from '~/store/snackbar/snackbar-actions';
14 import { projectPanelActions } from '~/store/project-panel/project-panel-action';
15 import { navigateToRunProcess } from '~/store/navigation/navigation-action';
16 import { goToStep, runProcessPanelActions } from '~/store/run-process-panel/run-process-panel-actions';
17 import { getResource } from '~/store/resources/resources';
18 import { initialize } from "redux-form";
19 import { RUN_PROCESS_BASIC_FORM, RunProcessBasicFormData } from "~/views/run-process-panel/run-process-basic-form";
20 import { RunProcessAdvancedFormData, RUN_PROCESS_ADVANCED_FORM } from "~/views/run-process-panel/run-process-advanced-form";
22 export const loadProcess = (containerRequestUuid: string) =>
23 async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository): Promise<Process> => {
24 const response = await services.workflowService.list();
25 dispatch(runProcessPanelActions.SET_WORKFLOWS(response.items));
26 const containerRequest = await services.containerRequestService.get(containerRequestUuid);
27 dispatch<any>(updateResources([containerRequest]));
28 if (containerRequest.containerUuid) {
29 const container = await services.containerService.get(containerRequest.containerUuid);
30 dispatch<any>(updateResources([container]));
31 await dispatch<any>(loadSubprocesses(containerRequest.containerUuid));
32 return { containerRequest, container };
34 return { containerRequest };
37 export const loadSubprocesses = (containerUuid: string) =>
38 async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
39 const containerRequests = await dispatch<any>(loadContainerRequests(
40 new FilterBuilder().addEqual('requestingContainerUuid', containerUuid).getFilters()
41 )) as ContainerRequestResource[];
43 const containerUuids: string[] = containerRequests.reduce((uuids, { containerUuid }) =>
45 ? [...uuids, containerUuid]
48 if (containerUuids.length > 0) {
49 await dispatch<any>(loadContainers(
50 new FilterBuilder().addIn('uuid', containerUuids).getFilters()
55 const MAX_AMOUNT_OF_SUBPROCESSES = 10000;
57 export const loadContainerRequests = (filters: string) =>
58 async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
59 const { items } = await services.containerRequestService.list({ filters, limit: MAX_AMOUNT_OF_SUBPROCESSES });
60 dispatch<any>(updateResources(items));
64 export const loadContainers = (filters: string) =>
65 async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
66 const { items } = await services.containerService.list({ filters });
67 dispatch<any>(updateResources(items));
71 export const cancelRunningWorkflow = (uuid: string) =>
72 async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
74 const process = await services.containerRequestService.update(uuid, { priority: 0 });
77 throw new Error('Could not cancel the process.');
81 export const reRunProcess = (processUuid: string, workflowUuid: string) =>
82 (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
83 const process = getResource<any>(processUuid)(getState().resources);
84 const workflows = getState().runProcessPanel.searchWorkflows;
85 const workflow = workflows.find(workflow => workflow.uuid === workflowUuid);
86 if (workflow && process) {
87 const newValues = getInputs(process);
88 process.mounts["/var/lib/cwl/workflow.json"].content.$graph.find(
89 (a: any) => a.id === '#main').inputs = newValues;
90 const stringifiedDefinition = JSON.stringify(process.mounts["/var/lib/cwl/workflow.json"].content);
91 const newWorkflow = { ...workflow, definition: stringifiedDefinition };
93 const basicInitialData: RunProcessBasicFormData = { name: `Copy of: ${process.name}`, description: process.description };
94 dispatch<any>(initialize(RUN_PROCESS_BASIC_FORM, basicInitialData));
96 const advancedInitialData: RunProcessAdvancedFormData = {
97 output: process.outputName,
98 runtime: process.schedulingParameters.max_run_time,
99 ram: process.runtimeConstraints.ram,
100 vcpus: process.runtimeConstraints.vcpus,
101 keep_cache_ram: process.runtimeConstraints.keep_cache_ram,
102 api: process.runtimeConstraints.API
104 dispatch<any>(initialize(RUN_PROCESS_ADVANCED_FORM, advancedInitialData));
106 dispatch<any>(navigateToRunProcess);
107 dispatch<any>(goToStep(1));
108 dispatch(runProcessPanelActions.SET_STEP_CHANGED(true));
109 dispatch(runProcessPanelActions.SET_SELECTED_WORKFLOW(newWorkflow));
111 dispatch<any>(snackbarActions.OPEN_SNACKBAR({ message: `You can't re-run this process`, kind: SnackbarKind.ERROR }));
115 const getInputs = (data: any) =>
116 data && data.mounts["/var/lib/cwl/workflow.json"] ? data.mounts["/var/lib/cwl/workflow.json"].content.$graph.find(
117 (a: any) => a.id === '#main').inputs.map(
123 default: data.mounts["/var/lib/cwl/cwl.input.json"].content[it.id],
129 export const openRemoveProcessDialog = (uuid: string) =>
130 (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
131 dispatch(dialogActions.OPEN_DIALOG({
132 id: REMOVE_PROCESS_DIALOG,
134 title: 'Remove process permanently',
135 text: 'Are you sure you want to remove this process?',
136 confirmButtonLabel: 'Remove',
142 export const REMOVE_PROCESS_DIALOG = 'removeProcessDialog';
144 export const removeProcessPermanently = (uuid: string) =>
145 async (dispatch: Dispatch, getState: () => RootState, services: ServiceRepository) => {
146 dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Removing ...', kind: SnackbarKind.INFO }));
147 await services.containerRequestService.delete(uuid);
148 dispatch(projectPanelActions.REQUEST_ITEMS());
149 dispatch(snackbarActions.OPEN_SNACKBAR({ message: 'Removed.', hideDuration: 2000, kind: SnackbarKind.SUCCESS }));