From 3e5b1458833e642ef0c8fc81b27eecd2d816aded Mon Sep 17 00:00:00 2001 From: Ken Hibino Date: Wed, 2 Dec 2020 19:44:50 -0800 Subject: [PATCH] Add redux actions and reducer for scheduler entries --- ui/src/actions/schedulerEntriesActions.ts | 46 ++++++++++++++++++++ ui/src/api.ts | 22 ++++++++++ ui/src/reducers/schedulerEntriesReducer.ts | 49 ++++++++++++++++++++++ ui/src/{store.tsx => store.ts} | 2 + 4 files changed, 119 insertions(+) create mode 100644 ui/src/actions/schedulerEntriesActions.ts create mode 100644 ui/src/reducers/schedulerEntriesReducer.ts rename ui/src/{store.tsx => store.ts} (82%) diff --git a/ui/src/actions/schedulerEntriesActions.ts b/ui/src/actions/schedulerEntriesActions.ts new file mode 100644 index 0000000..cfe4e1d --- /dev/null +++ b/ui/src/actions/schedulerEntriesActions.ts @@ -0,0 +1,46 @@ +import { Dispatch } from "@reduxjs/toolkit"; +import { listSchedulerEntries, ListSchedulerEntriesResponse } from "../api"; + +// List of scheduler-entry related action types. +export const LIST_SCHEDULER_ENTRIES_BEGIN = "LIST_SCHEDULER_ENTRIES_BEGIN"; +export const LIST_SCHEDULER_ENTRIES_SUCCESS = "LIST_SCHEDULER_ENTRIES_SUCCESS"; +export const LIST_SCHEDULER_ENTRIES_ERROR = "LIST_SCHEDULER_ENTRIES_ERROR"; + +interface ListSchedulerEntriesBeginAction { + type: typeof LIST_SCHEDULER_ENTRIES_BEGIN; +} + +interface ListSchedulerEntriesSuccessAction { + type: typeof LIST_SCHEDULER_ENTRIES_SUCCESS; + payload: ListSchedulerEntriesResponse; +} + +interface ListSchedulerEntriesErrorAction { + type: typeof LIST_SCHEDULER_ENTRIES_ERROR; + error: string; // error description +} + +// Union of all scheduler-entry related actions. +export type SchedulerEntriesActionTypes = + | ListSchedulerEntriesBeginAction + | ListSchedulerEntriesSuccessAction + | ListSchedulerEntriesErrorAction; + +export function listSchedulerEntriesAsync() { + return async (dispatch: Dispatch) => { + dispatch({ type: LIST_SCHEDULER_ENTRIES_BEGIN }); + try { + const response = await listSchedulerEntries(); + dispatch({ + type: LIST_SCHEDULER_ENTRIES_SUCCESS, + payload: response, + }); + } catch (error) { + console.error(error); + dispatch({ + type: LIST_SCHEDULER_ENTRIES_ERROR, + error: "Could not retrieve scheduler entries", + }); + } + }; +} diff --git a/ui/src/api.ts b/ui/src/api.ts index 4c5704b..a7a2c75 100644 --- a/ui/src/api.ts +++ b/ui/src/api.ts @@ -37,6 +37,10 @@ export interface ListDeadTasksResponse { stats: Queue; } +export interface ListSchedulerEntriesResponse { + entries: SchedulerEntry[]; +} + export interface Queue { queue: string; paused: boolean; @@ -97,6 +101,16 @@ export interface DeadTask extends BaseTask { error_message: string; } +export interface SchedulerEntry { + id: string; + spec: string; + task_type: string; + task_payload: { [key: string]: any }; + options: string[]; + next_enqueue_at: string; + prev_enqueue_at: string; +} + export interface PaginationOptions extends Record { size?: number; // size of the page page?: number; // page number (1 being the first page) @@ -213,3 +227,11 @@ export async function listDeadTasks( }); return resp.data; } + +export async function listSchedulerEntries(): Promise { + const resp = await axios({ + method: "get", + url: `${BASE_URL}/scheduler_entries`, + }); + return resp.data; +} diff --git a/ui/src/reducers/schedulerEntriesReducer.ts b/ui/src/reducers/schedulerEntriesReducer.ts new file mode 100644 index 0000000..7c907b8 --- /dev/null +++ b/ui/src/reducers/schedulerEntriesReducer.ts @@ -0,0 +1,49 @@ +import { + LIST_SCHEDULER_ENTRIES_BEGIN, + LIST_SCHEDULER_ENTRIES_ERROR, + LIST_SCHEDULER_ENTRIES_SUCCESS, + SchedulerEntriesActionTypes, +} from "../actions/schedulerEntriesActions"; +import { SchedulerEntry } from "../api"; + +interface SchedulerEntriesState { + loading: boolean; + data: SchedulerEntry[]; + error: string; // error description +} + +const initialState: SchedulerEntriesState = { + loading: false, + data: [], + error: "", +}; + +function schedulerEntriesReducer( + state = initialState, + action: SchedulerEntriesActionTypes +): SchedulerEntriesState { + switch (action.type) { + case LIST_SCHEDULER_ENTRIES_BEGIN: + return { + ...state, + loading: true, + }; + case LIST_SCHEDULER_ENTRIES_SUCCESS: + return { + error: "", + loading: false, + data: action.payload.entries, + }; + case LIST_SCHEDULER_ENTRIES_ERROR: + // TODO: set error state + return { + ...state, + loading: false, + error: action.error, + }; + default: + return state; + } +} + +export default schedulerEntriesReducer; diff --git a/ui/src/store.tsx b/ui/src/store.ts similarity index 82% rename from ui/src/store.tsx rename to ui/src/store.ts index 3493fd2..3587b8e 100644 --- a/ui/src/store.tsx +++ b/ui/src/store.ts @@ -2,11 +2,13 @@ import { combineReducers, configureStore } from "@reduxjs/toolkit"; import settingsReducer from "./reducers/settingsReducer"; import queuesReducer from "./reducers/queuesReducer"; import tasksReducer from "./reducers/tasksReducer"; +import schedulerEntriesReducer from "./reducers/schedulerEntriesReducer"; const rootReducer = combineReducers({ settings: settingsReducer, queues: queuesReducer, tasks: tasksReducer, + schedulerEntries: schedulerEntriesReducer, }); // AppState is the top-level application state maintained by redux store.