Add delete-all action button to DeadTasksTable

This commit is contained in:
Ken Hibino 2020-12-16 06:55:51 -08:00
parent fa231aa713
commit 226cfc3b82
6 changed files with 129 additions and 4 deletions

View File

@ -4,6 +4,7 @@ import {
batchRunDeadTasks, batchRunDeadTasks,
BatchRunTasksResponse, BatchRunTasksResponse,
cancelActiveTask, cancelActiveTask,
deleteAllDeadTasks,
deleteDeadTask, deleteDeadTask,
deleteRetryTask, deleteRetryTask,
deleteScheduledTask, deleteScheduledTask,
@ -60,6 +61,9 @@ export const BATCH_DELETE_DEAD_TASKS_BEGIN = "BATCH_DELETE_DEAD_TASKS_BEGIN";
export const BATCH_DELETE_DEAD_TASKS_SUCCESS = export const BATCH_DELETE_DEAD_TASKS_SUCCESS =
"BATCH_DELETE_DEAD_TASKS_SUCCESS"; "BATCH_DELETE_DEAD_TASKS_SUCCESS";
export const BATCH_DELETE_DEAD_TASKS_ERROR = "BATCH_DELETE_DEAD_TASKS_ERROR"; export const BATCH_DELETE_DEAD_TASKS_ERROR = "BATCH_DELETE_DEAD_TASKS_ERROR";
export const DELETE_ALL_DEAD_TASKS_BEGIN = "DELETE_ALL_DEAD_TASKS_BEGIN";
export const DELETE_ALL_DEAD_TASKS_SUCCESS = "DELETE_ALL_DEAD_TASKS_SUCCESS";
export const DELETE_ALL_DEAD_TASKS_ERROR = "DELETE_ALL_DEAD_TASKS_ERROR";
interface ListActiveTasksBeginAction { interface ListActiveTasksBeginAction {
type: typeof LIST_ACTIVE_TASKS_BEGIN; type: typeof LIST_ACTIVE_TASKS_BEGIN;
@ -279,6 +283,22 @@ interface BatchRunDeadTasksErrorAction {
error: string; error: string;
} }
interface DeleteAllDeadTasksBeginAction {
type: typeof DELETE_ALL_DEAD_TASKS_BEGIN;
queue: string;
}
interface DeleteAllDeadTasksSuccessAction {
type: typeof DELETE_ALL_DEAD_TASKS_SUCCESS;
queue: string;
}
interface DeleteAllDeadTasksErrorAction {
type: typeof DELETE_ALL_DEAD_TASKS_ERROR;
queue: string;
error: string;
}
// Union of all tasks related action types. // Union of all tasks related action types.
export type TasksActionTypes = export type TasksActionTypes =
| ListActiveTasksBeginAction | ListActiveTasksBeginAction
@ -316,7 +336,10 @@ export type TasksActionTypes =
| BatchDeleteDeadTasksErrorAction | BatchDeleteDeadTasksErrorAction
| BatchRunDeadTasksBeginAction | BatchRunDeadTasksBeginAction
| BatchRunDeadTasksSuccessAction | BatchRunDeadTasksSuccessAction
| BatchRunDeadTasksErrorAction; | BatchRunDeadTasksErrorAction
| DeleteAllDeadTasksBeginAction
| DeleteAllDeadTasksSuccessAction
| DeleteAllDeadTasksErrorAction;
export function listActiveTasksAsync( export function listActiveTasksAsync(
qname: string, qname: string,
@ -565,3 +588,20 @@ export function batchRunDeadTasksAsync(queue: string, taskKeys: string[]) {
} }
}; };
} }
export function deleteAllDeadTasksAsync(queue: string) {
return async (dispatch: Dispatch<TasksActionTypes>) => {
dispatch({ type: DELETE_ALL_DEAD_TASKS_BEGIN, queue });
try {
await deleteAllDeadTasks(queue);
dispatch({ type: DELETE_ALL_DEAD_TASKS_SUCCESS, queue });
} catch (error) {
console.error("deleteAllDeadTasksAsync: ", error);
dispatch({
type: DELETE_ALL_DEAD_TASKS_ERROR,
error: `Could not delete all dead tasks`,
queue,
});
}
};
}

View File

@ -307,6 +307,13 @@ export async function batchDeleteDeadTasks(
return resp.data; return resp.data;
} }
export async function deleteAllDeadTasks(qname: string): Promise<void> {
await axios({
method: "delete",
url: `${BASE_URL}/queues/${qname}/dead_tasks:delete_all`,
});
}
export async function batchRunDeadTasks( export async function batchRunDeadTasks(
qname: string, qname: string,
taskKeys: string[] taskKeys: string[]

View File

@ -31,6 +31,7 @@ import {
batchDeleteDeadTasksAsync, batchDeleteDeadTasksAsync,
batchRunDeadTasksAsync, batchRunDeadTasksAsync,
deleteDeadTaskAsync, deleteDeadTaskAsync,
deleteAllDeadTasksAsync,
listDeadTasksAsync, listDeadTasksAsync,
runDeadTaskAsync, runDeadTaskAsync,
} from "../actions/tasksActions"; } from "../actions/tasksActions";
@ -67,6 +68,7 @@ function mapStateToProps(state: AppState) {
loading: state.tasks.deadTasks.loading, loading: state.tasks.deadTasks.loading,
tasks: state.tasks.deadTasks.data, tasks: state.tasks.deadTasks.data,
batchActionPending: state.tasks.deadTasks.batchActionPending, batchActionPending: state.tasks.deadTasks.batchActionPending,
deleteAllRequestPending: state.tasks.deadTasks.deleteAllRequestPending,
pollInterval: state.settings.pollInterval, pollInterval: state.settings.pollInterval,
}; };
} }
@ -75,6 +77,7 @@ const mapDispatchToProps = {
listDeadTasksAsync, listDeadTasksAsync,
runDeadTaskAsync, runDeadTaskAsync,
deleteDeadTaskAsync, deleteDeadTaskAsync,
deleteAllDeadTasksAsync,
batchRunDeadTasksAsync, batchRunDeadTasksAsync,
batchDeleteDeadTasksAsync, batchDeleteDeadTasksAsync,
}; };
@ -125,6 +128,11 @@ function DeadTasksTable(props: Props & ReduxProps) {
const handleMenuClose = () => setMenuAnchor(null); const handleMenuClose = () => setMenuAnchor(null);
const handleDeleteAllClick = () => {
props.deleteAllDeadTasksAsync(queue);
setMenuAnchor(null);
};
const fetchData = useCallback(() => { const fetchData = useCallback(() => {
const pageOpts = { page: page + 1, size: pageSize }; const pageOpts = { page: page + 1, size: pageSize };
listDeadTasksAsync(queue, pageOpts); listDeadTasksAsync(queue, pageOpts);
@ -170,7 +178,12 @@ function DeadTasksTable(props: Props & ReduxProps) {
onClose={handleMenuClose} onClose={handleMenuClose}
> >
<MenuItem onClick={handleMenuClose}>Run All</MenuItem> <MenuItem onClick={handleMenuClose}>Run All</MenuItem>
<MenuItem onClick={handleMenuClose}>Delete All</MenuItem> <MenuItem
onClick={handleDeleteAllClick}
disabled={props.deleteAllRequestPending}
>
Delete All
</MenuItem>
</Menu> </Menu>
{numSelected > 0 && ( {numSelected > 0 && (
<ButtonGroup <ButtonGroup
@ -245,6 +258,7 @@ function DeadTasksTable(props: Props & ReduxProps) {
onDeleteClick={() => { onDeleteClick={() => {
props.deleteDeadTaskAsync(queue, task.key); props.deleteDeadTaskAsync(queue, task.key);
}} }}
deleteAllRequestPending={props.deleteAllRequestPending}
/> />
))} ))}
</TableBody> </TableBody>
@ -278,6 +292,7 @@ interface RowProps {
onSelectChange: (checked: boolean) => void; onSelectChange: (checked: boolean) => void;
onRunClick: () => void; onRunClick: () => void;
onDeleteClick: () => void; onDeleteClick: () => void;
deleteAllRequestPending: boolean;
} }
function Row(props: RowProps) { function Row(props: RowProps) {
@ -314,10 +329,16 @@ function Row(props: RowProps) {
<TableCell>{timeAgo(task.last_failed_at)}</TableCell> <TableCell>{timeAgo(task.last_failed_at)}</TableCell>
<TableCell>{task.error_message}</TableCell> <TableCell>{task.error_message}</TableCell>
<TableCell> <TableCell>
<Button onClick={props.onRunClick} disabled={task.requestPending}> <Button
onClick={props.onRunClick}
disabled={task.requestPending || props.deleteAllRequestPending}
>
Run Run
</Button> </Button>
<Button onClick={props.onDeleteClick} disabled={task.requestPending}> <Button
onClick={props.onDeleteClick}
disabled={task.requestPending || props.deleteAllRequestPending}
>
Delete Delete
</Button> </Button>
</TableCell> </TableCell>

View File

@ -16,6 +16,7 @@ import {
import { import {
BATCH_DELETE_DEAD_TASKS_SUCCESS, BATCH_DELETE_DEAD_TASKS_SUCCESS,
BATCH_RUN_DEAD_TASKS_SUCCESS, BATCH_RUN_DEAD_TASKS_SUCCESS,
DELETE_ALL_DEAD_TASKS_SUCCESS,
DELETE_DEAD_TASK_SUCCESS, DELETE_DEAD_TASK_SUCCESS,
DELETE_RETRY_TASK_SUCCESS, DELETE_RETRY_TASK_SUCCESS,
DELETE_SCHEDULED_TASK_SUCCESS, DELETE_SCHEDULED_TASK_SUCCESS,
@ -255,6 +256,22 @@ function queuesReducer(
return { ...state, data: newData }; return { ...state, data: newData };
} }
case DELETE_ALL_DEAD_TASKS_SUCCESS: {
const newData = state.data.map((queueInfo) => {
if (queueInfo.name !== action.queue) {
return queueInfo;
}
return {
...queueInfo,
currentStats: {
...queueInfo.currentStats,
dead: 0,
},
};
});
return { ...state, data: newData };
}
default: default:
return state; return state;
} }

View File

@ -5,6 +5,7 @@ import {
import { import {
BATCH_DELETE_DEAD_TASKS_SUCCESS, BATCH_DELETE_DEAD_TASKS_SUCCESS,
BATCH_RUN_DEAD_TASKS_SUCCESS, BATCH_RUN_DEAD_TASKS_SUCCESS,
DELETE_ALL_DEAD_TASKS_SUCCESS,
DELETE_DEAD_TASK_SUCCESS, DELETE_DEAD_TASK_SUCCESS,
DELETE_RETRY_TASK_SUCCESS, DELETE_RETRY_TASK_SUCCESS,
DELETE_SCHEDULED_TASK_SUCCESS, DELETE_SCHEDULED_TASK_SUCCESS,
@ -79,6 +80,12 @@ function snackbarReducer(
}; };
} }
case DELETE_ALL_DEAD_TASKS_SUCCESS:
return {
isOpen: true,
message: `All dead tasks delete`,
};
default: default:
return state; return state;
} }

View File

@ -36,6 +36,9 @@ import {
BATCH_RUN_DEAD_TASKS_BEGIN, BATCH_RUN_DEAD_TASKS_BEGIN,
BATCH_RUN_DEAD_TASKS_ERROR, BATCH_RUN_DEAD_TASKS_ERROR,
BATCH_RUN_DEAD_TASKS_SUCCESS, BATCH_RUN_DEAD_TASKS_SUCCESS,
DELETE_ALL_DEAD_TASKS_BEGIN,
DELETE_ALL_DEAD_TASKS_SUCCESS,
DELETE_ALL_DEAD_TASKS_ERROR,
} from "../actions/tasksActions"; } from "../actions/tasksActions";
import { import {
ActiveTask, ActiveTask,
@ -97,6 +100,7 @@ interface TasksState {
deadTasks: { deadTasks: {
loading: boolean; loading: boolean;
batchActionPending: boolean; batchActionPending: boolean;
deleteAllRequestPending: boolean;
error: string; error: string;
data: DeadTaskExtended[]; data: DeadTaskExtended[];
}; };
@ -126,6 +130,7 @@ const initialState: TasksState = {
deadTasks: { deadTasks: {
loading: false, loading: false,
batchActionPending: false, batchActionPending: false,
deleteAllRequestPending: false,
error: "", error: "",
data: [], data: [],
}, },
@ -467,6 +472,34 @@ function tasksReducer(
}, },
}; };
case DELETE_ALL_DEAD_TASKS_BEGIN:
return {
...state,
deadTasks: {
...state.deadTasks,
deleteAllRequestPending: true,
},
};
case DELETE_ALL_DEAD_TASKS_SUCCESS:
return {
...state,
deadTasks: {
...state.deadTasks,
deleteAllRequestPending: false,
data: [],
},
};
case DELETE_ALL_DEAD_TASKS_ERROR:
return {
...state,
deadTasks: {
...state.deadTasks,
deleteAllRequestPending: false,
},
};
case BATCH_RUN_DEAD_TASKS_BEGIN: case BATCH_RUN_DEAD_TASKS_BEGIN:
case BATCH_DELETE_DEAD_TASKS_BEGIN: case BATCH_DELETE_DEAD_TASKS_BEGIN:
return { return {