You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by bb...@apache.org on 2022/04/19 14:00:22 UTC
[airflow] 02/04: Readd mapped instance table selection
This is an automated email from the ASF dual-hosted git repository.
bbovenzi pushed a commit to branch mapped-instance-actions
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 5bee03ac9e7327880f428746e09111eedc2b27b9
Author: Brent Bovenzi <br...@gmail.com>
AuthorDate: Tue Apr 12 14:51:45 2022 -0400
Readd mapped instance table selection
---
airflow/www/static/js/tree/Table.jsx | 4 +-
airflow/www/static/js/tree/api/useClearTask.js | 4 +-
.../www/static/js/tree/api/useConfirmMarkTask.js | 12 +++---
.../www/static/js/tree/api/useMarkFailedTask.js | 4 +-
.../www/static/js/tree/api/useMarkSuccessTask.js | 4 +-
airflow/www/static/js/tree/api/useRunTask.js | 43 ++++++++++++----------
.../js/tree/details/content/taskInstance/index.jsx | 25 ++++++-------
.../content/taskInstance/taskActions/Clear.jsx | 5 ++-
.../taskInstance/taskActions/MarkFailed.jsx | 6 ++-
.../taskInstance/taskActions/MarkSuccess.jsx | 10 +++--
.../content/taskInstance/taskActions/Run.jsx | 26 ++++---------
11 files changed, 73 insertions(+), 70 deletions(-)
diff --git a/airflow/www/static/js/tree/Table.jsx b/airflow/www/static/js/tree/Table.jsx
index 152f647ea3..e500b08966 100644
--- a/airflow/www/static/js/tree/Table.jsx
+++ b/airflow/www/static/js/tree/Table.jsx
@@ -46,7 +46,7 @@ import {
} from 'react-icons/ti';
const IndeterminateCheckbox = forwardRef(
- ({ indeterminate, ...rest }, ref) => {
+ ({ indeterminate, checked, ...rest }, ref) => {
const defaultRef = useRef();
const resolvedRef = ref || defaultRef;
@@ -55,7 +55,7 @@ const IndeterminateCheckbox = forwardRef(
}, [resolvedRef, indeterminate]);
return (
- <Checkbox ref={resolvedRef} {...rest} />
+ <Checkbox ref={resolvedRef} isChecked={checked} {...rest} />
);
},
);
diff --git a/airflow/www/static/js/tree/api/useClearTask.js b/airflow/www/static/js/tree/api/useClearTask.js
index bcf99bb250..eea4b2b656 100644
--- a/airflow/www/static/js/tree/api/useClearTask.js
+++ b/airflow/www/static/js/tree/api/useClearTask.js
@@ -36,7 +36,7 @@ export default function useClearTask({
return useMutation(
['clearTask', dagId, runId, taskId],
({
- past, future, upstream, downstream, recursive, failed, confirmed,
+ past, future, upstream, downstream, recursive, failed, confirmed, mapIndexes = [],
}) => {
const params = new URLSearchParams({
csrf_token: csrfToken,
@@ -51,6 +51,7 @@ export default function useClearTask({
downstream,
recursive,
only_failed: failed,
+ map_indexes: mapIndexes,
}).toString();
return axios.post(clearUrl, params, {
@@ -71,6 +72,7 @@ export default function useClearTask({
}
if (!status || status !== 'error') {
queryClient.invalidateQueries('treeData');
+ queryClient.invalidateQueries('mappedInstances', dagId, runId, taskId);
startRefresh();
}
},
diff --git a/airflow/www/static/js/tree/api/useConfirmMarkTask.js b/airflow/www/static/js/tree/api/useConfirmMarkTask.js
index 1450a15d3d..85b5f7df42 100644
--- a/airflow/www/static/js/tree/api/useConfirmMarkTask.js
+++ b/airflow/www/static/js/tree/api/useConfirmMarkTask.js
@@ -29,9 +29,9 @@ export default function useConfirmMarkTask({
return useMutation(
['confirmStateChange', dagId, runId, taskId, state],
({
- past, future, upstream, downstream,
- }) => axios.get(confirmUrl, {
- params: {
+ past, future, upstream, downstream, mapIndexes = [],
+ }) => {
+ const params = new URLSearchParams({
dag_id: dagId,
dag_run_id: runId,
task_id: taskId,
@@ -40,7 +40,9 @@ export default function useConfirmMarkTask({
upstream,
downstream,
state,
- },
- }),
+ map_indexes: mapIndexes,
+ });
+ return axios.get(confirmUrl, { params });
+ },
);
}
diff --git a/airflow/www/static/js/tree/api/useMarkFailedTask.js b/airflow/www/static/js/tree/api/useMarkFailedTask.js
index f2fd28bdb2..333fed21c2 100644
--- a/airflow/www/static/js/tree/api/useMarkFailedTask.js
+++ b/airflow/www/static/js/tree/api/useMarkFailedTask.js
@@ -33,7 +33,7 @@ export default function useMarkFailedTask({
return useMutation(
['markFailed', dagId, runId, taskId],
({
- past, future, upstream, downstream,
+ past, future, upstream, downstream, mapIndexes = [],
}) => {
const params = new URLSearchParams({
csrf_token: csrfToken,
@@ -45,6 +45,7 @@ export default function useMarkFailedTask({
future,
upstream,
downstream,
+ map_indexes: mapIndexes,
}).toString();
return axios.post(failedUrl, params, {
@@ -56,6 +57,7 @@ export default function useMarkFailedTask({
{
onSuccess: () => {
queryClient.invalidateQueries('treeData');
+ queryClient.invalidateQueries('mappedInstances', dagId, runId, taskId);
startRefresh();
},
},
diff --git a/airflow/www/static/js/tree/api/useMarkSuccessTask.js b/airflow/www/static/js/tree/api/useMarkSuccessTask.js
index 92ba539de6..cde919a274 100644
--- a/airflow/www/static/js/tree/api/useMarkSuccessTask.js
+++ b/airflow/www/static/js/tree/api/useMarkSuccessTask.js
@@ -33,7 +33,7 @@ export default function useMarkSuccessTask({
return useMutation(
['markSuccess', dagId, runId, taskId],
({
- past, future, upstream, downstream,
+ past, future, upstream, downstream, mapIndexes = [],
}) => {
const params = new URLSearchParams({
csrf_token: csrfToken,
@@ -45,6 +45,7 @@ export default function useMarkSuccessTask({
future,
upstream,
downstream,
+ map_indexes: mapIndexes,
}).toString();
return axios.post(successUrl, params, {
@@ -56,6 +57,7 @@ export default function useMarkSuccessTask({
{
onSuccess: () => {
queryClient.invalidateQueries('treeData');
+ queryClient.invalidateQueries('mappedInstances', dagId, runId, taskId);
startRefresh();
},
},
diff --git a/airflow/www/static/js/tree/api/useRunTask.js b/airflow/www/static/js/tree/api/useRunTask.js
index 44a9e14bf4..9e45c42f59 100644
--- a/airflow/www/static/js/tree/api/useRunTask.js
+++ b/airflow/www/static/js/tree/api/useRunTask.js
@@ -32,32 +32,34 @@ export default function useRunTask(dagId, runId, taskId) {
const { startRefresh } = useAutoRefresh();
return useMutation(
['runTask', dagId, runId, taskId],
- ({
+ async ({
ignoreAllDeps,
ignoreTaskState,
ignoreTaskDeps,
- mapIndex = -1,
- }) => {
- const params = new URLSearchParams({
- csrf_token: csrfToken,
- dag_id: dagId,
- dag_run_id: runId,
- task_id: taskId,
- ignore_all_deps: ignoreAllDeps,
- ignore_task_deps: ignoreTaskDeps,
- ignore_ti_state: ignoreTaskState,
- map_index: mapIndex,
- }).toString();
+ mapIndexes,
+ }) => Promise.all(
+ (mapIndexes.length ? mapIndexes : [-1]).map((mi) => {
+ const params = new URLSearchParams({
+ csrf_token: csrfToken,
+ dag_id: dagId,
+ dag_run_id: runId,
+ task_id: taskId,
+ ignore_all_deps: ignoreAllDeps,
+ ignore_task_deps: ignoreTaskDeps,
+ ignore_ti_state: ignoreTaskState,
+ map_index: mi,
+ }).toString();
- return axios.post(runUrl, params, {
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded',
- },
- });
- },
+ return axios.post(runUrl, params, {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ });
+ }),
+ ),
{
onSuccess: (data) => {
- const { message, status } = data;
+ const { message, status } = data.length ? data[0] : data;
if (message && status === 'error') {
toast({
description: message,
@@ -67,6 +69,7 @@ export default function useRunTask(dagId, runId, taskId) {
}
if (!status || status !== 'error') {
queryClient.invalidateQueries('treeData');
+ queryClient.invalidateQueries('mappedInstances', dagId, runId, taskId);
startRefresh();
}
},
diff --git a/airflow/www/static/js/tree/details/content/taskInstance/index.jsx b/airflow/www/static/js/tree/details/content/taskInstance/index.jsx
index 62ffee156a..0e4f441e24 100644
--- a/airflow/www/static/js/tree/details/content/taskInstance/index.jsx
+++ b/airflow/www/static/js/tree/details/content/taskInstance/index.jsx
@@ -24,7 +24,6 @@ import {
Divider,
StackDivider,
Text,
- Flex,
} from '@chakra-ui/react';
import RunAction from './taskActions/Run';
@@ -89,39 +88,32 @@ const TaskInstance = ({ taskId, runId }) => {
{!isGroup && (
<Box my={3}>
<Text as="strong">{taskActionsTitle}</Text>
- <Flex maxHeight="20px" minHeight="20px">
- {selectedRows.length ? (
- <Text color="red.500">
- Clear, Mark Failed, and Mark Success do not yet work with individual mapped tasks.
- </Text>
- ) : <Divider my={2} />}
- </Flex>
- {/* visibility={selectedRows.length ? 'visible' : 'hidden'} */}
+ <Divider my={2} />
<VStack justifyContent="center" divider={<StackDivider my={3} />}>
<RunAction
runId={runId}
taskId={taskId}
dagId={dagId}
- selectedRows={selectedRows}
+ mapIndexes={selectedRows}
/>
<ClearAction
runId={runId}
taskId={taskId}
dagId={dagId}
executionDate={executionDate}
- selectedRows={selectedRows}
+ mapIndexes={selectedRows}
/>
<MarkFailedAction
runId={runId}
taskId={taskId}
dagId={dagId}
- selectedRows={selectedRows}
+ mapIndexes={selectedRows}
/>
<MarkSuccessAction
runId={runId}
taskId={taskId}
dagId={dagId}
- selectedRows={selectedRows}
+ mapIndexes={selectedRows}
/>
</VStack>
<Divider my={2} />
@@ -143,7 +135,12 @@ const TaskInstance = ({ taskId, runId }) => {
extraLinks={extraLinks}
/>
{isMapped && (
- <MappedInstances dagId={dagId} runId={runId} taskId={taskId} selectRows={setSelectedRows} />
+ <MappedInstances
+ dagId={dagId}
+ runId={runId}
+ taskId={taskId}
+ selectRows={setSelectedRows}
+ />
)}
</Box>
);
diff --git a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Clear.jsx b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Clear.jsx
index cada7b59ed..d825976ed2 100644
--- a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Clear.jsx
+++ b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Clear.jsx
@@ -34,7 +34,7 @@ const Run = ({
runId,
taskId,
executionDate,
- selectedRows,
+ mapIndexes,
}) => {
const [affectedTasks, setAffectedTasks] = useState([]);
@@ -74,6 +74,7 @@ const Run = ({
recursive,
failed,
confirmed: false,
+ mapIndexes,
});
setAffectedTasks(data);
onOpen();
@@ -92,6 +93,7 @@ const Run = ({
recursive,
failed,
confirmed: true,
+ mapIndexes,
});
setAffectedTasks([]);
onClose();
@@ -114,7 +116,6 @@ const Run = ({
colorScheme="blue"
onClick={onClick}
isLoading={isLoading}
- isDisabled={!!selectedRows.length}
title="Clearing deletes the previous state of the task instance, allowing it to get re-triggered by the scheduler or a backfill command"
>
Clear
diff --git a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkFailed.jsx b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkFailed.jsx
index 6bc10c066e..12f8bcfeef 100644
--- a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkFailed.jsx
+++ b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkFailed.jsx
@@ -33,7 +33,7 @@ const MarkFailed = ({
dagId,
runId,
taskId,
- selectedRows,
+ mapIndexes,
}) => {
const [affectedTasks, setAffectedTasks] = useState([]);
@@ -69,6 +69,7 @@ const MarkFailed = ({
future,
upstream,
downstream,
+ mapIndexes,
});
setAffectedTasks(data);
onOpen();
@@ -84,6 +85,7 @@ const MarkFailed = ({
future,
upstream,
downstream,
+ mapIndexes,
});
setAffectedTasks([]);
onClose();
@@ -100,7 +102,7 @@ const MarkFailed = ({
<ActionButton bg={upstream && 'gray.100'} onClick={onToggleUpstream} name="Upstream" />
<ActionButton bg={downstream && 'gray.100'} onClick={onToggleDownstream} name="Downstream" />
</ButtonGroup>
- <Button colorScheme="red" onClick={onClick} isLoading={isMarkLoading || isConfirmLoading} isDisabled={!!selectedRows.length}>
+ <Button colorScheme="red" onClick={onClick} isLoading={isMarkLoading || isConfirmLoading}>
Mark Failed
</Button>
<ConfirmDialog
diff --git a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkSuccess.jsx b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkSuccess.jsx
index b4d2b8c047..bdf59e6a4d 100644
--- a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkSuccess.jsx
+++ b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkSuccess.jsx
@@ -29,8 +29,8 @@ import ConfirmDialog from '../../ConfirmDialog';
import ActionButton from './ActionButton';
import { useMarkSuccessTask, useConfirmMarkTask } from '../../../../api';
-const Run = ({
- dagId, runId, taskId, selectedRows,
+const MarkSuccess = ({
+ dagId, runId, taskId, mapIndexes,
}) => {
const [affectedTasks, setAffectedTasks] = useState([]);
@@ -64,6 +64,7 @@ const Run = ({
future,
upstream,
downstream,
+ mapIndexes,
});
setAffectedTasks(data);
onOpen();
@@ -79,6 +80,7 @@ const Run = ({
future,
upstream,
downstream,
+ mapIndexes,
});
setAffectedTasks([]);
onClose();
@@ -95,7 +97,7 @@ const Run = ({
<ActionButton bg={upstream && 'gray.100'} onClick={onToggleUpstream} name="Upstream" />
<ActionButton bg={downstream && 'gray.100'} onClick={onToggleDownstream} name="Downstream" />
</ButtonGroup>
- <Button colorScheme="green" onClick={onClick} isLoading={isMarkLoading || isConfirmLoading} isDisabled={!!selectedRows.length}>
+ <Button colorScheme="green" onClick={onClick} isLoading={isMarkLoading || isConfirmLoading}>
Mark Success
</Button>
<ConfirmDialog
@@ -109,4 +111,4 @@ const Run = ({
);
};
-export default Run;
+export default MarkSuccess;
diff --git a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Run.jsx b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Run.jsx
index abb17a8479..464ca7026d 100644
--- a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Run.jsx
+++ b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Run.jsx
@@ -35,7 +35,7 @@ const Run = ({
dagId,
runId,
taskId,
- selectedRows,
+ mapIndexes,
}) => {
const containerRef = useContainerRef();
const [ignoreAllDeps, setIgnoreAllDeps] = useState(false);
@@ -50,22 +50,12 @@ const Run = ({
const { mutate: onRun, isLoading } = useRunTask(dagId, runId, taskId);
const onClick = () => {
- if (selectedRows.length) {
- selectedRows.forEach((mapIndex) => {
- onRun({
- ignoreAllDeps,
- ignoreTaskState,
- ignoreTaskDeps,
- mapIndex,
- });
- });
- } else {
- onRun({
- ignoreAllDeps,
- ignoreTaskState,
- ignoreTaskDeps,
- });
- }
+ onRun({
+ ignoreAllDeps,
+ ignoreTaskState,
+ ignoreTaskDeps,
+ mapIndexes,
+ });
};
return (
@@ -96,7 +86,7 @@ const Run = ({
<Tooltip
label="Only works with the Celery, CeleryKubernetes or Kubernetes executors"
shouldWrapChildren // Will show the tooltip even if the button is disabled
- disabled={canRun}
+ isDisabled={canRun}
portalProps={{ containerRef }}
>
<Button colorScheme="blue" onClick={onClick} isLoading={isLoading} disabled={!canRun}>