Add run-all dead tasks action button to DeadTasksTable

This commit is contained in:
Ken Hibino 2020-12-17 06:57:30 -08:00
parent 4d5de30a57
commit bf81787115
6 changed files with 104 additions and 13 deletions

View File

@ -19,6 +19,7 @@ import {
listScheduledTasks,
ListScheduledTasksResponse,
PaginationOptions,
runAllDeadTasks,
runDeadTask,
} from "../api";
import { Dispatch } from "redux";
@ -61,6 +62,9 @@ export const BATCH_DELETE_DEAD_TASKS_BEGIN = "BATCH_DELETE_DEAD_TASKS_BEGIN";
export const BATCH_DELETE_DEAD_TASKS_SUCCESS =
"BATCH_DELETE_DEAD_TASKS_SUCCESS";
export const BATCH_DELETE_DEAD_TASKS_ERROR = "BATCH_DELETE_DEAD_TASKS_ERROR";
export const RUN_ALL_DEAD_TASKS_BEGIN = "RUN_ALL_DEAD_TASKS_BEGIN";
export const RUN_ALL_DEAD_TASKS_SUCCESS = "RUN_ALL_DEAD_TASKS_SUCCESS";
export const RUN_ALL_DEAD_TASKS_ERROR = "RUN_ALL_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";
@ -283,6 +287,22 @@ interface BatchRunDeadTasksErrorAction {
error: string;
}
interface RunAllDeadTasksBeginAction {
type: typeof RUN_ALL_DEAD_TASKS_BEGIN;
queue: string;
}
interface RunAllDeadTasksSuccessAction {
type: typeof RUN_ALL_DEAD_TASKS_SUCCESS;
queue: string;
}
interface RunAllDeadTasksErrorAction {
type: typeof RUN_ALL_DEAD_TASKS_ERROR;
queue: string;
error: string;
}
interface DeleteAllDeadTasksBeginAction {
type: typeof DELETE_ALL_DEAD_TASKS_BEGIN;
queue: string;
@ -337,6 +357,9 @@ export type TasksActionTypes =
| BatchRunDeadTasksBeginAction
| BatchRunDeadTasksSuccessAction
| BatchRunDeadTasksErrorAction
| RunAllDeadTasksBeginAction
| RunAllDeadTasksSuccessAction
| RunAllDeadTasksErrorAction
| DeleteAllDeadTasksBeginAction
| DeleteAllDeadTasksSuccessAction
| DeleteAllDeadTasksErrorAction;
@ -605,3 +628,20 @@ export function deleteAllDeadTasksAsync(queue: string) {
}
};
}
export function runAllDeadTasksAsync(queue: string) {
return async (dispatch: Dispatch<TasksActionTypes>) => {
dispatch({ type: RUN_ALL_DEAD_TASKS_BEGIN, queue });
try {
await runAllDeadTasks(queue);
dispatch({ type: RUN_ALL_DEAD_TASKS_SUCCESS, queue });
} catch (error) {
console.error("runAllDeadTasksAsync: ", error);
dispatch({
type: RUN_ALL_DEAD_TASKS_ERROR,
error: `Could not run all dead tasks`,
queue,
});
}
};
}

View File

@ -328,6 +328,13 @@ export async function batchRunDeadTasks(
return resp.data;
}
export async function runAllDeadTasks(qname: string): Promise<void> {
await axios({
method: "post",
url: `${BASE_URL}/queues/${qname}/dead_tasks:run_all`,
});
}
export async function listSchedulerEntries(): Promise<ListSchedulerEntriesResponse> {
const resp = await axios({
method: "get",

View File

@ -34,6 +34,7 @@ import {
deleteAllDeadTasksAsync,
listDeadTasksAsync,
runDeadTaskAsync,
runAllDeadTasksAsync,
} from "../actions/tasksActions";
import TablePaginationActions, {
defaultPageSize,
@ -68,7 +69,7 @@ function mapStateToProps(state: AppState) {
loading: state.tasks.deadTasks.loading,
tasks: state.tasks.deadTasks.data,
batchActionPending: state.tasks.deadTasks.batchActionPending,
deleteAllRequestPending: state.tasks.deadTasks.deleteAllRequestPending,
allActionPending: state.tasks.deadTasks.allActionPending,
pollInterval: state.settings.pollInterval,
};
}
@ -76,6 +77,7 @@ function mapStateToProps(state: AppState) {
const mapDispatchToProps = {
listDeadTasksAsync,
runDeadTaskAsync,
runAllDeadTasksAsync,
deleteDeadTaskAsync,
deleteAllDeadTasksAsync,
batchRunDeadTasksAsync,
@ -128,6 +130,11 @@ function DeadTasksTable(props: Props & ReduxProps) {
const handleMenuClose = () => setMenuAnchor(null);
const handleRunAllClick = () => {
props.runAllDeadTasksAsync(queue);
setMenuAnchor(null);
};
const handleDeleteAllClick = () => {
props.deleteAllDeadTasksAsync(queue);
setMenuAnchor(null);
@ -177,10 +184,15 @@ function DeadTasksTable(props: Props & ReduxProps) {
open={Boolean(menuAnchor)}
onClose={handleMenuClose}
>
<MenuItem onClick={handleMenuClose}>Run All</MenuItem>
<MenuItem
onClick={handleRunAllClick}
disabled={props.allActionPending}
>
Run All
</MenuItem>
<MenuItem
onClick={handleDeleteAllClick}
disabled={props.deleteAllRequestPending}
disabled={props.allActionPending}
>
Delete All
</MenuItem>
@ -258,7 +270,7 @@ function DeadTasksTable(props: Props & ReduxProps) {
onDeleteClick={() => {
props.deleteDeadTaskAsync(queue, task.key);
}}
deleteAllRequestPending={props.deleteAllRequestPending}
allActionPending={props.allActionPending}
/>
))}
</TableBody>
@ -292,7 +304,7 @@ interface RowProps {
onSelectChange: (checked: boolean) => void;
onRunClick: () => void;
onDeleteClick: () => void;
deleteAllRequestPending: boolean;
allActionPending: boolean;
}
function Row(props: RowProps) {
@ -331,13 +343,13 @@ function Row(props: RowProps) {
<TableCell>
<Button
onClick={props.onRunClick}
disabled={task.requestPending || props.deleteAllRequestPending}
disabled={task.requestPending || props.allActionPending}
>
Run
</Button>
<Button
onClick={props.onDeleteClick}
disabled={task.requestPending || props.deleteAllRequestPending}
disabled={task.requestPending || props.allActionPending}
>
Delete
</Button>

View File

@ -25,6 +25,7 @@ import {
LIST_PENDING_TASKS_SUCCESS,
LIST_RETRY_TASKS_SUCCESS,
LIST_SCHEDULED_TASKS_SUCCESS,
RUN_ALL_DEAD_TASKS_SUCCESS,
RUN_DEAD_TASK_SUCCESS,
TasksActionTypes,
} from "../actions/tasksActions";
@ -256,6 +257,24 @@ function queuesReducer(
return { ...state, data: newData };
}
case RUN_ALL_DEAD_TASKS_SUCCESS: {
const newData = state.data.map((queueInfo) => {
if (queueInfo.name !== action.queue) {
return queueInfo;
}
return {
...queueInfo,
currentStats: {
...queueInfo.currentStats,
pending:
queueInfo.currentStats.pending + queueInfo.currentStats.dead,
dead: 0,
},
};
});
return { ...state, data: newData };
}
case DELETE_ALL_DEAD_TASKS_SUCCESS: {
const newData = state.data.map((queueInfo) => {
if (queueInfo.name !== action.queue) {

View File

@ -9,6 +9,7 @@ import {
DELETE_DEAD_TASK_SUCCESS,
DELETE_RETRY_TASK_SUCCESS,
DELETE_SCHEDULED_TASK_SUCCESS,
RUN_ALL_DEAD_TASKS_SUCCESS,
RUN_DEAD_TASK_SUCCESS,
TasksActionTypes,
} from "../actions/tasksActions";
@ -80,10 +81,16 @@ function snackbarReducer(
};
}
case RUN_ALL_DEAD_TASKS_SUCCESS:
return {
isOpen: true,
message: "All dead tasks are now pending",
};
case DELETE_ALL_DEAD_TASKS_SUCCESS:
return {
isOpen: true,
message: `All dead tasks delete`,
message: "All dead tasks delete",
};
default:

View File

@ -39,6 +39,9 @@ import {
DELETE_ALL_DEAD_TASKS_BEGIN,
DELETE_ALL_DEAD_TASKS_SUCCESS,
DELETE_ALL_DEAD_TASKS_ERROR,
RUN_ALL_DEAD_TASKS_BEGIN,
RUN_ALL_DEAD_TASKS_ERROR,
RUN_ALL_DEAD_TASKS_SUCCESS,
} from "../actions/tasksActions";
import {
ActiveTask,
@ -100,7 +103,7 @@ interface TasksState {
deadTasks: {
loading: boolean;
batchActionPending: boolean;
deleteAllRequestPending: boolean;
allActionPending: boolean;
error: string;
data: DeadTaskExtended[];
};
@ -130,7 +133,7 @@ const initialState: TasksState = {
deadTasks: {
loading: false,
batchActionPending: false,
deleteAllRequestPending: false,
allActionPending: false,
error: "",
data: [],
},
@ -472,31 +475,34 @@ function tasksReducer(
},
};
case RUN_ALL_DEAD_TASKS_BEGIN:
case DELETE_ALL_DEAD_TASKS_BEGIN:
return {
...state,
deadTasks: {
...state.deadTasks,
deleteAllRequestPending: true,
allActionPending: true,
},
};
case RUN_ALL_DEAD_TASKS_SUCCESS:
case DELETE_ALL_DEAD_TASKS_SUCCESS:
return {
...state,
deadTasks: {
...state.deadTasks,
deleteAllRequestPending: false,
allActionPending: false,
data: [],
},
};
case RUN_ALL_DEAD_TASKS_ERROR:
case DELETE_ALL_DEAD_TASKS_ERROR:
return {
...state,
deadTasks: {
...state.deadTasks,
deleteAllRequestPending: false,
allActionPending: false,
},
};