19691: Show unknown errors on project & collection creation dialogs.
[arvados-workbench2.git] / src / store / processes / process.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { ContainerRequestResource, ContainerRequestState } from '../../models/container-request';
6 import { ContainerResource, ContainerState } from '../../models/container';
7 import { ResourcesState, getResource } from 'store/resources/resources';
8 import { filterResources } from '../resources/resources';
9 import { ResourceKind, Resource, extractUuidKind } from 'models/resource';
10 import { getTimeDiff } from 'common/formatters';
11 import { ArvadosTheme } from 'common/custom-theme';
12
13 export interface Process {
14     containerRequest: ContainerRequestResource;
15     container?: ContainerResource;
16 }
17
18 export enum ProcessStatus {
19     CANCELLED = 'Cancelled',
20     COMPLETED = 'Completed',
21     DRAFT = 'Draft',
22     FAILING = 'Failing',
23     FAILED = 'Failed',
24     ONHOLD = 'On hold',
25     QUEUED = 'Queued',
26     RUNNING = 'Running',
27     WARNING = 'Warning',
28     UNKNOWN = 'Unknown',
29 }
30
31 export const getProcess = (uuid: string) => (resources: ResourcesState): Process | undefined => {
32     if (extractUuidKind(uuid) === ResourceKind.CONTAINER_REQUEST) {
33         const containerRequest = getResource<ContainerRequestResource>(uuid)(resources);
34         if (containerRequest) {
35             if (containerRequest.containerUuid) {
36                 const container = getResource<ContainerResource>(containerRequest.containerUuid)(resources);
37                 if (container) {
38                     return { containerRequest, container };
39                 }
40             }
41             return { containerRequest };
42         }
43     }
44     return;
45 };
46
47 export const getSubprocesses = (uuid: string) => (resources: ResourcesState) => {
48     const process = getProcess(uuid)(resources);
49     if (process && process.container) {
50         const containerRequests = filterResources(isSubprocess(process.container.uuid))(resources) as ContainerRequestResource[];
51         return containerRequests.reduce((subprocesses, { uuid }) => {
52             const process = getProcess(uuid)(resources);
53             return process
54                 ? [...subprocesses, process]
55                 : subprocesses;
56         }, []);
57     }
58     return [];
59 };
60
61 export const getProcessRuntime = ({ container }: Process) => {
62     if (container) {
63         if (container.startedAt === null) {
64             return 0;
65         }
66         if (container.finishedAt === null) {
67             // Count it from now
68             return new Date().getTime() - new Date(container.startedAt).getTime();
69         }
70         return getTimeDiff(container.finishedAt, container.startedAt);
71     } else {
72         return 0;
73     }
74 };
75
76 export const getProcessStatusColor = (status: string, { customs }: ArvadosTheme) => {
77     switch (status) {
78         case ProcessStatus.RUNNING:
79             return customs.colors.blue500;
80         case ProcessStatus.COMPLETED:
81             return customs.colors.green700;
82         case ProcessStatus.WARNING:
83             return customs.colors.yellow700;
84         case ProcessStatus.FAILING:
85             return customs.colors.orange;
86         case ProcessStatus.CANCELLED:
87         case ProcessStatus.FAILED:
88             return customs.colors.red900;
89         default:
90             return customs.colors.grey500;
91     }
92 };
93
94 export const getProcessStatus = ({ containerRequest, container }: Process): ProcessStatus => {
95     switch (true) {
96         case containerRequest.state === ContainerRequestState.FINAL &&
97             container?.state !== ContainerState.COMPLETE:
98             // Request was finalized before its container started (or the
99             // container was cancelled)
100             return ProcessStatus.CANCELLED;
101
102         case containerRequest.state === ContainerRequestState.UNCOMMITTED:
103             return ProcessStatus.DRAFT;
104
105         case container?.state === ContainerState.COMPLETE:
106             if (container?.exitCode === 0) {
107                 return ProcessStatus.COMPLETED;
108             }
109             return ProcessStatus.FAILED;
110
111         case container?.state === ContainerState.CANCELLED:
112             return ProcessStatus.CANCELLED;
113
114         case container?.state === ContainerState.QUEUED ||
115             container?.state === ContainerState.LOCKED:
116             if (containerRequest.priority === 0) {
117                 return ProcessStatus.ONHOLD;
118             }
119             return ProcessStatus.QUEUED;
120
121         case container?.state === ContainerState.RUNNING:
122             if (!!container?.runtimeStatus.error) {
123                 return ProcessStatus.FAILING;
124             }
125             if (!!container?.runtimeStatus.warning) {
126                 return ProcessStatus.WARNING;
127             }
128             return ProcessStatus.RUNNING;
129
130         default:
131             return ProcessStatus.UNKNOWN;
132     }
133 };
134
135 const isSubprocess = (containerUuid: string) => (resource: Resource) =>
136     resource.kind === ResourceKind.CONTAINER_REQUEST
137     && (resource as ContainerRequestResource).requestingContainerUuid === containerUuid;