You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by ur...@apache.org on 2022/08/23 13:28:47 UTC
[airflow] branch main updated: Use per-timetable ordering in grid UI (#25880)
This is an automated email from the ASF dual-hosted git repository.
uranusjr pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 6e37680e20 Use per-timetable ordering in grid UI (#25880)
6e37680e20 is described below
commit 6e37680e20586f5ca882258892bb6da67a651807
Author: Brent Bovenzi <br...@gmail.com>
AuthorDate: Tue Aug 23 14:28:30 2022 +0100
Use per-timetable ordering in grid UI (#25880)
Co-authored-by: Tzu-ping Chung <ur...@gmail.com>
---
airflow/www/static/js/api/useGridData.ts | 11 +++-
airflow/www/static/js/dag/details/Header.tsx | 6 +--
airflow/www/static/js/dag/grid/dagRuns/Tooltip.tsx | 58 +++++++++++-----------
airflow/www/static/js/types/index.ts | 3 ++
airflow/www/static/js/utils/index.test.ts | 28 ++++++++++-
airflow/www/static/js/utils/index.ts | 13 ++++-
airflow/www/views.py | 1 +
tests/www/views/test_views_grid.py | 3 ++
8 files changed, 89 insertions(+), 34 deletions(-)
diff --git a/airflow/www/static/js/api/useGridData.ts b/airflow/www/static/js/api/useGridData.ts
index dc5e5dfb9a..2e2ca1cb95 100644
--- a/airflow/www/static/js/api/useGridData.ts
+++ b/airflow/www/static/js/api/useGridData.ts
@@ -26,7 +26,8 @@ import useErrorToast from 'src/utils/useErrorToast';
import useFilters, {
BASE_DATE_PARAM, NUM_RUNS_PARAM, RUN_STATE_PARAM, RUN_TYPE_PARAM, now,
} from 'src/dag/useFilters';
-import type { Task, DagRun } from 'src/types';
+import type { Task, DagRun, RunOrdering } from 'src/types';
+import { camelCase } from 'lodash';
const DAG_ID_PARAM = 'dag_id';
@@ -38,6 +39,7 @@ const urlRoot = getMetaValue('root');
interface GridData {
dagRuns: DagRun[];
groups: Task;
+ ordering: RunOrdering;
}
const emptyGridData: GridData = {
@@ -47,8 +49,14 @@ const emptyGridData: GridData = {
label: null,
instances: [],
},
+ ordering: [],
};
+const formatOrdering = (data: GridData) => ({
+ ...data,
+ ordering: data.ordering.map((o: string) => camelCase(o)) as RunOrdering,
+});
+
export const areActiveRuns = (runs: DagRun[] = []) => runs.filter((run) => ['manual', 'manual'].includes(run.runType)).filter((run) => ['queued', 'running', 'scheduled'].includes(run.state)).length > 0;
const useGridData = () => {
@@ -88,6 +96,7 @@ const useGridData = () => {
});
throw (error);
},
+ select: formatOrdering,
},
);
return {
diff --git a/airflow/www/static/js/dag/details/Header.tsx b/airflow/www/static/js/dag/details/Header.tsx
index 3b957f6a17..d7ddb98564 100644
--- a/airflow/www/static/js/dag/details/Header.tsx
+++ b/airflow/www/static/js/dag/details/Header.tsx
@@ -25,7 +25,7 @@ import {
Text,
} from '@chakra-ui/react';
-import { getMetaValue, getTask } from 'src/utils';
+import { getDagRunLabel, getMetaValue, getTask } from 'src/utils';
import useSelection from 'src/dag/useSelection';
import Time from 'src/components/Time';
import { useGridData } from 'src/api';
@@ -36,7 +36,7 @@ import BreadcrumbText from './BreadcrumbText';
const dagId = getMetaValue('dag_id');
const Header = () => {
- const { data: { dagRuns, groups } } = useGridData();
+ const { data: { dagRuns, groups, ordering } } = useGridData();
const { selected: { taskId, runId, mapIndex }, onSelect, clearSelection } = useSelection();
const dagRun = dagRuns.find((r) => r.runId === runId);
@@ -58,7 +58,7 @@ const Header = () => {
|| runId.includes('backfill__')
|| runId.includes('dataset_triggered__')
)
- ? <Time dateTime={dagRun.dataIntervalStart || dagRun.executionDate} />
+ ? <Time dateTime={getDagRunLabel({ dagRun, ordering })} />
: runId;
runLabel = (
<>
diff --git a/airflow/www/static/js/dag/grid/dagRuns/Tooltip.tsx b/airflow/www/static/js/dag/grid/dagRuns/Tooltip.tsx
index ae52d9bdaa..f8b577a1bc 100644
--- a/airflow/www/static/js/dag/grid/dagRuns/Tooltip.tsx
+++ b/airflow/www/static/js/dag/grid/dagRuns/Tooltip.tsx
@@ -19,9 +19,12 @@
import React from 'react';
import { Box, Text } from '@chakra-ui/react';
+import { startCase } from 'lodash';
import { formatDuration } from 'src/datetime_utils';
import Time from 'src/components/Time';
+import { getDagRunLabel } from 'src/utils';
+import { useGridData } from 'src/api';
import type { RunWithDuration } from './index';
@@ -29,33 +32,32 @@ interface Props {
dagRun: RunWithDuration;
}
-const DagRunTooltip = ({
- dagRun: {
- state, duration, dataIntervalStart, executionDate, runType,
- },
-}: Props) => (
- <Box py="2px">
- <Text>
- Status:
- {' '}
- {state || 'no status'}
- </Text>
- <Text whiteSpace="nowrap">
- Run:
- {' '}
- <Time dateTime={dataIntervalStart || executionDate} />
- </Text>
- <Text>
- Duration:
- {' '}
- {formatDuration(duration)}
- </Text>
- <Text>
- Type:
- {' '}
- {runType}
- </Text>
- </Box>
-);
+const DagRunTooltip = ({ dagRun }: Props) => {
+ const { data: { ordering } } = useGridData();
+ return (
+ <Box py="2px">
+ <Text>
+ Status:
+ {' '}
+ {dagRun.state || 'no status'}
+ </Text>
+ <Text whiteSpace="nowrap">
+ {startCase(ordering[0] || ordering[1])}
+ {': '}
+ <Time dateTime={getDagRunLabel({ dagRun, ordering })} />
+ </Text>
+ <Text>
+ Duration:
+ {' '}
+ {formatDuration(dagRun.duration)}
+ </Text>
+ <Text>
+ Type:
+ {' '}
+ {dagRun.runType}
+ </Text>
+ </Box>
+ );
+};
export default DagRunTooltip;
diff --git a/airflow/www/static/js/types/index.ts b/airflow/www/static/js/types/index.ts
index 6918320f15..34f40f4dbc 100644
--- a/airflow/www/static/js/types/index.ts
+++ b/airflow/www/static/js/types/index.ts
@@ -79,6 +79,8 @@ interface Task {
hasOutletDatasets?: boolean;
}
+type RunOrdering = ('dataIntervalStart' | 'executionDate' | 'dataIntervalEnd')[];
+
export type {
Dag,
DagRun,
@@ -87,4 +89,5 @@ export type {
TaskInstance,
Task,
API,
+ RunOrdering,
};
diff --git a/airflow/www/static/js/utils/index.test.ts b/airflow/www/static/js/utils/index.test.ts
index e3d9f69386..03d3cf4d82 100644
--- a/airflow/www/static/js/utils/index.test.ts
+++ b/airflow/www/static/js/utils/index.test.ts
@@ -18,7 +18,8 @@
*/
import { isEmpty } from 'lodash';
-import { getTask, getTaskSummary } from '.';
+import type { DagRun } from 'src/types';
+import { getDagRunLabel, getTask, getTaskSummary } from '.';
const sampleTasks = {
id: null,
@@ -112,3 +113,28 @@ describe('Test getTaskSummary()', () => {
expect(isEmpty(summary.operators)).toBeTruthy();
});
});
+
+describe('Test getDagRunLabel', () => {
+ const dagRun = {
+ dagId: 'dagId',
+ runId: 'run1',
+ dataIntervalStart: '2021-12-07T21:14:19.704433+00:00',
+ dataIntervalEnd: '2021-12-08T21:14:19.704433+00:00',
+ startDate: '2021-11-08T21:14:19.704433+00:00',
+ endDate: '2021-11-08T21:17:13.206426+00:00',
+ state: 'failed',
+ runType: 'scheduled',
+ executionDate: '2021-12-09T21:14:19.704433+00:00',
+ lastSchedulingDecision: '2021-11-08T21:14:19.704433+00:00',
+ } as DagRun;
+
+ test('Defaults to dataIntervalStart', async () => {
+ const runLabel = getDagRunLabel({ dagRun });
+ expect(runLabel).toBe(dagRun.dataIntervalStart);
+ });
+
+ test('Passing an order overrides default', async () => {
+ const runLabel = getDagRunLabel({ dagRun, ordering: ['executionDate'] });
+ expect(runLabel).toBe(dagRun.executionDate);
+ });
+});
diff --git a/airflow/www/static/js/utils/index.ts b/airflow/www/static/js/utils/index.ts
index ffbdc00289..a8506eaf91 100644
--- a/airflow/www/static/js/utils/index.ts
+++ b/airflow/www/static/js/utils/index.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import type { Task } from 'src/types';
+import type { DagRun, RunOrdering, Task } from 'src/types';
// Delay in ms for various hover actions
const hoverDelay = 200;
@@ -114,6 +114,16 @@ const getTaskSummary = ({
};
};
+interface RunLabelProps {
+ dagRun: DagRun;
+ ordering?: RunOrdering;
+}
+
+const getDagRunLabel = ({
+ dagRun,
+ ordering = ['dataIntervalEnd', 'executionDate'],
+}: RunLabelProps) => dagRun[ordering[0]] ?? dagRun[ordering[1]];
+
export {
hoverDelay,
finalStatesMap,
@@ -121,4 +131,5 @@ export {
appendSearchParams,
getTask,
getTaskSummary,
+ getDagRunLabel,
};
diff --git a/airflow/www/views.py b/airflow/www/views.py
index 2aec0df078..56011fcd27 100644
--- a/airflow/www/views.py
+++ b/airflow/www/views.py
@@ -3632,6 +3632,7 @@ class Airflow(AirflowBaseView):
data = {
'groups': dag_to_grid(dag, dag_runs, session),
'dag_runs': encoded_runs,
+ 'ordering': dag.timetable.run_ordering,
}
# avoid spaces to reduce payload size
return (
diff --git a/tests/www/views/test_views_grid.py b/tests/www/views/test_views_grid.py
index 6ca422c68a..9c756ee5e6 100644
--- a/tests/www/views/test_views_grid.py
+++ b/tests/www/views/test_views_grid.py
@@ -124,6 +124,7 @@ def test_no_runs(admin_client, dag_without_runs):
'instances': [],
'label': None,
},
+ 'ordering': ['data_interval_end', 'execution_date'],
}
@@ -272,6 +273,7 @@ def test_one_run(admin_client, dag_with_runs: List[DagRun], session):
'instances': [],
'label': None,
},
+ 'ordering': ['data_interval_end', 'execution_date'],
}
@@ -323,6 +325,7 @@ def test_has_outlet_dataset_flag(admin_client, dag_maker, session, app, monkeypa
'instances': [],
'label': None,
},
+ 'ordering': ['data_interval_end', 'execution_date'],
}