Add batch run button to DeadTasksTable

This commit is contained in:
Ken Hibino 2020-12-15 06:46:23 -08:00
parent 706e80580d
commit 9bfd373f85
6 changed files with 132 additions and 5 deletions

View File

@ -1,6 +1,8 @@
import { import {
batchDeleteDeadTasks, batchDeleteDeadTasks,
BatchDeleteTasksResponse, BatchDeleteTasksResponse,
batchRunDeadTasks,
BatchRunTasksResponse,
cancelActiveTask, cancelActiveTask,
deleteDeadTask, deleteDeadTask,
deleteRetryTask, deleteRetryTask,
@ -51,6 +53,9 @@ export const DELETE_RETRY_TASK_ERROR = "DELETE_RETRY_TASK_ERROR";
export const DELETE_DEAD_TASK_BEGIN = "DELETE_DEAD_TASK_BEGIN"; export const DELETE_DEAD_TASK_BEGIN = "DELETE_DEAD_TASK_BEGIN";
export const DELETE_DEAD_TASK_SUCCESS = "DELETE_DEAD_TASK_SUCCESS"; export const DELETE_DEAD_TASK_SUCCESS = "DELETE_DEAD_TASK_SUCCESS";
export const DELETE_DEAD_TASK_ERROR = "DELETE_DEAD_TASK_ERROR"; export const DELETE_DEAD_TASK_ERROR = "DELETE_DEAD_TASK_ERROR";
export const BATCH_RUN_DEAD_TASKS_BEGIN = "BATCH_RUN_DEAD_TASKS_BEGIN";
export const BATCH_RUN_DEAD_TASKS_SUCCESS = "BATCH_RUN_DEAD_TASKS_SUCCESS";
export const BATCH_RUN_DEAD_TASKS_ERROR = "BATCH_RUN_DEAD_TASKS_ERROR";
export const BATCH_DELETE_DEAD_TASKS_BEGIN = "BATCH_DELETE_DEAD_TASKS_BEGIN"; 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";
@ -255,6 +260,25 @@ interface BatchDeleteDeadTasksErrorAction {
error: string; error: string;
} }
interface BatchRunDeadTasksBeginAction {
type: typeof BATCH_RUN_DEAD_TASKS_BEGIN;
queue: string;
taskKeys: string[];
}
interface BatchRunDeadTasksSuccessAction {
type: typeof BATCH_RUN_DEAD_TASKS_SUCCESS;
queue: string;
payload: BatchRunTasksResponse;
}
interface BatchRunDeadTasksErrorAction {
type: typeof BATCH_RUN_DEAD_TASKS_ERROR;
queue: string;
taskKeys: 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
@ -289,7 +313,10 @@ export type TasksActionTypes =
| DeleteDeadTaskErrorAction | DeleteDeadTaskErrorAction
| BatchDeleteDeadTasksBeginAction | BatchDeleteDeadTasksBeginAction
| BatchDeleteDeadTasksSuccessAction | BatchDeleteDeadTasksSuccessAction
| BatchDeleteDeadTasksErrorAction; | BatchDeleteDeadTasksErrorAction
| BatchRunDeadTasksBeginAction
| BatchRunDeadTasksSuccessAction
| BatchRunDeadTasksErrorAction;
export function listActiveTasksAsync( export function listActiveTasksAsync(
qname: string, qname: string,
@ -516,3 +543,25 @@ export function batchDeleteDeadTasksAsync(queue: string, taskKeys: string[]) {
} }
}; };
} }
export function batchRunDeadTasksAsync(queue: string, taskKeys: string[]) {
return async (dispatch: Dispatch<TasksActionTypes>) => {
dispatch({ type: BATCH_RUN_DEAD_TASKS_BEGIN, queue, taskKeys });
try {
const response = await batchRunDeadTasks(queue, taskKeys);
dispatch({
type: BATCH_RUN_DEAD_TASKS_SUCCESS,
queue: queue,
payload: response,
});
} catch (error) {
console.error("batchRunDeadTasksAsync: ", error);
dispatch({
type: BATCH_RUN_DEAD_TASKS_ERROR,
error: `Could not batch run tasks: ${taskKeys}`,
queue,
taskKeys,
});
}
};
}

View File

@ -46,6 +46,11 @@ export interface BatchDeleteTasksResponse {
failed_keys: string[]; failed_keys: string[];
} }
export interface BatchRunTasksResponse {
pending_keys: string[];
error_keys: string[];
}
export interface Queue { export interface Queue {
queue: string; queue: string;
paused: boolean; paused: boolean;
@ -299,7 +304,20 @@ export async function batchDeleteDeadTasks(
task_keys: taskKeys, task_keys: taskKeys,
}, },
}); });
console.log("debug: response:", resp); return resp.data;
}
export async function batchRunDeadTasks(
qname: string,
taskKeys: string[]
): Promise<BatchRunTasksResponse> {
const resp = await axios({
method: "post",
url: `${BASE_URL}/queues/${qname}/dead_tasks:batch_run`,
data: {
task_keys: taskKeys,
},
});
return resp.data; return resp.data;
} }

View File

@ -26,10 +26,11 @@ import SyntaxHighlighter from "react-syntax-highlighter";
import syntaxHighlightStyle from "react-syntax-highlighter/dist/esm/styles/hljs/github"; import syntaxHighlightStyle from "react-syntax-highlighter/dist/esm/styles/hljs/github";
import { AppState } from "../store"; import { AppState } from "../store";
import { import {
batchDeleteDeadTasksAsync,
batchRunDeadTasksAsync,
deleteDeadTaskAsync,
listDeadTasksAsync, listDeadTasksAsync,
runDeadTaskAsync, runDeadTaskAsync,
deleteDeadTaskAsync,
batchDeleteDeadTasksAsync,
} from "../actions/tasksActions"; } from "../actions/tasksActions";
import TablePaginationActions, { import TablePaginationActions, {
defaultPageSize, defaultPageSize,
@ -72,6 +73,7 @@ const mapDispatchToProps = {
listDeadTasksAsync, listDeadTasksAsync,
runDeadTaskAsync, runDeadTaskAsync,
deleteDeadTaskAsync, deleteDeadTaskAsync,
batchRunDeadTasksAsync,
batchDeleteDeadTasksAsync, batchDeleteDeadTasksAsync,
}; };
@ -153,7 +155,16 @@ function DeadTasksTable(props: Props & ReduxProps) {
color="primary" color="primary"
aria-label="text primary button group" aria-label="text primary button group"
> >
<Button>Run</Button> <Button
disabled={props.batchActionPending}
onClick={() =>
props
.batchRunDeadTasksAsync(queue, selectedKeys)
.then(() => setSelectedKeys([]))
}
>
Run
</Button>
<Button>Kill</Button> <Button>Kill</Button>
<Button <Button
disabled={props.batchActionPending} disabled={props.batchActionPending}

View File

@ -15,6 +15,7 @@ import {
} from "../actions/queuesActions"; } from "../actions/queuesActions";
import { import {
BATCH_DELETE_DEAD_TASKS_SUCCESS, BATCH_DELETE_DEAD_TASKS_SUCCESS,
BATCH_RUN_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,
@ -217,6 +218,26 @@ function queuesReducer(
return { ...state, data: newData }; return { ...state, data: newData };
} }
case BATCH_RUN_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 +
action.payload.pending_keys.length,
dead:
queueInfo.currentStats.dead - action.payload.pending_keys.length,
},
};
});
return { ...state, data: newData };
}
case BATCH_DELETE_DEAD_TASKS_SUCCESS: { case BATCH_DELETE_DEAD_TASKS_SUCCESS: {
const newData = state.data.map((queueInfo) => { const newData = state.data.map((queueInfo) => {
if (queueInfo.name !== action.queue) { if (queueInfo.name !== action.queue) {

View File

@ -4,6 +4,7 @@ import {
} from "../actions/snackbarActions"; } from "../actions/snackbarActions";
import { import {
BATCH_DELETE_DEAD_TASKS_SUCCESS, BATCH_DELETE_DEAD_TASKS_SUCCESS,
BATCH_RUN_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,
@ -62,6 +63,14 @@ function snackbarReducer(
message: `Dead task ${action.taskKey} deleted`, message: `Dead task ${action.taskKey} deleted`,
}; };
case BATCH_RUN_DEAD_TASKS_SUCCESS: {
const n = action.payload.pending_keys.length;
return {
isOpen: true,
message: `${n} Dead ${n === 1 ? "task is" : "tasks are"} now pending`,
};
}
case BATCH_DELETE_DEAD_TASKS_SUCCESS: { case BATCH_DELETE_DEAD_TASKS_SUCCESS: {
const n = action.payload.deleted_keys.length; const n = action.payload.deleted_keys.length;
return { return {

View File

@ -33,6 +33,9 @@ import {
RUN_DEAD_TASK_BEGIN, RUN_DEAD_TASK_BEGIN,
RUN_DEAD_TASK_SUCCESS, RUN_DEAD_TASK_SUCCESS,
RUN_DEAD_TASK_ERROR, RUN_DEAD_TASK_ERROR,
BATCH_RUN_DEAD_TASKS_BEGIN,
BATCH_RUN_DEAD_TASKS_ERROR,
BATCH_RUN_DEAD_TASKS_SUCCESS,
} from "../actions/tasksActions"; } from "../actions/tasksActions";
import { import {
ActiveTask, ActiveTask,
@ -464,6 +467,7 @@ function tasksReducer(
}, },
}; };
case BATCH_RUN_DEAD_TASKS_BEGIN:
case BATCH_DELETE_DEAD_TASKS_BEGIN: case BATCH_DELETE_DEAD_TASKS_BEGIN:
return { return {
...state, ...state,
@ -473,6 +477,20 @@ function tasksReducer(
}, },
}; };
case BATCH_RUN_DEAD_TASKS_SUCCESS: {
const newData = state.deadTasks.data.filter(
(task) => !action.payload.pending_keys.includes(task.key)
);
return {
...state,
deadTasks: {
...state.deadTasks,
batchActionPending: false,
data: newData,
},
};
}
case BATCH_DELETE_DEAD_TASKS_SUCCESS: { case BATCH_DELETE_DEAD_TASKS_SUCCESS: {
const newData = state.deadTasks.data.filter( const newData = state.deadTasks.data.filter(
(task) => !action.payload.deleted_keys.includes(task.key) (task) => !action.payload.deleted_keys.includes(task.key)
@ -487,6 +505,7 @@ function tasksReducer(
}; };
} }
case BATCH_RUN_DEAD_TASKS_ERROR:
case BATCH_DELETE_DEAD_TASKS_ERROR: case BATCH_DELETE_DEAD_TASKS_ERROR:
return { return {
...state, ...state,