From 833ca7c60bdc8a3d762fe207103b61a26e551290 Mon Sep 17 00:00:00 2001 From: Abdulmateen Tairu <36048005+Taycode@users.noreply.github.com> Date: Mon, 26 Jun 2023 17:48:05 +0100 Subject: [PATCH] Add promote all actions to delayed queues (#596) * Add promote all actions to delayed queues * prettier fixes --- .gitignore | 1 + packages/api/src/handlers/promoteAll.ts | 18 ++++++++++++++++++ packages/api/src/routes.ts | 6 ++++++ .../components/QueueActions/QueueActions.tsx | 13 +++++++++++++ packages/ui/src/hooks/useStore.ts | 9 +++++++++ packages/ui/src/services/Api.ts | 6 ++++++ packages/ui/typings/app.d.ts | 1 + 7 files changed, 54 insertions(+) create mode 100644 packages/api/src/handlers/promoteAll.ts diff --git a/.gitignore b/.gitignore index 63fbc475d..8216f8a45 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ yarn-error.log website/build docker-compose.dockest-generated.yml dockest-error.json +.idea/ diff --git a/packages/api/src/handlers/promoteAll.ts b/packages/api/src/handlers/promoteAll.ts new file mode 100644 index 000000000..6b421efe2 --- /dev/null +++ b/packages/api/src/handlers/promoteAll.ts @@ -0,0 +1,18 @@ +import { BullBoardRequest, ControllerHandlerReturnType } from "../../typings/app"; +import { BaseAdapter } from "../queueAdapters/base"; +import { STATUSES } from "../constants/statuses"; +import { queueProvider } from "../providers/queue"; + +async function promoteAll( + _req: BullBoardRequest, + queue: BaseAdapter +): Promise { + const queueStatus = STATUSES.delayed; + + const jobs = await queue.getJobs([queueStatus]); + await Promise.all(jobs.map((job) => job.promote())); + + return { status: 200, body: {} }; +} + +export const promoteAllHandler = queueProvider(promoteAll); diff --git a/packages/api/src/routes.ts b/packages/api/src/routes.ts index 037a3e260..000cf8b1c 100644 --- a/packages/api/src/routes.ts +++ b/packages/api/src/routes.ts @@ -11,6 +11,7 @@ import { redisStatsHandler } from './handlers/redisStats'; import { resumeQueueHandler } from './handlers/resumeQueue'; import { retryAllHandler } from './handlers/retryAll'; import { retryJobHandler } from './handlers/retryJob'; +import { promoteAllHandler } from "./handlers/promoteAll"; export const appRoutes: AppRouteDefs = { entryPoint: { @@ -31,6 +32,11 @@ export const appRoutes: AppRouteDefs = { route: '/api/queues/:queueName/retry/:queueStatus', handler: retryAllHandler, }, + { + method: 'put', + route: '/api/queues/:queueName/promote', + handler: promoteAllHandler, + }, { method: 'put', route: '/api/queues/:queueName/clean/:queueStatus', diff --git a/packages/ui/src/components/QueueActions/QueueActions.tsx b/packages/ui/src/components/QueueActions/QueueActions.tsx index 8d8c61199..86b003010 100644 --- a/packages/ui/src/components/QueueActions/QueueActions.tsx +++ b/packages/ui/src/components/QueueActions/QueueActions.tsx @@ -6,6 +6,7 @@ import { RetryIcon } from '../Icons/Retry'; import { TrashIcon } from '../Icons/Trash'; import { Button } from '../JobCard/Button/Button'; import s from './QueueActions.module.css'; +import { PromoteIcon } from "../Icons/Promote"; interface QueueActionProps { queue: AppQueue; @@ -26,6 +27,10 @@ function isRetryAllStatus(status: any): status is JobRetryStatus { return [STATUSES.failed, STATUSES.completed].includes(status); } +function isPromoteAllStatus(status: any): status is JobRetryStatus { + return [STATUSES.delayed].includes(status); +} + export const QueueActions = ({ status, actions, queue, allowRetries }: QueueActionProps) => { if (!isStatusActionable(status)) { return null; @@ -49,6 +54,14 @@ export const QueueActions = ({ status, actions, queue, allowRetries }: QueueActi )} + {isPromoteAllStatus(status) && ( +
  • + +
  • + )} ); }; diff --git a/packages/ui/src/hooks/useStore.ts b/packages/ui/src/hooks/useStore.ts index 6cb3eb580..0139d0dc8 100644 --- a/packages/ui/src/hooks/useStore.ts +++ b/packages/ui/src/hooks/useStore.ts @@ -9,6 +9,7 @@ import { useInterval } from './useInterval'; import { useQuery } from './useQuery'; import { useSelectedStatuses } from './useSelectedStatuses'; import { useSettingsStore } from './useSettings'; +import { STATUSES } from "@bull-board/api/dist/src/constants/statuses"; type State = { data: null | GetQueuesResponse; @@ -109,6 +110,13 @@ export const useStore = (): Store => { confirmQueueActions ); + const promoteAll = (queueName: string) => + withConfirmAndUpdate( + () => api.promoteAll(queueName), + `Are you sure that you want to promote all ${STATUSES.delayed} jobs?`, + confirmQueueActions + ); + const cleanAll = (queueName: string, status: JobCleanStatus) => withConfirmAndUpdate( () => api.cleanAll(queueName, status), @@ -144,6 +152,7 @@ export const useStore = (): Store => { state, actions: { promoteJob, + promoteAll, retryJob, retryAll, cleanJob, diff --git a/packages/ui/src/services/Api.ts b/packages/ui/src/services/Api.ts index 98d2082fd..f97766de9 100644 --- a/packages/ui/src/services/Api.ts +++ b/packages/ui/src/services/Api.ts @@ -37,6 +37,12 @@ export class Api { ); } + public promoteAll(queueName: string): Promise { + return this.axios.put( + `/queues/${encodeURIComponent(queueName)}/promote` + ); + } + public cleanAll(queueName: string, status: JobCleanStatus): Promise { return this.axios.put( `/queues/${encodeURIComponent(queueName)}/clean/${encodeURIComponent(status)}` diff --git a/packages/ui/typings/app.d.ts b/packages/ui/typings/app.d.ts index 9c745faca..01250fc22 100644 --- a/packages/ui/typings/app.d.ts +++ b/packages/ui/typings/app.d.ts @@ -16,6 +16,7 @@ export interface QueueActions { cleanJob: (queueName: string) => (job: AppJob) => () => Promise; getJobLogs: (queueName: string) => (job: AppJob) => () => Promise; retryAll: (queueName: string, status: JobRetryStatus) => () => Promise; + promoteAll: (queueName: string) => () => Promise; cleanAll: (queueName: string, status: JobCleanStatus) => () => Promise; pauseQueue: (queueName: string) => () => Promise; resumeQueue: (queueName: string) => () => Promise;