Skip to content

Commit 1e14d26

Browse files
shubhamraj-gitsanederchik
authored andcommitted
Refresh Dag details page on new run (apache#51173)
* refresh dag page on new run * comments
1 parent f53437b commit 1e14d26

File tree

2 files changed

+81
-6
lines changed

2 files changed

+81
-6
lines changed

airflow-core/src/airflow/ui/src/pages/Dag/Dag.tsx

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
* under the License.
1818
*/
1919
import { ReactFlowProvider } from "@xyflow/react";
20+
import { useState } from "react";
2021
import { FiBarChart, FiCode } from "react-icons/fi";
2122
import { LuChartColumn } from "react-icons/lu";
2223
import { MdDetails, MdOutlineEventNote } from "react-icons/md";
@@ -27,6 +28,7 @@ import { useDagServiceGetDagDetails, useDagsServiceRecentDagRuns } from "openapi
2728
import type { DAGWithLatestDagRunsResponse } from "openapi/requests/types.gen";
2829
import { TaskIcon } from "src/assets/TaskIcon";
2930
import { DetailsLayout } from "src/layouts/Details/DetailsLayout";
31+
import { useRefreshOnNewDagRuns } from "src/queries/useRefreshOnNewDagRuns";
3032
import { isStatePending, useAutoRefresh } from "src/utils";
3133

3234
import { Header } from "./Header";
@@ -53,6 +55,7 @@ export const Dag = () => {
5355
});
5456

5557
const refetchInterval = useAutoRefresh({ dagId });
58+
const [hasPendingRuns, setHasPendingRuns] = useState<boolean | undefined>(false);
5659

5760
// TODO: replace with with a list dag runs by dag id request
5861
const {
@@ -61,14 +64,20 @@ export const Dag = () => {
6164
isLoading: isLoadingRuns,
6265
} = useDagsServiceRecentDagRuns({ dagIds: [dagId], dagRunsLimit: 1 }, undefined, {
6366
enabled: Boolean(dagId),
64-
refetchInterval: (query) =>
65-
query.state.data?.dags
66-
.find((recentDag) => recentDag.dag_id === dagId)
67-
?.latest_dag_runs.some((run) => isStatePending(run.state))
68-
? refetchInterval
69-
: false,
67+
refetchInterval: (query) => {
68+
setHasPendingRuns(
69+
query.state.data?.dags
70+
.find((recentDag) => recentDag.dag_id === dagId)
71+
?.latest_dag_runs.some((run) => isStatePending(run.state)),
72+
);
73+
74+
return hasPendingRuns ? refetchInterval : false;
75+
},
7076
});
7177

78+
// Ensures continuous refresh to detect new runs when there's no pending state and new runs are initiated from other page
79+
useRefreshOnNewDagRuns(dagId, hasPendingRuns);
80+
7281
let dagWithRuns = runsData?.dags.find((recentDag) => recentDag.dag_id === dagId);
7382

7483
if (dagWithRuns === undefined && dag !== undefined) {
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*!
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
import { useQueryClient } from "@tanstack/react-query";
20+
import { useEffect, useRef } from "react";
21+
22+
import {
23+
useDagRunServiceGetDagRuns,
24+
useDagServiceGetDagDetailsKey,
25+
UseDagRunServiceGetDagRunsKeyFn,
26+
UseDagServiceGetDagDetailsKeyFn,
27+
useDagsServiceRecentDagRunsKey,
28+
UseGridServiceGridDataKeyFn,
29+
UseTaskInstanceServiceGetTaskInstancesKeyFn,
30+
} from "openapi/queries";
31+
32+
import { useConfig } from "./useConfig";
33+
34+
export const useRefreshOnNewDagRuns = (dagId: string, hasPendingRuns: boolean | undefined) => {
35+
const queryClient = useQueryClient();
36+
const previousDagRunIdRef = useRef<string>();
37+
const autoRefreshInterval = useConfig("auto_refresh_interval") as number;
38+
39+
const { data } = useDagRunServiceGetDagRuns({ dagId, limit: 1, orderBy: "-run_after" }, undefined, {
40+
enabled: Boolean(dagId) && !hasPendingRuns,
41+
refetchInterval: Boolean(autoRefreshInterval) ? autoRefreshInterval * 1000 : 5000,
42+
});
43+
44+
useEffect(() => {
45+
const latestDagRun = data?.dag_runs[0];
46+
47+
const latestDagRunId = latestDagRun?.dag_run_id;
48+
49+
if ((latestDagRunId ?? "") && previousDagRunIdRef.current !== latestDagRunId) {
50+
previousDagRunIdRef.current = latestDagRunId;
51+
52+
const queryKeys = [
53+
[useDagsServiceRecentDagRunsKey],
54+
[useDagServiceGetDagDetailsKey],
55+
UseDagServiceGetDagDetailsKeyFn({ dagId }, [{ dagId }]),
56+
UseDagRunServiceGetDagRunsKeyFn({ dagId }, [{ dagId }]),
57+
UseTaskInstanceServiceGetTaskInstancesKeyFn({ dagId, dagRunId: "~" }, [{ dagId, dagRunId: "~" }]),
58+
UseGridServiceGridDataKeyFn({ dagId }, [{ dagId }]),
59+
];
60+
61+
queryKeys.forEach((key) => {
62+
void queryClient.invalidateQueries({ queryKey: key });
63+
});
64+
}
65+
}, [data, dagId, queryClient]);
66+
};

0 commit comments

Comments
 (0)