diff --git a/ui/src/actions/tasksActions.ts b/ui/src/actions/tasksActions.ts index 6bd1f9e..c76148d 100644 --- a/ui/src/actions/tasksActions.ts +++ b/ui/src/actions/tasksActions.ts @@ -3,6 +3,9 @@ import { batchDeleteRetryTasks, batchDeleteScheduledTasks, BatchDeleteTasksResponse, + batchKillRetryTasks, + batchKillScheduledTasks, + BatchKillTasksResponse, batchRunDeadTasks, batchRunRetryTasks, batchRunScheduledTasks, @@ -14,6 +17,10 @@ import { deleteDeadTask, deleteRetryTask, deleteScheduledTask, + killAllRetryTasks, + killAllScheduledTasks, + killRetryTask, + killScheduledTask, listActiveTasks, ListActiveTasksResponse, listDeadTasks, @@ -65,12 +72,24 @@ export const RUN_DEAD_TASK_ERROR = "RUN_DEAD_TASK_ERROR"; export const DELETE_SCHEDULED_TASK_BEGIN = "DELETE_SCHEDULED_TASK_BEGIN"; export const DELETE_SCHEDULED_TASK_SUCCESS = "DELETE_SCHEDULED_TASK_SUCCESS"; export const DELETE_SCHEDULED_TASK_ERROR = "DELETE_SCHEDULED_TASK_ERROR"; +export const KILL_SCHEDULED_TASK_BEGIN = "KILL_DEAD_TASK_BEGIN"; +export const KILL_SCHEDULED_TASK_SUCCESS = "KILL_DEAD_TASK_SUCCESS"; +export const KILL_SCHEDULED_TASK_ERROR = "KILL_DEAD_TASK_ERROR"; +export const KILL_RETRY_TASK_BEGIN = "KILL_RETRY_TASK_BEGIN"; +export const KILL_RETRY_TASK_SUCCESS = "KILL_RETRY_TASK_SUCCESS"; +export const KILL_RETRY_TASK_ERROR = "KILL_RETRY_TASK_ERROR"; export const BATCH_RUN_SCHEDULED_TASKS_BEGIN = "BATCH_RUN_SCHEDULED_TASKS_BEGIN"; export const BATCH_RUN_SCHEDULED_TASKS_SUCCESS = "BATCH_RUN_SCHEDULED_TASKS_SUCCESS"; export const BATCH_RUN_SCHEDULED_TASKS_ERROR = "BATCH_RUN_SCHEDULED_TASKS_ERROR"; +export const BATCH_KILL_SCHEDULED_TASKS_BEGIN = + "BATCH_KILL_SCHEDULED_TASKS_BEGIN"; +export const BATCH_KILL_SCHEDULED_TASKS_SUCCESS = + "BATCH_KILL_SCHEDULED_TASKS_SUCCESS"; +export const BATCH_KILL_SCHEDULED_TASKS_ERROR = + "BATCH_RUN_SCHEDULED_TASKS_ERROR"; export const BATCH_DELETE_SCHEDULED_TASKS_BEGIN = "BATCH_DELETE_SCHEDULED_TASKS_BEGIN"; export const BATCH_DELETE_SCHEDULED_TASKS_SUCCESS = @@ -81,6 +100,10 @@ export const RUN_ALL_SCHEDULED_TASKS_BEGIN = "RUN_ALL_SCHEDULED_TASKS_BEGIN"; export const RUN_ALL_SCHEDULED_TASKS_SUCCESS = "RUN_ALL_SCHEDULED_TASKS_SUCCESS"; export const RUN_ALL_SCHEDULED_TASKS_ERROR = "RUN_ALL_SCHEDULED_TASKS_ERROR"; +export const KILL_ALL_SCHEDULED_TASKS_BEGIN = "KILL_ALL_SCHEDULED_TASKS_BEGIN"; +export const KILL_ALL_SCHEDULED_TASKS_SUCCESS = + "KILL_ALL_SCHEDULED_TASKS_SUCCESS"; +export const KILL_ALL_SCHEDULED_TASKS_ERROR = "KILL_ALL_SCHEDULED_TASKS_ERROR"; export const DELETE_ALL_SCHEDULED_TASKS_BEGIN = "DELETE_ALL_SCHEDULED_TASKS_BEGIN"; export const DELETE_ALL_SCHEDULED_TASKS_SUCCESS = @@ -93,6 +116,9 @@ export const DELETE_RETRY_TASK_ERROR = "DELETE_RETRY_TASK_ERROR"; export const BATCH_RUN_RETRY_TASKS_BEGIN = "BATCH_RUN_RETRY_TASKS_BEGIN"; export const BATCH_RUN_RETRY_TASKS_SUCCESS = "BATCH_RUN_RETRY_TASKS_SUCCESS"; export const BATCH_RUN_RETRY_TASKS_ERROR = "BATCH_RUN_RETRY_TASKS_ERROR"; +export const BATCH_KILL_RETRY_TASKS_BEGIN = "BATCH_KILL_RETRY_TASKS_BEGIN"; +export const BATCH_KILL_RETRY_TASKS_SUCCESS = "BATCH_KILL_RETRY_TASKS_SUCCESS"; +export const BATCH_KILL_RETRY_TASKS_ERROR = "BATCH_KILL_RETRY_TASKS_ERROR"; export const BATCH_DELETE_RETRY_TASKS_BEGIN = "BATCH_DELETE_RETRY_TASKS_BEGIN"; export const BATCH_DELETE_RETRY_TASKS_SUCCESS = "BATCH_DELETE_RETRY_TASKS_SUCCESS"; @@ -100,6 +126,9 @@ export const BATCH_DELETE_RETRY_TASKS_ERROR = "BATCH_DELETE_RETRY_TASKS_ERROR"; export const RUN_ALL_RETRY_TASKS_BEGIN = "RUN_ALL_RETRY_TASKS_BEGIN"; export const RUN_ALL_RETRY_TASKS_SUCCESS = "RUN_ALL_RETRY_TASKS_SUCCESS"; export const RUN_ALL_RETRY_TASKS_ERROR = "RUN_ALL_RETRY_TASKS_ERROR"; +export const KILL_ALL_RETRY_TASKS_BEGIN = "KILL_ALL_RETRY_TASKS_BEGIN"; +export const KILL_ALL_RETRY_TASKS_SUCCESS = "KILL_ALL_RETRY_TASKS_SUCCESS"; +export const KILL_ALL_RETRY_TASKS_ERROR = "KILL_ALL_RETRY_TASKS_ERROR"; export const DELETE_ALL_RETRY_TASKS_BEGIN = "DELETE_ALL_RETRY_TASKS_BEGIN"; export const DELETE_ALL_RETRY_TASKS_SUCCESS = "DELETE_ALL_RETRY_TASKS_SUCCESS"; export const DELETE_ALL_RETRY_TASKS_ERROR = "DELETE_ALL_RETRY_TASKS_ERROR"; @@ -223,6 +252,7 @@ interface CancelActiveTaskErrorAction { taskId: string; error: string; } + interface RunScheduledTaskBeginAction { type: typeof RUN_SCHEDULED_TASK_BEGIN; queue: string; @@ -242,6 +272,25 @@ interface RunScheduledTaskErrorAction { error: string; } +interface KillScheduledTaskBeginAction { + type: typeof KILL_SCHEDULED_TASK_BEGIN; + queue: string; + taskKey: string; +} + +interface KillScheduledTaskSuccessAction { + type: typeof KILL_SCHEDULED_TASK_SUCCESS; + queue: string; + taskKey: string; +} + +interface KillScheduledTaskErrorAction { + type: typeof KILL_SCHEDULED_TASK_ERROR; + queue: string; + taskKey: string; + error: string; +} + interface RunRetryTaskBeginAction { type: typeof RUN_RETRY_TASK_BEGIN; queue: string; @@ -261,6 +310,25 @@ interface RunRetryTaskErrorAction { error: string; } +interface KillRetryTaskBeginAction { + type: typeof KILL_RETRY_TASK_BEGIN; + queue: string; + taskKey: string; +} + +interface KillRetryTaskSuccessAction { + type: typeof KILL_RETRY_TASK_SUCCESS; + queue: string; + taskKey: string; +} + +interface KillRetryTaskErrorAction { + type: typeof KILL_RETRY_TASK_ERROR; + queue: string; + taskKey: string; + error: string; +} + interface RunDeadTaskBeginAction { type: typeof RUN_DEAD_TASK_BEGIN; queue: string; @@ -353,6 +421,41 @@ interface RunAllScheduledTasksErrorAction { error: string; } +interface BatchKillScheduledTasksBeginAction { + type: typeof BATCH_KILL_SCHEDULED_TASKS_BEGIN; + queue: string; + taskKeys: string[]; +} + +interface BatchKillScheduledTasksSuccessAction { + type: typeof BATCH_KILL_SCHEDULED_TASKS_SUCCESS; + queue: string; + payload: BatchKillTasksResponse; +} + +interface BatchKillScheduledTasksErrorAction { + type: typeof BATCH_KILL_SCHEDULED_TASKS_ERROR; + queue: string; + taskKeys: string[]; + error: string; +} + +interface KillAllScheduledTasksBeginAction { + type: typeof KILL_ALL_SCHEDULED_TASKS_BEGIN; + queue: string; +} + +interface KillAllScheduledTasksSuccessAction { + type: typeof KILL_ALL_SCHEDULED_TASKS_SUCCESS; + queue: string; +} + +interface KillAllScheduledTasksErrorAction { + type: typeof KILL_ALL_SCHEDULED_TASKS_ERROR; + queue: string; + error: string; +} + interface DeleteAllScheduledTasksBeginAction { type: typeof DELETE_ALL_SCHEDULED_TASKS_BEGIN; queue: string; @@ -442,6 +545,41 @@ interface RunAllRetryTasksErrorAction { error: string; } +interface BatchKillRetryTasksBeginAction { + type: typeof BATCH_KILL_RETRY_TASKS_BEGIN; + queue: string; + taskKeys: string[]; +} + +interface BatchKillRetryTasksSuccessAction { + type: typeof BATCH_KILL_RETRY_TASKS_SUCCESS; + queue: string; + payload: BatchKillTasksResponse; +} + +interface BatchKillRetryTasksErrorAction { + type: typeof BATCH_KILL_RETRY_TASKS_ERROR; + queue: string; + taskKeys: string[]; + error: string; +} + +interface KillAllRetryTasksBeginAction { + type: typeof KILL_ALL_RETRY_TASKS_BEGIN; + queue: string; +} + +interface KillAllRetryTasksSuccessAction { + type: typeof KILL_ALL_RETRY_TASKS_SUCCESS; + queue: string; +} + +interface KillAllRetryTasksErrorAction { + type: typeof KILL_ALL_RETRY_TASKS_ERROR; + queue: string; + error: string; +} + interface DeleteAllRetryTasksBeginAction { type: typeof DELETE_ALL_RETRY_TASKS_BEGIN; queue: string; @@ -576,6 +714,12 @@ export type TasksActionTypes = | RunDeadTaskBeginAction | RunDeadTaskSuccessAction | RunDeadTaskErrorAction + | KillScheduledTaskBeginAction + | KillScheduledTaskSuccessAction + | KillScheduledTaskErrorAction + | KillRetryTaskBeginAction + | KillRetryTaskSuccessAction + | KillRetryTaskErrorAction | DeleteScheduledTaskBeginAction | DeleteScheduledTaskSuccessAction | DeleteScheduledTaskErrorAction @@ -588,6 +732,12 @@ export type TasksActionTypes = | RunAllScheduledTasksBeginAction | RunAllScheduledTasksSuccessAction | RunAllScheduledTasksErrorAction + | BatchKillScheduledTasksBeginAction + | BatchKillScheduledTasksSuccessAction + | BatchKillScheduledTasksErrorAction + | KillAllScheduledTasksBeginAction + | KillAllScheduledTasksSuccessAction + | KillAllScheduledTasksErrorAction | DeleteAllScheduledTasksBeginAction | DeleteAllScheduledTasksSuccessAction | DeleteAllScheduledTasksErrorAction @@ -603,6 +753,12 @@ export type TasksActionTypes = | RunAllRetryTasksBeginAction | RunAllRetryTasksSuccessAction | RunAllRetryTasksErrorAction + | BatchKillRetryTasksBeginAction + | BatchKillRetryTasksSuccessAction + | BatchKillRetryTasksErrorAction + | KillAllRetryTasksBeginAction + | KillAllRetryTasksSuccessAction + | KillAllRetryTasksErrorAction | DeleteAllRetryTasksBeginAction | DeleteAllRetryTasksSuccessAction | DeleteAllRetryTasksErrorAction @@ -790,6 +946,42 @@ export function runRetryTaskAsync(queue: string, taskKey: string) { }; } +export function killScheduledTaskAsync(queue: string, taskKey: string) { + return async (dispatch: Dispatch) => { + dispatch({ type: KILL_SCHEDULED_TASK_BEGIN, queue, taskKey }); + try { + await killScheduledTask(queue, taskKey); + dispatch({ type: KILL_SCHEDULED_TASK_SUCCESS, queue, taskKey }); + } catch (error) { + console.error("killScheduledTaskAsync: ", error); + dispatch({ + type: KILL_SCHEDULED_TASK_ERROR, + error: `Could not kill task: ${taskKey}`, + queue, + taskKey, + }); + } + }; +} + +export function killRetryTaskAsync(queue: string, taskKey: string) { + return async (dispatch: Dispatch) => { + dispatch({ type: KILL_RETRY_TASK_BEGIN, queue, taskKey }); + try { + await killRetryTask(queue, taskKey); + dispatch({ type: KILL_RETRY_TASK_SUCCESS, queue, taskKey }); + } catch (error) { + console.error("killRetryTaskAsync: ", error); + dispatch({ + type: KILL_RETRY_TASK_ERROR, + error: `Could not kill task: ${taskKey}`, + queue, + taskKey, + }); + } + }; +} + export function runDeadTaskAsync(queue: string, taskKey: string) { return async (dispatch: Dispatch) => { dispatch({ type: RUN_DEAD_TASK_BEGIN, queue, taskKey }); @@ -873,6 +1065,31 @@ export function batchRunScheduledTasksAsync(queue: string, taskKeys: string[]) { }; } +export function batchKillScheduledTasksAsync( + queue: string, + taskKeys: string[] +) { + return async (dispatch: Dispatch) => { + dispatch({ type: BATCH_KILL_SCHEDULED_TASKS_BEGIN, queue, taskKeys }); + try { + const response = await batchKillScheduledTasks(queue, taskKeys); + dispatch({ + type: BATCH_KILL_SCHEDULED_TASKS_SUCCESS, + queue: queue, + payload: response, + }); + } catch (error) { + console.error("batchKillScheduledTasksAsync: ", error); + dispatch({ + type: BATCH_KILL_SCHEDULED_TASKS_ERROR, + error: `Could not batch kill tasks: ${taskKeys}`, + queue, + taskKeys, + }); + } + }; +} + export function deleteAllScheduledTasksAsync(queue: string) { return async (dispatch: Dispatch) => { dispatch({ type: DELETE_ALL_SCHEDULED_TASKS_BEGIN, queue }); @@ -907,6 +1124,23 @@ export function runAllScheduledTasksAsync(queue: string) { }; } +export function killAllScheduledTasksAsync(queue: string) { + return async (dispatch: Dispatch) => { + dispatch({ type: RUN_ALL_SCHEDULED_TASKS_BEGIN, queue }); + try { + await killAllScheduledTasks(queue); + dispatch({ type: RUN_ALL_SCHEDULED_TASKS_SUCCESS, queue }); + } catch (error) { + console.error("killAllScheduledTasksAsync: ", error); + dispatch({ + type: RUN_ALL_SCHEDULED_TASKS_ERROR, + error: `Could not kill all scheduled tasks`, + queue, + }); + } + }; +} + export function deleteRetryTaskAsync(queue: string, taskKey: string) { return async (dispatch: Dispatch) => { dispatch({ type: DELETE_RETRY_TASK_BEGIN, queue, taskKey }); @@ -969,6 +1203,28 @@ export function batchRunRetryTasksAsync(queue: string, taskKeys: string[]) { }; } +export function batchKillRetryTasksAsync(queue: string, taskKeys: string[]) { + return async (dispatch: Dispatch) => { + dispatch({ type: BATCH_KILL_RETRY_TASKS_BEGIN, queue, taskKeys }); + try { + const response = await batchKillRetryTasks(queue, taskKeys); + dispatch({ + type: BATCH_KILL_RETRY_TASKS_SUCCESS, + queue: queue, + payload: response, + }); + } catch (error) { + console.error("batchKillRetryTasksAsync: ", error); + dispatch({ + type: BATCH_KILL_RETRY_TASKS_ERROR, + error: `Could not batch kill tasks: ${taskKeys}`, + queue, + taskKeys, + }); + } + }; +} + export function deleteAllRetryTasksAsync(queue: string) { return async (dispatch: Dispatch) => { dispatch({ type: DELETE_ALL_RETRY_TASKS_BEGIN, queue }); @@ -1003,6 +1259,23 @@ export function runAllRetryTasksAsync(queue: string) { }; } +export function killAllRetryTasksAsync(queue: string) { + return async (dispatch: Dispatch) => { + dispatch({ type: KILL_ALL_RETRY_TASKS_BEGIN, queue }); + try { + await killAllRetryTasks(queue); + dispatch({ type: KILL_ALL_RETRY_TASKS_SUCCESS, queue }); + } catch (error) { + console.error("killAllRetryTasksAsync: ", error); + dispatch({ + type: KILL_ALL_RETRY_TASKS_ERROR, + error: `Could not kill all retry tasks`, + queue, + }); + } + }; +} + export function deleteDeadTaskAsync(queue: string, taskKey: string) { return async (dispatch: Dispatch) => { dispatch({ type: DELETE_DEAD_TASK_BEGIN, queue, taskKey }); diff --git a/ui/src/api.ts b/ui/src/api.ts index f6811b9..f23cd3f 100644 --- a/ui/src/api.ts +++ b/ui/src/api.ts @@ -51,6 +51,11 @@ export interface BatchRunTasksResponse { error_keys: string[]; } +export interface BatchKillTasksResponse { + dead_keys: string[]; + error_keys: string[]; +} + export interface Queue { queue: string; paused: boolean; @@ -263,6 +268,16 @@ export async function runScheduledTask( }); } +export async function killScheduledTask( + qname: string, + taskKey: string +): Promise { + await axios({ + method: "post", + url: `${BASE_URL}/queues/${qname}/scheduled_tasks/${taskKey}:kill`, + }); +} + export async function deleteScheduledTask( qname: string, taskKey: string @@ -315,6 +330,27 @@ export async function runAllScheduledTasks(qname: string): Promise { }); } +export async function batchKillScheduledTasks( + qname: string, + taskKeys: string[] +): Promise { + const resp = await axios({ + method: "post", + url: `${BASE_URL}/queues/${qname}/scheduled_tasks:batch_kill`, + data: { + task_keys: taskKeys, + }, + }); + return resp.data; +} + +export async function killAllScheduledTasks(qname: string): Promise { + await axios({ + method: "post", + url: `${BASE_URL}/queues/${qname}/scheduled_tasks:kill_all`, + }); +} + export async function runRetryTask( qname: string, taskKey: string @@ -325,6 +361,16 @@ export async function runRetryTask( }); } +export async function killRetryTask( + qname: string, + taskKey: string +): Promise { + await axios({ + method: "post", + url: `${BASE_URL}/queues/${qname}/retry_tasks/${taskKey}:kill`, + }); +} + export async function deleteRetryTask( qname: string, taskKey: string @@ -377,6 +423,27 @@ export async function runAllRetryTasks(qname: string): Promise { }); } +export async function batchKillRetryTasks( + qname: string, + taskKeys: string[] +): Promise { + const resp = await axios({ + method: "post", + url: `${BASE_URL}/queues/${qname}/retry_tasks:batch_kill`, + data: { + task_keys: taskKeys, + }, + }); + return resp.data; +} + +export async function killAllRetryTasks(qname: string): Promise { + await axios({ + method: "post", + url: `${BASE_URL}/queues/${qname}/retry_tasks:kill_all`, + }); +} + export async function runDeadTask( qname: string, taskKey: string diff --git a/ui/src/components/DeadTasksTable.tsx b/ui/src/components/DeadTasksTable.tsx index 87e478f..1d259aa 100644 --- a/ui/src/components/DeadTasksTable.tsx +++ b/ui/src/components/DeadTasksTable.tsx @@ -124,13 +124,13 @@ function DeadTasksTable(props: Props & ReduxProps) { const handleBatchRunClick = () => { props - .batchDeleteDeadTasksAsync(queue, selectedKeys) + .batchRunDeadTasksAsync(queue, selectedKeys) .then(() => setSelectedKeys([])); }; const handleBatchDeleteClick = () => { props - .batchRunDeadTasksAsync(queue, selectedKeys) + .batchDeleteDeadTasksAsync(queue, selectedKeys) .then(() => setSelectedKeys([])); }; diff --git a/ui/src/components/RetryTasksTable.tsx b/ui/src/components/RetryTasksTable.tsx index 8e5d8f4..af1eeab 100644 --- a/ui/src/components/RetryTasksTable.tsx +++ b/ui/src/components/RetryTasksTable.tsx @@ -25,11 +25,14 @@ import syntaxHighlightStyle from "react-syntax-highlighter/dist/esm/styles/hljs/ import { batchDeleteRetryTasksAsync, batchRunRetryTasksAsync, + batchKillRetryTasksAsync, deleteAllRetryTasksAsync, runAllRetryTasksAsync, + killAllRetryTasksAsync, listRetryTasksAsync, deleteRetryTaskAsync, runRetryTaskAsync, + killRetryTaskAsync, } from "../actions/tasksActions"; import { AppState } from "../store"; import TablePaginationActions, { @@ -60,11 +63,14 @@ function mapStateToProps(state: AppState) { const mapDispatchToProps = { batchDeleteRetryTasksAsync, batchRunRetryTasksAsync, + batchKillRetryTasksAsync, deleteAllRetryTasksAsync, runAllRetryTasksAsync, + killAllRetryTasksAsync, listRetryTasksAsync, deleteRetryTaskAsync, runRetryTaskAsync, + killRetryTaskAsync, }; const connector = connect(mapStateToProps, mapDispatchToProps); @@ -114,15 +120,25 @@ function RetryTasksTable(props: Props & ReduxProps) { props.deleteAllRetryTasksAsync(queue); }; + const handleKillAllClick = () => { + props.killAllRetryTasksAsync(queue); + }; + const handleBatchRunClick = () => { props - .batchDeleteRetryTasksAsync(queue, selectedKeys) + .batchRunRetryTasksAsync(queue, selectedKeys) .then(() => setSelectedKeys([])); }; const handleBatchDeleteClick = () => { props - .batchRunRetryTasksAsync(queue, selectedKeys) + .batchDeleteRetryTasksAsync(queue, selectedKeys) + .then(() => setSelectedKeys([])); + }; + + const handleBatchKillClick = () => { + props + .batchKillRetryTasksAsync(queue, selectedKeys) .then(() => setSelectedKeys([])); }; @@ -163,8 +179,10 @@ function RetryTasksTable(props: Props & ReduxProps) { showBatchActions={numSelected > 0} onRunAllClick={handleRunAllClick} onDeleteAllClick={handleDeleteAllClick} + onKillAllClick={handleKillAllClick} onBatchRunClick={handleBatchRunClick} onBatchDeleteClick={handleBatchDeleteClick} + onBatchKillClick={handleBatchKillClick} /> { props.deleteRetryTaskAsync(task.queue, task.key); }} + onKillClick={() => { + props.killRetryTaskAsync(task.queue, task.key); + }} /> ))} @@ -253,6 +274,7 @@ interface RowProps { onSelectChange: (checked: boolean) => void; onDeleteClick: () => void; onRunClick: () => void; + onKillClick: () => void; allActionPending: boolean; } @@ -295,6 +317,12 @@ function Row(props: RowProps) { > Run +
{ props.deleteScheduledTaskAsync(queue, task.key); }} + onKillClick={() => { + props.killScheduledTaskAsync(queue, task.key); + }} /> ))} @@ -250,6 +271,7 @@ interface RowProps { onSelectChange: (checked: boolean) => void; onRunClick: () => void; onDeleteClick: () => void; + onKillClick: () => void; allActionPending: boolean; } @@ -289,6 +311,12 @@ function Row(props: RowProps) { > Run + - + {props.onBatchKillClick && ( + + )}