This is an automated email from the ASF dual-hosted git repository. bbovenzi pushed a commit to branch mapped-task-drawer in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 194a371f11e026ba74a7a15691d63d190ea4cae8 Author: Brent Bovenzi <[email protected]> AuthorDate: Tue Mar 8 15:54:45 2022 -0500 dag run actions w/ react-query --- airflow/www/static/js/tree/Tree.jsx | 3 +- airflow/www/static/js/tree/api/index.js | 6 ++ .../js/tree/api/{index.js => useClearRun.js} | 38 +++++++++---- .../js/tree/api/{index.js => useMarkFailedRun.js} | 38 +++++++++---- .../js/tree/api/{index.js => useMarkSuccessRun.js} | 38 +++++++++---- .../www/static/js/tree/details/content/DagRun.jsx | 64 ++-------------------- airflow/www/static/js/tree/index.jsx | 1 - airflow/www/static/js/tree/useTreeData.js | 20 ++++++- 8 files changed, 110 insertions(+), 98 deletions(-) diff --git a/airflow/www/static/js/tree/Tree.jsx b/airflow/www/static/js/tree/Tree.jsx index b777d73..a0fa54b 100644 --- a/airflow/www/static/js/tree/Tree.jsx +++ b/airflow/www/static/js/tree/Tree.jsx @@ -128,7 +128,8 @@ const Tree = () => { overflowX="auto" ref={scrollRef} flexGrow={1} - width={isOpen && '300px'} + maxWidth={isOpen && '300px'} + minWidth={isOpen && '300px'} > <Table height={0}> <Thead> diff --git a/airflow/www/static/js/tree/api/index.js b/airflow/www/static/js/tree/api/index.js index 3327fef..96c4a67 100644 --- a/airflow/www/static/js/tree/api/index.js +++ b/airflow/www/static/js/tree/api/index.js @@ -22,6 +22,9 @@ import camelcaseKeys from 'camelcase-keys'; import useDag from './useDag'; import useTasks from './useTasks'; +import useClearRun from './useClearRun'; +import useMarkFailedRun from './useMarkFailedRun'; +import useMarkSuccessRun from './useMarkSuccessRun'; axios.interceptors.response.use( (res) => (res.data ? camelcaseKeys(res.data, { deep: true }) : res), @@ -30,4 +33,7 @@ axios.interceptors.response.use( export { useDag, useTasks, + useClearRun, + useMarkFailedRun, + useMarkSuccessRun, }; diff --git a/airflow/www/static/js/tree/api/index.js b/airflow/www/static/js/tree/api/useClearRun.js similarity index 52% copy from airflow/www/static/js/tree/api/index.js copy to airflow/www/static/js/tree/api/useClearRun.js index 3327fef..8be4d17 100644 --- a/airflow/www/static/js/tree/api/index.js +++ b/airflow/www/static/js/tree/api/useClearRun.js @@ -18,16 +18,32 @@ */ import axios from 'axios'; -import camelcaseKeys from 'camelcase-keys'; +import { useMutation, useQueryClient } from 'react-query'; +import { getMetaValue } from '../../utils'; -import useDag from './useDag'; -import useTasks from './useTasks'; +export default function useClearRun(dagId, runId) { + const queryClient = useQueryClient(); + return useMutation( + ['dagRunClear', dagId, runId], + () => { + const csrfToken = getMetaValue('csrf_token'); + const params = new URLSearchParams({ + csrf_token: csrfToken, + confirmed: true, + dag_id: dagId, + dag_run_id: runId, + }).toString(); -axios.interceptors.response.use( - (res) => (res.data ? camelcaseKeys(res.data, { deep: true }) : res), -); - -export { - useDag, - useTasks, -}; + return axios.post('/dagrun_clear', params, { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + }); + }, + { + onSettled: () => { + queryClient.invalidateQueries('treeData'); + }, + }, + ); +} diff --git a/airflow/www/static/js/tree/api/index.js b/airflow/www/static/js/tree/api/useMarkFailedRun.js similarity index 52% copy from airflow/www/static/js/tree/api/index.js copy to airflow/www/static/js/tree/api/useMarkFailedRun.js index 3327fef..dec25fe 100644 --- a/airflow/www/static/js/tree/api/index.js +++ b/airflow/www/static/js/tree/api/useMarkFailedRun.js @@ -18,16 +18,32 @@ */ import axios from 'axios'; -import camelcaseKeys from 'camelcase-keys'; +import { useMutation, useQueryClient } from 'react-query'; +import { getMetaValue } from '../../utils'; -import useDag from './useDag'; -import useTasks from './useTasks'; +export default function useMarkFailedRun(dagId, runId) { + const queryClient = useQueryClient(); + return useMutation( + ['dagRunFailed', dagId, runId], + () => { + const csrfToken = getMetaValue('csrf_token'); + const params = new URLSearchParams({ + csrf_token: csrfToken, + confirmed: true, + dag_id: dagId, + dag_run_id: runId, + }).toString(); -axios.interceptors.response.use( - (res) => (res.data ? camelcaseKeys(res.data, { deep: true }) : res), -); - -export { - useDag, - useTasks, -}; + return axios.post('/dagrun_failed', params, { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + }); + }, + { + onSettled: () => { + queryClient.invalidateQueries('treeData'); + }, + }, + ); +} diff --git a/airflow/www/static/js/tree/api/index.js b/airflow/www/static/js/tree/api/useMarkSuccessRun.js similarity index 52% copy from airflow/www/static/js/tree/api/index.js copy to airflow/www/static/js/tree/api/useMarkSuccessRun.js index 3327fef..7e1d589 100644 --- a/airflow/www/static/js/tree/api/index.js +++ b/airflow/www/static/js/tree/api/useMarkSuccessRun.js @@ -18,16 +18,32 @@ */ import axios from 'axios'; -import camelcaseKeys from 'camelcase-keys'; +import { useMutation, useQueryClient } from 'react-query'; +import { getMetaValue } from '../../utils'; -import useDag from './useDag'; -import useTasks from './useTasks'; +export default function useMarkSuccessRun(dagId, runId) { + const queryClient = useQueryClient(); + return useMutation( + ['dagRunSuccess', dagId, runId], + () => { + const csrfToken = getMetaValue('csrf_token'); + const params = new URLSearchParams({ + csrf_token: csrfToken, + confirmed: true, + dag_id: dagId, + dag_run_id: runId, + }).toString(); -axios.interceptors.response.use( - (res) => (res.data ? camelcaseKeys(res.data, { deep: true }) : res), -); - -export { - useDag, - useTasks, -}; + return axios.post('/dagrun_success', params, { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + }); + }, + { + onSettled: () => { + queryClient.invalidateQueries('treeData'); + }, + }, + ); +} diff --git a/airflow/www/static/js/tree/details/content/DagRun.jsx b/airflow/www/static/js/tree/details/content/DagRun.jsx index be06794..b47907b 100644 --- a/airflow/www/static/js/tree/details/content/DagRun.jsx +++ b/airflow/www/static/js/tree/details/content/DagRun.jsx @@ -20,7 +20,6 @@ /* global moment */ import React from 'react'; -import axios from 'axios'; import { Flex, Text, @@ -30,71 +29,16 @@ import { import { MdPlayArrow } from 'react-icons/md'; import { formatDateTime, formatDuration } from '../../../datetime_utils'; -import { getMetaValue } from '../../../utils'; +import { useClearRun, useMarkFailedRun, useMarkSuccessRun } from '../../api'; const DagRun = ({ dagRun: { dagId, state, runId, duration, dataIntervalStart, dataIntervalEnd, startDate, endDate, runType, }, }) => { - const csrfToken = getMetaValue('csrf_token'); - - const onClear = async () => { - const params = new URLSearchParams({ - csrf_token: csrfToken, - confirmed: true, - dag_id: dagId, - dag_run_id: runId, - }).toString(); - - try { - await axios.post('/dagrun_clear', params, { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - }); - } catch (e) { - console.error(e); - } - }; - - const markFailed = async () => { - const params = new URLSearchParams({ - csrf_token: csrfToken, - confirmed: true, - dag_id: dagId, - dag_run_id: runId, - }).toString(); - - try { - await axios.post('/dagrun_failed', params, { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - }); - } catch (e) { - console.error(e); - } - }; - - const markSuccess = async () => { - const params = new URLSearchParams({ - csrf_token: csrfToken, - confirmed: true, - dag_id: dagId, - dag_run_id: runId, - }).toString(); - - try { - await axios.post('/dagrun_success', params, { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - }); - } catch (e) { - console.error(e); - } - }; + const { mutate: onClear } = useClearRun(dagId, runId); + const { mutate: markFailed } = useMarkFailedRun(dagId, runId); + const { mutate: markSuccess } = useMarkSuccessRun(dagId, runId); return ( <Box fontSize="12px" py="4px"> diff --git a/airflow/www/static/js/tree/index.jsx b/airflow/www/static/js/tree/index.jsx index a509d25..4eea821 100644 --- a/airflow/www/static/js/tree/index.jsx +++ b/airflow/www/static/js/tree/index.jsx @@ -36,7 +36,6 @@ const myCache = createCache({ }); const mainElement = document.getElementById('react-container'); shadowRoot.appendChild(mainElement); -const queryClient = new QueryClient(); const queryClient = new QueryClient({ defaultOptions: { diff --git a/airflow/www/static/js/tree/useTreeData.js b/airflow/www/static/js/tree/useTreeData.js index e26a9c9..24481b3 100644 --- a/airflow/www/static/js/tree/useTreeData.js +++ b/airflow/www/static/js/tree/useTreeData.js @@ -19,6 +19,7 @@ /* global treeData, localStorage, autoRefreshInterval, fetch */ +import { useEffect } from 'react'; import { useDisclosure } from '@chakra-ui/react'; import camelcaseKeys from 'camelcase-keys'; import { useQuery } from 'react-query'; @@ -54,8 +55,9 @@ const formatData = (data) => { const useTreeData = () => { const initialData = formatData(treeData); + const canRefresh = isPaused !== 'True' && !JSON.parse(localStorage.getItem(autoRefreshKey)); - const defaultIsOpen = isPaused !== 'True' && !JSON.parse(localStorage.getItem(autoRefreshKey)) && areActiveRuns(initialData.dagRuns); + const defaultIsOpen = canRefresh && areActiveRuns(initialData.dagRuns); const { isOpen: isRefreshOn, onToggle, onClose } = useDisclosure({ defaultIsOpen }); const onToggleRefresh = () => { @@ -88,12 +90,24 @@ const useTreeData = () => { dagRuns: [], }; }, { - // only enabled and refetch if the refresh switch is on - enabled: isRefreshOn, + // only refetch if the refresh switch is on refetchInterval: isRefreshOn && autoRefreshInterval * 1000, initialData, }); + // turn on autorefresh if data is active again + useEffect(() => { + if ( + query.data.dagRuns + && JSON.stringify(query.data.dagRuns) !== JSON.stringify(initialData.dagRuns) + && canRefresh + && areActiveRuns(query.data.dagRuns) + && !isRefreshOn + ) { + onToggle(); + } + }, [canRefresh, initialData.dagRuns, isRefreshOn, onToggle, query.data]); + return { ...query, isRefreshOn,
