Add redux actions and reducer for active task cancellation

This commit is contained in:
Ken Hibino 2020-12-05 09:24:42 -08:00
parent 47d8c73ab7
commit a737eea675
3 changed files with 120 additions and 3 deletions

View File

@ -1,4 +1,5 @@
import { import {
cancelActiveTask,
listActiveTasks, listActiveTasks,
ListActiveTasksResponse, ListActiveTasksResponse,
listDeadTasks, listDeadTasks,
@ -29,6 +30,9 @@ export const LIST_RETRY_TASKS_ERROR = "LIST_RETRY_TASKS_ERROR";
export const LIST_DEAD_TASKS_BEGIN = "LIST_DEAD_TASKS_BEGIN"; export const LIST_DEAD_TASKS_BEGIN = "LIST_DEAD_TASKS_BEGIN";
export const LIST_DEAD_TASKS_SUCCESS = "LIST_DEAD_TASKS_SUCCESS"; export const LIST_DEAD_TASKS_SUCCESS = "LIST_DEAD_TASKS_SUCCESS";
export const LIST_DEAD_TASKS_ERROR = "LIST_DEAD_TASKS_ERROR"; export const LIST_DEAD_TASKS_ERROR = "LIST_DEAD_TASKS_ERROR";
export const CANCEL_ACTIVE_TASK_BEGIN = "CANCEL_ACTIVE_TASK_BEGIN";
export const CANCEL_ACTIVE_TASK_SUCCESS = "CANCEL_ACTIVE_TASK_SUCCESS";
export const CANCEL_ACTIVE_TASK_ERROR = "CANCEL_ACTIVE_TASK_ERROR";
interface ListActiveTasksBeginAction { interface ListActiveTasksBeginAction {
type: typeof LIST_ACTIVE_TASKS_BEGIN; type: typeof LIST_ACTIVE_TASKS_BEGIN;
@ -115,6 +119,25 @@ interface ListDeadTasksErrorAction {
error: string; // error description error: string; // error description
} }
interface CancelActiveTaskBeginAction {
type: typeof CANCEL_ACTIVE_TASK_BEGIN;
queue: string;
taskId: string;
}
interface CancelActiveTaskSuccessAction {
type: typeof CANCEL_ACTIVE_TASK_SUCCESS;
queue: string;
taskId: string;
}
interface CancelActiveTaskErrorAction {
type: typeof CANCEL_ACTIVE_TASK_ERROR;
queue: string;
taskId: 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
@ -131,7 +154,10 @@ export type TasksActionTypes =
| ListRetryTasksErrorAction | ListRetryTasksErrorAction
| ListDeadTasksBeginAction | ListDeadTasksBeginAction
| ListDeadTasksSuccessAction | ListDeadTasksSuccessAction
| ListDeadTasksErrorAction; | ListDeadTasksErrorAction
| CancelActiveTaskBeginAction
| CancelActiveTaskSuccessAction
| CancelActiveTaskErrorAction;
export function listActiveTasksAsync( export function listActiveTasksAsync(
qname: string, qname: string,
@ -247,3 +273,20 @@ export function listDeadTasksAsync(
} }
}; };
} }
export function cancelActiveTaskAsync(queue: string, taskId: string) {
return async (dispatch: Dispatch<TasksActionTypes>) => {
dispatch({ type: CANCEL_ACTIVE_TASK_BEGIN, queue, taskId });
try {
await cancelActiveTask(queue, taskId);
dispatch({ type: CANCEL_ACTIVE_TASK_SUCCESS, queue, taskId });
} catch {
dispatch({
type: CANCEL_ACTIVE_TASK_ERROR,
error: `Could not cancel task: ${taskId}`,
queue,
taskId,
});
}
};
}

View File

@ -170,6 +170,16 @@ export async function listActiveTasks(
return resp.data; return resp.data;
} }
export async function cancelActiveTask(
qname: string,
taskId: string
): Promise<void> {
await axios({
method: "post",
url: `${BASE_URL}/queues/${qname}/active_tasks/${taskId}/cancel`,
});
}
export async function listPendingTasks( export async function listPendingTasks(
qname: string, qname: string,
pageOpts?: PaginationOptions pageOpts?: PaginationOptions

View File

@ -15,6 +15,9 @@ import {
LIST_DEAD_TASKS_BEGIN, LIST_DEAD_TASKS_BEGIN,
LIST_DEAD_TASKS_SUCCESS, LIST_DEAD_TASKS_SUCCESS,
LIST_DEAD_TASKS_ERROR, LIST_DEAD_TASKS_ERROR,
CANCEL_ACTIVE_TASK_BEGIN,
CANCEL_ACTIVE_TASK_SUCCESS,
CANCEL_ACTIVE_TASK_ERROR,
} from "../actions/tasksActions"; } from "../actions/tasksActions";
import { import {
ActiveTask, ActiveTask,
@ -24,11 +27,21 @@ import {
ScheduledTask, ScheduledTask,
} from "../api"; } from "../api";
interface ActiveTaskExtended extends ActiveTask {
// Indicates that a request has been sent for this
// task and awaiting for a response.
requestPending: boolean;
// Incidates that a cancelation signal has been
// published for this task.
canceling: boolean;
}
interface TasksState { interface TasksState {
activeTasks: { activeTasks: {
loading: boolean; loading: boolean;
error: string; error: string;
data: ActiveTask[]; data: ActiveTaskExtended[];
}; };
pendingTasks: { pendingTasks: {
loading: boolean; loading: boolean;
@ -101,7 +114,11 @@ function tasksReducer(
activeTasks: { activeTasks: {
loading: false, loading: false,
error: "", error: "",
data: action.payload.tasks, data: action.payload.tasks.map((task) => ({
...task,
canceling: false,
requestPending: false,
})),
}, },
}; };
@ -235,6 +252,53 @@ function tasksReducer(
}, },
}; };
case CANCEL_ACTIVE_TASK_BEGIN: {
const newData = state.activeTasks.data.map((task) => {
if (task.id !== action.taskId) {
return task;
}
return { ...task, requestPending: true };
});
return {
...state,
activeTasks: {
...state.activeTasks,
data: newData,
},
};
}
case CANCEL_ACTIVE_TASK_SUCCESS: {
const newData = state.activeTasks.data.map((task) => {
if (task.id !== action.taskId) {
return task;
}
return { ...task, requestPending: false, canceling: true };
});
return {
...state,
activeTasks: {
...state.activeTasks,
data: newData,
},
};
}
case CANCEL_ACTIVE_TASK_ERROR:
const newData = state.activeTasks.data.map((task) => {
if (task.id !== action.taskId) {
return task;
}
return { ...task, requestPending: false };
});
return {
...state,
activeTasks: {
...state.activeTasks,
data: newData,
},
};
default: default:
return state; return state;
} }