Skip to content

Commit

Permalink
refactor: Remove ExecutionDataCache in favor of react-query (#126)
Browse files Browse the repository at this point in the history
* refactor: first step of using queries for NE table

* refactor: removing data cache from first layer of NE table

* refactor: removing remaining execution data cache usage

* refactor: rename QueryKey type and remove bug workaround

* refactor: fixing remaining consumers of NEs
  • Loading branch information
schottra committed Jan 4, 2021
1 parent 1de2618 commit be9fd46
Show file tree
Hide file tree
Showing 50 changed files with 3,629 additions and 3,591 deletions.
6 changes: 4 additions & 2 deletions src/components/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { CssBaseline } from '@material-ui/core';
import { ThemeProvider } from '@material-ui/styles';
import { env } from 'common/env';
import { debug, debugPrefix } from 'common/log';
import { QueryAuthorizationObserver } from 'components/common/QueryAuthorizationObserver';
import { queryClient } from 'components/common/queryCache';
import { APIContext, useAPIState } from 'components/data/apiContext';
import { QueryAuthorizationObserver } from 'components/data/QueryAuthorizationObserver';
import { createQueryClient } from 'components/data/queryCache';
import { LoginExpiredHandler } from 'components/Errors/LoginExpiredHandler';
import { SystemStatusBanner } from 'components/Notifications/SystemStatusBanner';
import { skeletonColor, skeletonHighlightColor } from 'components/Theme';
Expand All @@ -21,6 +21,8 @@ import { history } from 'routes/history';
import { NavBarRouter } from 'routes/NavBarRouter';
import { ErrorBoundary } from '../common';

const queryClient = createQueryClient();

export const AppComponent: React.StatelessComponent<{}> = () => {
if (env.NODE_ENV === 'development') {
debug.enable(`${debugPrefix}*:*`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import { RefreshConfig } from 'components/hooks';
import { Execution } from 'models';
import * as React from 'react';
import { executionRefreshIntervalMs } from '../constants';
import { ExecutionContext, ExecutionDataCacheContext } from '../contexts';
import { useExecutionDataCache } from '../useExecutionDataCache';
import { ExecutionContext } from '../contexts';
import { useWorkflowExecutionQuery } from '../useWorkflowExecution';
import { executionIsTerminal } from '../utils';
import { ExecutionDetailsAppBarContent } from './ExecutionDetailsAppBarContent';
Expand Down Expand Up @@ -46,6 +45,7 @@ export interface ExecutionDetailsRouteParams {
}
export type ExecutionDetailsProps = ExecutionDetailsRouteParams;

// TODO: Remove?
const executionRefreshConfig: RefreshConfig<Execution> = {
interval: executionRefreshIntervalMs,
valueIsFinal: executionIsTerminal
Expand All @@ -61,7 +61,6 @@ const RenderExecutionDetails: React.FC<RenderExecutionDetailsProps> = ({
const styles = useStyles();
const [metadataExpanded, setMetadataExpanded] = React.useState(true);
const toggleMetadata = () => setMetadataExpanded(!metadataExpanded);
const dataCache = useExecutionDataCache();
const contextValue = {
execution
};
Expand All @@ -83,9 +82,7 @@ const RenderExecutionDetails: React.FC<RenderExecutionDetailsProps> = ({
</IconButton>
</div>
</div>
<ExecutionDataCacheContext.Provider value={dataCache}>
<ExecutionNodeViews execution={execution} />
</ExecutionDataCacheContext.Provider>
<ExecutionNodeViews execution={execution} />
</ExecutionContext.Provider>
);
};
Expand Down
53 changes: 29 additions & 24 deletions src/components/Executions/ExecutionDetails/ExecutionNodeViews.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { Tab, Tabs } from '@material-ui/core';
import { makeStyles, Theme } from '@material-ui/core/styles';
import { WaitForData } from 'components/common';
import { WaitForQuery } from 'components/common/WaitForQuery';
import { useTabState } from 'components/hooks/useTabState';
import { secondaryBackgroundColor } from 'components/Theme';
import { Execution } from 'models';
import { Execution, NodeExecution } from 'models';
import * as React from 'react';
import { NodeExecutionsRequestConfigContext } from '../contexts';
import { ExecutionFilters } from '../ExecutionFilters';
import { useNodeExecutionFiltersState } from '../filters/useExecutionFiltersState';
import { NodeExecutionsTable } from '../Tables/NodeExecutionsTable';
import { useWorkflowExecutionState } from '../useWorkflowExecutionState';
import { tabs } from './constants';
import { ExecutionWorkflowGraph } from './ExecutionWorkflowGraph';
import { useExecutionNodeViewsState } from './useExecutionNodeViewsState';

const useStyles = makeStyles((theme: Theme) => ({
filters: {
Expand Down Expand Up @@ -49,13 +49,28 @@ export const ExecutionNodeViews: React.FC<ExecutionNodeViewsProps> = ({
tabState.value === tabs.nodes.id ? filterState.appliedFilters : [];

const {
workflow,
nodeExecutions,
nodeExecutionsQuery,
nodeExecutionsRequestConfig
} = useWorkflowExecutionState(execution, appliedFilters);
} = useExecutionNodeViewsState(execution, appliedFilters);

// TODO: Handle error case (table usually rendered the error)
const renderNodeExecutionsTable = (nodeExecutions: NodeExecution[]) => (
<NodeExecutionsRequestConfigContext.Provider
value={nodeExecutionsRequestConfig}
>
<NodeExecutionsTable nodeExecutions={nodeExecutions} />
</NodeExecutionsRequestConfigContext.Provider>
);

const renderExecutionWorkflowGraph = (nodeExecutions: NodeExecution[]) => (
<ExecutionWorkflowGraph
nodeExecutions={nodeExecutions}
workflowId={execution.closure.workflowId}
/>
);

return (
<WaitForData {...workflow}>
<>
<Tabs className={styles.tabs} {...tabState}>
<Tab value={tabs.nodes.id} label={tabs.nodes.label} />
<Tab value={tabs.graph.id} label={tabs.graph.label} />
Expand All @@ -66,27 +81,17 @@ export const ExecutionNodeViews: React.FC<ExecutionNodeViewsProps> = ({
<div className={styles.filters}>
<ExecutionFilters {...filterState} />
</div>
<WaitForData {...nodeExecutions}>
<NodeExecutionsRequestConfigContext.Provider
value={nodeExecutionsRequestConfig}
>
<NodeExecutionsTable
{...nodeExecutions}
moreItemsAvailable={false}
/>
</NodeExecutionsRequestConfigContext.Provider>
</WaitForData>
<WaitForQuery query={nodeExecutionsQuery}>
{renderNodeExecutionsTable}
</WaitForQuery>
</>
)}
{tabState.value === tabs.graph.id && (
<WaitForData {...nodeExecutions}>
<ExecutionWorkflowGraph
nodeExecutions={nodeExecutions.value}
workflow={workflow.value}
/>
</WaitForData>
<WaitForQuery query={nodeExecutionsQuery}>
{renderExecutionWorkflowGraph}
</WaitForQuery>
)}
</div>
</WaitForData>
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,28 +1,34 @@
import { DetailsPanel } from 'components/common';
import { WaitForQuery } from 'components/common/WaitForQuery';
import { makeWorkflowQuery } from 'components/Workflow/workflowQueries';
import { WorkflowGraph } from 'components/WorkflowGraph';
import { keyBy } from 'lodash';
import { endNodeId, startNodeId } from 'models';
import { Workflow } from 'models/Workflow';
import { endNodeId, NodeExecution, startNodeId } from 'models';
import { Workflow, WorkflowId } from 'models/Workflow';
import * as React from 'react';
import { useQuery } from 'react-query';
import { NodeExecutionsContext } from '../contexts';
import { DetailedNodeExecution } from '../types';
import { NodeExecutionDetails } from './NodeExecutionDetails';
import { NodeExecutionDetailsPanelContent } from './NodeExecutionDetailsPanelContent';
import { TaskExecutionNodeRenderer } from './TaskExecutionNodeRenderer/TaskExecutionNodeRenderer';

export interface ExecutionWorkflowGraphProps {
nodeExecutions: DetailedNodeExecution[];
workflow: Workflow;
nodeExecutions: NodeExecution[];
workflowId: WorkflowId;
}

/** Wraps a WorkflowGraph, customizing it to also show execution statuses */
export const ExecutionWorkflowGraph: React.FC<ExecutionWorkflowGraphProps> = ({
nodeExecutions,
workflow
workflowId
}) => {
const workflowQuery = useQuery<Workflow, Error>(
makeWorkflowQuery(workflowId)
);
const nodeExecutionsById = React.useMemo(
() => keyBy(nodeExecutions, 'id.nodeId'),
[nodeExecutions]
);

const [selectedNodes, setSelectedNodes] = React.useState<string[]>([]);
const onNodeSelectionChanged = (newSelection: string[]) => {
const validSelection = newSelection.filter(nodeId => {
Expand All @@ -38,29 +44,35 @@ export const ExecutionWorkflowGraph: React.FC<ExecutionWorkflowGraphProps> = ({
setSelectedNodes(validSelection);
};

// Note: flytegraph allows multiple selection, but we only support showing
// a single item in the details panel
const selectedExecution = selectedNodes.length
? nodeExecutionsById[selectedNodes[0]]
? nodeExecutionsById[selectedNodes[0]].id
: null;
const onCloseDetailsPanel = () => setSelectedNodes([]);

const renderGraph = (workflow: Workflow) => (
<WorkflowGraph
onNodeSelectionChanged={onNodeSelectionChanged}
nodeRenderer={TaskExecutionNodeRenderer}
selectedNodes={selectedNodes}
workflow={workflow}
/>
);

return (
<>
<NodeExecutionsContext.Provider value={nodeExecutionsById}>
<WorkflowGraph
onNodeSelectionChanged={onNodeSelectionChanged}
nodeRenderer={TaskExecutionNodeRenderer}
selectedNodes={selectedNodes}
workflow={workflow}
/>
<WaitForQuery query={workflowQuery}>{renderGraph}</WaitForQuery>
</NodeExecutionsContext.Provider>
<DetailsPanel
open={selectedExecution !== null}
onClose={onCloseDetailsPanel}
>
{selectedExecution && (
<NodeExecutionDetails
<NodeExecutionDetailsPanelContent
onClose={onCloseDetailsPanel}
execution={selectedExecution}
nodeExecutionId={selectedExecution}
/>
)}
</DetailsPanel>
Expand Down
Loading

0 comments on commit be9fd46

Please sign in to comment.