-
- {renderExecutionsTimeline}
-
+ ;
diff --git a/packages/zapp/console/src/components/Executions/ExecutionDetails/test/Timeline.test.tsx b/packages/zapp/console/src/components/Executions/ExecutionDetails/test/Timeline.test.tsx
index d1e68dba2..f99d01f8d 100644
--- a/packages/zapp/console/src/components/Executions/ExecutionDetails/test/Timeline.test.tsx
+++ b/packages/zapp/console/src/components/Executions/ExecutionDetails/test/Timeline.test.tsx
@@ -1,5 +1,6 @@
import ThemeProvider from '@material-ui/styles/ThemeProvider';
import { render, waitFor } from '@testing-library/react';
+import { NodeExecutionsByIdContext } from 'components/Executions/contexts';
import { muiTheme } from 'components/Theme/muiTheme';
import { oneFailedTaskWorkflow } from 'mocks/data/fixtures/oneFailedTaskWorkflow';
import { insertFixture } from 'mocks/data/insertFixture';
@@ -16,6 +17,10 @@ jest.mock('../ExecutionWorkflowGraph.tsx', () => ({
ExecutionWorkflowGraph: () => null,
}));
+jest.mock('../Timeline/ExecutionTimeline.tsx', () => ({
+ ExecutionTimeline: () => null,
+}));
+
jest.mock('chart.js', () => ({
Chart: { register: () => null },
Tooltip: { positioners: { cursor: () => null } },
@@ -59,7 +64,9 @@ describe('ExecutionDetails > Timeline', () => {
render(
-
+
+
+
,
);
diff --git a/packages/zapp/console/src/components/Executions/contexts.ts b/packages/zapp/console/src/components/Executions/contexts.ts
index 691d464ee..faeb47b6d 100644
--- a/packages/zapp/console/src/components/Executions/contexts.ts
+++ b/packages/zapp/console/src/components/Executions/contexts.ts
@@ -9,6 +9,7 @@ export interface ExecutionContextData {
export const ExecutionContext = React.createContext
(
{} as ExecutionContextData,
);
-export const NodeExecutionsContext = React.createContext>({});
+
+export const NodeExecutionsByIdContext = React.createContext>({});
export const NodeExecutionsRequestConfigContext = React.createContext({});
diff --git a/packages/zapp/console/src/components/Executions/nodeExecutionQueries.ts b/packages/zapp/console/src/components/Executions/nodeExecutionQueries.ts
index f31766060..556832414 100644
--- a/packages/zapp/console/src/components/Executions/nodeExecutionQueries.ts
+++ b/packages/zapp/console/src/components/Executions/nodeExecutionQueries.ts
@@ -280,86 +280,6 @@ function fetchChildNodeExecutionGroups(
return fetchGroupsForTaskExecutionNode(queryClient, nodeExecution, config);
}
-/**
- * Query returns all children for a list of `nodeExecutions`
- * Will recursively gather all children for anyone that isParent()
- */
-async function fetchAllChildNodeExecutions(
- queryClient: QueryClient,
- nodeExecutions: NodeExecution[],
- config: RequestConfig,
-): Promise> {
- const executionGroups: Array = await Promise.all(
- nodeExecutions.map((exe) => fetchChildNodeExecutionGroups(queryClient, exe, config)),
- );
-
- /** Recursive check for nested/dynamic nodes */
- const childrenFromChildrenNodes: NodeExecution[] = [];
- executionGroups.map((group) =>
- group.map((attempt) => {
- attempt.nodeExecutions.map((execution) => {
- if (isParentNode(execution)) {
- childrenFromChildrenNodes.push(execution);
- }
- });
- }),
- );
-
- /** Request and concact data from children */
- if (childrenFromChildrenNodes.length > 0) {
- const childGroups = await fetchAllChildNodeExecutions(
- queryClient,
- childrenFromChildrenNodes,
- config,
- );
- for (const group in childGroups) {
- executionGroups.push(childGroups[group]);
- }
- }
- return executionGroups;
-}
-
-/**
- *
- * @param nodeExecutions list of parent node executionId's
- * @param config
- * @returns
- */
-export function useAllChildNodeExecutionGroupsQuery(
- nodeExecutions: NodeExecution[],
- config: RequestConfig,
-): QueryObserverResult, Error> {
- const queryClient = useQueryClient();
- const shouldEnableFn = (groups) => {
- if (groups.length > 0) {
- return groups.some((group) => {
- // non-empty groups are wrapped in array
- const unwrappedGroup = Array.isArray(group) ? group[0] : group;
- if (unwrappedGroup?.nodeExecutions?.length > 0) {
- /* Return true is any executions are not yet terminal (ie, they can change) */
- return unwrappedGroup.nodeExecutions.some((ne) => {
- return !nodeExecutionIsTerminal(ne);
- });
- } else {
- return false;
- }
- });
- } else {
- return false;
- }
- };
-
- const key = `${nodeExecutions?.[0]?.scopedId}-${nodeExecutions?.[0]?.closure?.phase}`;
-
- return useConditionalQuery>(
- {
- queryKey: [QueryType.NodeExecutionChildList, key, config],
- queryFn: () => fetchAllChildNodeExecutions(queryClient, nodeExecutions, config),
- },
- shouldEnableFn,
- );
-}
-
/** Fetches and groups `NodeExecution`s which are direct children of the given
* `NodeExecution`.
*/
@@ -438,15 +358,29 @@ export function useAllTreeNodeExecutionGroupsQuery(
): QueryObserverResult {
const queryClient = useQueryClient();
const shouldEnableFn = (groups) => {
- if (nodeExecutions.some((ne) => !nodeExecutionIsTerminal(ne))) {
- return true;
+ if (groups.length > 0) {
+ return groups.some((group) => {
+ // non-empty groups are wrapped in array
+ const unwrappedGroup = Array.isArray(group) ? group[0] : group;
+ if (unwrappedGroup?.nodeExecutions?.length > 0) {
+ /* Return true is any executions are not yet terminal (ie, they can change) */
+ return unwrappedGroup.nodeExecutions.some((ne) => {
+ return !nodeExecutionIsTerminal(ne);
+ });
+ } else {
+ return false;
+ }
+ });
+ } else {
+ return false;
}
- return groups.some((group) => !nodeExecutionIsTerminal(group));
};
+ const key = `${nodeExecutions?.[0]?.scopedId}-${nodeExecutions?.[0]?.closure?.phase}`;
+
return useConditionalQuery(
{
- queryKey: [QueryType.NodeExecutionTreeList, nodeExecutions[0]?.id, config],
+ queryKey: [QueryType.NodeExecutionTreeList, key, config],
queryFn: () => fetchAllTreeNodeExecutions(queryClient, nodeExecutions, config),
refetchInterval: executionRefreshIntervalMs,
},
diff --git a/packages/zapp/console/src/components/WorkflowGraph/WorkflowGraph.tsx b/packages/zapp/console/src/components/WorkflowGraph/WorkflowGraph.tsx
index ff0035bb4..fad6e0902 100644
--- a/packages/zapp/console/src/components/WorkflowGraph/WorkflowGraph.tsx
+++ b/packages/zapp/console/src/components/WorkflowGraph/WorkflowGraph.tsx
@@ -11,6 +11,9 @@ import { makeNodeExecutionDynamicWorkflowQuery } from 'components/Workflow/workf
import { createDebugLogger } from 'common/log';
import { CompiledNode } from 'models/Node/types';
import { TaskExecutionPhase } from 'models/Execution/enums';
+import { NodeExecutionsByIdContext } from 'components/Executions/contexts';
+import { useContext } from 'react';
+import { checkForDynamicExecutions } from 'components/common/utils';
import { transformerWorkflowToDag } from './transformerWorkflowToDag';
export interface WorkflowGraphProps {
@@ -19,7 +22,6 @@ export interface WorkflowGraphProps {
selectedPhase?: TaskExecutionPhase;
isDetailsTabClosed: boolean;
workflow: Workflow;
- nodeExecutionsById?: any;
}
interface PrepareDAGResult {
@@ -63,42 +65,12 @@ export const WorkflowGraph: React.FC = (props) => {
onPhaseSelectionChanged,
selectedPhase,
isDetailsTabClosed,
- nodeExecutionsById,
workflow,
} = props;
+ const nodeExecutionsById = useContext(NodeExecutionsByIdContext);
const { dag, staticExecutionIdsMap, error } = workflowToDag(workflow);
- /**
- * Note:
- * Dynamic nodes are deteremined at runtime and thus do not come
- * down as part of the workflow closure. We can detect and place
- * dynamic nodes by finding orphan execution id's and then mapping
- * those executions into the dag by using the executions 'uniqueParentId'
- * to render that node as a subworkflow
- */
- const checkForDynamicExeuctions = (allExecutions, staticExecutions) => {
- const parentsToFetch = {};
- for (const executionId in allExecutions) {
- if (!staticExecutions[executionId]) {
- const dynamicExecution = allExecutions[executionId];
- const dynamicExecutionId = dynamicExecution.metadata.specNodeId || dynamicExecution.id;
- const uniqueParentId = dynamicExecution.fromUniqueParentId;
- if (uniqueParentId) {
- if (parentsToFetch[uniqueParentId]) {
- parentsToFetch[uniqueParentId].push(dynamicExecutionId);
- } else {
- parentsToFetch[uniqueParentId] = [dynamicExecutionId];
- }
- }
- }
- }
- const result = {};
- for (const parentId in parentsToFetch) {
- result[parentId] = allExecutions[parentId];
- }
- return result;
- };
- const dynamicParents = checkForDynamicExeuctions(nodeExecutionsById, staticExecutionIdsMap);
+ const dynamicParents = checkForDynamicExecutions(nodeExecutionsById, staticExecutionIdsMap);
const dynamicWorkflowQuery = useQuery(makeNodeExecutionDynamicWorkflowQuery(dynamicParents));
const renderReactFlowGraph = (dynamicWorkflows) => {
debug('DynamicWorkflows:', dynamicWorkflows);
@@ -118,7 +90,6 @@ export const WorkflowGraph: React.FC = (props) => {
return (
({
ReactFlowWrapper: jest.fn(({ children }) => (
@@ -27,7 +26,6 @@ describe('WorkflowGraph', () => {
onNodeSelectionChanged={jest.fn}
onPhaseSelectionChanged={jest.fn}
workflow={workflow}
- nodeExecutionsById={nodeExecutionsById}
isDetailsTabClosed={true}
/>
,
diff --git a/packages/zapp/console/src/components/common/utils.ts b/packages/zapp/console/src/components/common/utils.ts
index c6c521874..4612bddbe 100644
--- a/packages/zapp/console/src/components/common/utils.ts
+++ b/packages/zapp/console/src/components/common/utils.ts
@@ -16,3 +16,34 @@ export function measureText(fontDefinition: string, text: string) {
context.font = fontDefinition;
return context.measureText(text);
}
+
+/**
+ * Note:
+ * Dynamic nodes are deteremined at runtime and thus do not come
+ * down as part of the workflow closure. We can detect and place
+ * dynamic nodes by finding orphan execution id's and then mapping
+ * those executions into the dag by using the executions 'uniqueParentId'
+ * to render that node as a subworkflow
+ */
+export const checkForDynamicExecutions = (allExecutions, staticExecutions) => {
+ const parentsToFetch = {};
+ for (const executionId in allExecutions) {
+ if (!staticExecutions[executionId]) {
+ const dynamicExecution = allExecutions[executionId];
+ const dynamicExecutionId = dynamicExecution.metadata.specNodeId || dynamicExecution.id;
+ const uniqueParentId = dynamicExecution.fromUniqueParentId;
+ if (uniqueParentId) {
+ if (parentsToFetch[uniqueParentId]) {
+ parentsToFetch[uniqueParentId].push(dynamicExecutionId);
+ } else {
+ parentsToFetch[uniqueParentId] = [dynamicExecutionId];
+ }
+ }
+ }
+ }
+ const result = {};
+ for (const parentId in parentsToFetch) {
+ result[parentId] = allExecutions[parentId];
+ }
+ return result;
+};
diff --git a/packages/zapp/console/src/components/flytegraph/ReactFlow/ReactFlowGraphComponent.tsx b/packages/zapp/console/src/components/flytegraph/ReactFlow/ReactFlowGraphComponent.tsx
index 2fb41b801..b84d2f8bc 100644
--- a/packages/zapp/console/src/components/flytegraph/ReactFlow/ReactFlowGraphComponent.tsx
+++ b/packages/zapp/console/src/components/flytegraph/ReactFlow/ReactFlowGraphComponent.tsx
@@ -1,6 +1,7 @@
import * as React from 'react';
-import { useState, useEffect } from 'react';
+import { useState, useEffect, useContext } from 'react';
import { ConvertFlyteDagToReactFlows } from 'components/flytegraph/ReactFlow/transformDAGToReactFlowV2';
+import { NodeExecutionsByIdContext } from 'components/Executions/contexts';
import { RFWrapperProps, RFGraphTypes, ConvertDagProps } from './types';
import { getRFBackground } from './utils';
import { ReactFlowWrapper } from './ReactFlowWrapper';
@@ -50,9 +51,9 @@ const ReactFlowGraphComponent = (props) => {
onPhaseSelectionChanged,
selectedPhase,
isDetailsTabClosed,
- nodeExecutionsById,
dynamicWorkflows,
} = props;
+ const nodeExecutionsById = useContext(NodeExecutionsByIdContext);
const [state, setState] = useState({
data,
dynamicWorkflows,
diff --git a/packages/zapp/console/src/models/Execution/types.ts b/packages/zapp/console/src/models/Execution/types.ts
index 0ac356e58..b2990fc75 100644
--- a/packages/zapp/console/src/models/Execution/types.ts
+++ b/packages/zapp/console/src/models/Execution/types.ts
@@ -92,6 +92,7 @@ export interface NodeExecution extends Admin.INodeExecution {
closure: NodeExecutionClosure;
metadata?: NodeExecutionMetadata;
scopedId?: string;
+ fromUniqueParentId?: string;
}
export interface NodeExecutionsById {