Skip to content

Commit

Permalink
fix: force node executions to pull their status (#737)
Browse files Browse the repository at this point in the history
* fix: force node executions to pull their status

Signed-off-by: Carina Ursu <[email protected]>

* chore: progress

Signed-off-by: Carina Ursu <[email protected]>

* chore: nodes not loading fix

Signed-off-by: Carina Ursu <[email protected]>

* chore: fix

Signed-off-by: Carina Ursu <[email protected]>

* chore: fixes

Signed-off-by: Carina Ursu <[email protected]>

* chore: progress

Signed-off-by: Carina Ursu <[email protected]>

* chore: some refactoring

Signed-off-by: Carina Ursu <[email protected]>

* chore: cleanup

Signed-off-by: Carina Ursu <[email protected]>

* chore: progress

Signed-off-by: Carina Ursu <[email protected]>

* chore: progress

Signed-off-by: Carina Ursu <[email protected]>

* chore: progress

Signed-off-by: Carina Ursu <[email protected]>

* chore: progress

Signed-off-by: Carina Ursu <[email protected]>

* chore: fixes

Signed-off-by: Carina Ursu <[email protected]>

* chore: fix map tasks

Signed-off-by: Carina Ursu <[email protected]>

* chore: dynamic execution fixes

Signed-off-by: Carina Ursu <[email protected]>

* chore: fixes

Signed-off-by: Carina Ursu <[email protected]>

* chore: cleanup

Signed-off-by: Carina Ursu <[email protected]>

* chore: append task executions

Signed-off-by: Carina Ursu <[email protected]>

* chore: fix ExecutionTabContent.test.tsx

Signed-off-by: Carina Ursu <[email protected]>

* chore: fix WorkflowGraph.test.tsx

Signed-off-by: Carina Ursu <[email protected]>

* chore: test fixes

Signed-off-by: Carina Ursu <[email protected]>

* chore: more tests

Signed-off-by: Carina Ursu <[email protected]>

* chore: test fixes

Signed-off-by: Carina Ursu <[email protected]>

* chore: more tests

Signed-off-by: Carina Ursu <[email protected]>

* chore: bump version

Signed-off-by: Carina Ursu <[email protected]>

---------

Signed-off-by: Carina Ursu <[email protected]>
  • Loading branch information
ursucarina authored Apr 17, 2023
1 parent 33ee52a commit 27238ce
Show file tree
Hide file tree
Showing 95 changed files with 3,110 additions and 1,908 deletions.
2 changes: 1 addition & 1 deletion packages/console/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@flyteorg/console",
"version": "0.0.20",
"version": "0.0.21",
"description": "Flyteconsole main app module",
"main": "./dist/index.js",
"module": "./lib/index.js",
Expand Down
9 changes: 7 additions & 2 deletions packages/console/src/components/Executions/CacheStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,15 @@ export interface CacheStatusProps {
variant?: 'normal' | 'iconOnly';
sourceTaskExecutionId?: TaskExecutionIdentifier;
iconStyles?: React.CSSProperties;
className?: string;
}

export const CacheStatus: React.FC<CacheStatusProps> = ({
cacheStatus,
sourceTaskExecutionId,
variant = 'normal',
iconStyles,
className,
}) => {
const commonStyles = useCommonStyles();
const styles = useStyles();
Expand All @@ -100,11 +102,12 @@ export const CacheStatus: React.FC<CacheStatusProps> = ({
const message = cacheStatusMessages[cacheStatus] || unknownCacheStatusString;

return variant === 'iconOnly' ? (
<Tooltip title={message}>
<Tooltip title={message} className={className}>
<NodeExecutionCacheStatusIcon
className={classnames(
commonStyles.iconRight,
commonStyles.iconSecondary,
className,
)}
style={iconStyles}
status={cacheStatus}
Expand All @@ -113,7 +116,7 @@ export const CacheStatus: React.FC<CacheStatusProps> = ({
) : (
<>
<Typography
className={styles.cacheStatus}
className={classnames(styles.cacheStatus, className)}
variant="subtitle1"
color="textSecondary"
>
Expand All @@ -122,6 +125,7 @@ export const CacheStatus: React.FC<CacheStatusProps> = ({
className={classnames(
commonStyles.iconSecondary,
commonStyles.iconLeft,
className,
)}
/>
{message}
Expand All @@ -131,6 +135,7 @@ export const CacheStatus: React.FC<CacheStatusProps> = ({
className={classnames(
commonStyles.primaryLink,
styles.sourceExecutionLink,
className,
)}
to={Routes.ExecutionDetails.makeUrl(
sourceTaskExecutionId.nodeExecutionId.executionId,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import React, {
PropsWithChildren,
useContext,
useEffect,
createContext,
useState,
} from 'react';
import { NodeExecutionIdentifier } from 'models/Execution/types';
import { DetailsPanel } from 'components/common/DetailsPanel';
import { TaskExecutionPhase } from 'models';
import { Core } from '@flyteorg/flyteidl-types';
import { isStartOrEndNode } from 'models/Node/utils';
import { NodeExecutionDetailsPanelContent } from './NodeExecutionDetailsPanelContent';
import { useNodeExecutionsById } from '../contextProvider/NodeExecutionDetails';

export interface DetailsPanelContextData {
selectedExecution?: NodeExecutionIdentifier | null;
setSelectedExecution: (
selectedExecutionId: NodeExecutionIdentifier | null,
) => void;
onNodeSelectionChanged: (newSelection: string[]) => void;
selectedPhase: Core.TaskExecution.Phase | undefined;
setSelectedPhase: (
value: React.SetStateAction<Core.TaskExecution.Phase | undefined>,
) => void;
isDetailsTabClosed: boolean;
setIsDetailsTabClosed: (boolean) => void;
}

export const DetailsPanelContext = createContext<DetailsPanelContextData>(
{} as DetailsPanelContextData,
);

export interface DetailsPanelContextProviderProps {
selectedPhase?: TaskExecutionPhase;
}
export const DetailsPanelContextProvider = ({
children,
}: PropsWithChildren<DetailsPanelContextProviderProps>) => {
const [selectedNodes, setSelectedNodes] = useState<string[]>([]);
const { nodeExecutionsById } = useNodeExecutionsById();

const [selectedPhase, setSelectedPhase] = useState<
TaskExecutionPhase | undefined
>(undefined);

// Note: flytegraph allows multiple selection, but we only support showing
// a single item in the details panel
const [selectedExecution, setSelectedExecution] =
useState<NodeExecutionIdentifier | null>(
selectedNodes.length
? nodeExecutionsById[selectedNodes[0]]
? nodeExecutionsById[selectedNodes[0]].id
: {
nodeId: selectedNodes[0],
executionId:
nodeExecutionsById[Object.keys(nodeExecutionsById)[0]].id
.executionId,
}
: null,
);

const [isDetailsTabClosed, setIsDetailsTabClosed] = useState<boolean>(
!selectedExecution,
);

useEffect(() => {
setIsDetailsTabClosed(!selectedExecution);
}, [selectedExecution]);

const onNodeSelectionChanged = (newSelection: string[]) => {
const validSelection = newSelection.filter(nodeId => {
if (isStartOrEndNode(nodeId)) {
return false;
}
return true;
});
setSelectedNodes(validSelection);
const newSelectedExecution = validSelection.length
? nodeExecutionsById[validSelection[0]]
? nodeExecutionsById[validSelection[0]].id
: {
nodeId: validSelection[0],
executionId:
nodeExecutionsById[Object.keys(nodeExecutionsById)[0]].id
.executionId,
}
: null;
setSelectedExecution(newSelectedExecution);
};

const onCloseDetailsPanel = () => {
setSelectedExecution(null);
setSelectedPhase(undefined);
setSelectedNodes([]);
};

return (
<DetailsPanelContext.Provider
value={{
selectedExecution,
setSelectedExecution,
onNodeSelectionChanged,
selectedPhase,
setSelectedPhase,
isDetailsTabClosed,
setIsDetailsTabClosed,
}}
>
{children}
<DetailsPanel open={!isDetailsTabClosed} onClose={onCloseDetailsPanel}>
{!isDetailsTabClosed && selectedExecution && (
<NodeExecutionDetailsPanelContent
onClose={onCloseDetailsPanel}
taskPhase={selectedPhase ?? TaskExecutionPhase.UNDEFINED}
nodeExecutionId={selectedExecution}
/>
)}
</DetailsPanel>
</DetailsPanelContext.Provider>
);
};

export const useDetailsPanel = () => {
return useContext(DetailsPanelContext);
};
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as React from 'react';
import { useContext } from 'react';
import { Collapse, IconButton } from '@material-ui/core';
import { makeStyles, Theme } from '@material-ui/core/styles';
import ExpandMore from '@material-ui/icons/ExpandMore';
Expand All @@ -7,13 +9,16 @@ import { WaitForQuery } from 'components/common/WaitForQuery';
import { withRouteParams } from 'components/common/withRouteParams';
import { DataError } from 'components/Errors/DataError';
import { Execution } from 'models/Execution/types';
import * as React from 'react';
import { RouteComponentProps } from 'react-router-dom';
import { useQuery, useQueryClient } from 'react-query';
import { Workflow } from 'models/Workflow/types';
import { makeWorkflowQuery } from 'components/Workflow/workflowQueries';
import { ExecutionContext } from '../contexts';
import { useWorkflowExecutionQuery } from '../useWorkflowExecution';
import { ExecutionDetailsAppBarContent } from './ExecutionDetailsAppBarContent';
import { ExecutionMetadata } from './ExecutionMetadata';
import { ExecutionNodeViews } from './ExecutionNodeViews';
import { NodeExecutionDetailsContextProvider } from '../contextProvider/NodeExecutionDetails';

const useStyles = makeStyles((theme: Theme) => ({
expandCollapseButton: {
Expand All @@ -38,51 +43,60 @@ const useStyles = makeStyles((theme: Theme) => ({
},
}));

export interface ExecutionDetailsRouteParams {
domainId: string;
executionId: string;
projectId: string;
}
export type ExecutionDetailsProps = ExecutionDetailsRouteParams;

interface RenderExecutionDetailsProps {
execution: Execution;
}

const RenderExecutionDetails: React.FC<RenderExecutionDetailsProps> = ({
execution,
}) => {
const RenderExecutionContainer: React.FC<{}> = () => {
const styles = useStyles();
const [metadataExpanded, setMetadataExpanded] = React.useState(true);
const toggleMetadata = () => setMetadataExpanded(!metadataExpanded);
const contextValue = {
execution,
};

const { execution } = useContext(ExecutionContext);

const {
closure: { workflowId },
} = execution;

const workflowQuery = useQuery<Workflow, Error>(
makeWorkflowQuery(useQueryClient(), workflowId),
);
return (
<ExecutionContext.Provider value={contextValue}>
<ExecutionDetailsAppBarContent execution={execution} />
<div className={styles.metadataContainer}>
<Collapse in={metadataExpanded}>
<ExecutionMetadata execution={execution} />
</Collapse>
<div className={styles.expandCollapseContainer}>
<IconButton size="small" onClick={toggleMetadata}>
<ExpandMore
className={classnames(styles.expandCollapseButton, {
expanded: metadataExpanded,
})}
/>
</IconButton>
</div>
</div>
<ExecutionNodeViews execution={execution} />
</ExecutionContext.Provider>
<>
{/* Fetches the current workflow to build the execution tree inside NodeExecutionDetailsContextProvider */}
<WaitForQuery errorComponent={DataError} query={workflowQuery}>
{workflow => (
<>
{/* Provides a node execution tree for the current workflow */}
<NodeExecutionDetailsContextProvider workflowId={workflow.id}>
<ExecutionDetailsAppBarContent />
<div className={styles.metadataContainer}>
<Collapse in={metadataExpanded}>
<ExecutionMetadata />
</Collapse>
<div className={styles.expandCollapseContainer}>
<IconButton size="small" onClick={toggleMetadata}>
<ExpandMore
className={classnames(styles.expandCollapseButton, {
expanded: metadataExpanded,
})}
/>
</IconButton>
</div>
</div>

<ExecutionNodeViews />
</NodeExecutionDetailsContextProvider>
</>
)}
</WaitForQuery>
</>
);
};

export interface ExecutionDetailsRouteParams {
domainId: string;
executionId: string;
projectId: string;
}
/** The view component for the Execution Details page */
export const ExecutionDetailsContainer: React.FC<ExecutionDetailsProps> = ({
export const ExecutionDetailsWrapper: React.FC<ExecutionDetailsRouteParams> = ({
executionId,
domainId,
projectId,
Expand All @@ -93,21 +107,28 @@ export const ExecutionDetailsContainer: React.FC<ExecutionDetailsProps> = ({
name: executionId,
};

const renderExecutionDetails = (execution: Execution) => (
<RenderExecutionDetails execution={execution} />
);
const workflowExecutionQuery = useWorkflowExecutionQuery(id);

return (
// get the workflow execution query to get the current workflow id
<WaitForQuery
errorComponent={DataError}
loadingComponent={LargeLoadingSpinner}
query={useWorkflowExecutionQuery(id)}
query={workflowExecutionQuery}
>
{renderExecutionDetails}
{(execution: Execution) => (
<ExecutionContext.Provider
value={{
execution,
}}
>
<RenderExecutionContainer />
</ExecutionContext.Provider>
)}
</WaitForQuery>
);
};

export const ExecutionDetails: React.FunctionComponent<
RouteComponentProps<ExecutionDetailsRouteParams>
> = withRouteParams<ExecutionDetailsRouteParams>(ExecutionDetailsContainer);
> = withRouteParams<ExecutionDetailsRouteParams>(ExecutionDetailsWrapper);
Loading

0 comments on commit 27238ce

Please sign in to comment.