From 561295251434db3fdd3c6c5f269b0aa6bce937a4 Mon Sep 17 00:00:00 2001 From: Felix Mosheev <9304194+felixmosh@users.noreply.github.com> Date: Fri, 7 May 2021 11:41:34 +0300 Subject: [PATCH] refactor: extract common control code to queueProvider & jobProvider --- src/routes/apiRouter.ts | 41 +++++++++++++++++-------- src/routes/handlers/cleanAll.ts | 19 ++---------- src/routes/handlers/cleanJob.ts | 33 ++++---------------- src/routes/handlers/jobLogs.ts | 24 ++------------- src/routes/handlers/promoteJob.ts | 28 ++--------------- src/routes/handlers/retryAll.ts | 22 ++++--------- src/routes/handlers/retryJob.ts | 31 ++++--------------- src/routes/middlewares/jobProvider.ts | 25 +++++++++++++++ src/routes/middlewares/queueProvider.ts | 33 ++++++++++++++++++++ src/routes/middlewares/wrapAsync.ts | 6 ++++ 10 files changed, 120 insertions(+), 142 deletions(-) create mode 100644 src/routes/middlewares/jobProvider.ts create mode 100644 src/routes/middlewares/queueProvider.ts create mode 100644 src/routes/middlewares/wrapAsync.ts diff --git a/src/routes/apiRouter.ts b/src/routes/apiRouter.ts index b5538ce9..ca1e37be 100644 --- a/src/routes/apiRouter.ts +++ b/src/routes/apiRouter.ts @@ -1,5 +1,4 @@ import { Router } from 'express' -import { ParamsDictionary, RequestHandler } from 'express-serve-static-core' import { cleanAll } from './handlers/cleanAll' import { cleanJob } from './handlers/cleanJob' import { errorHandler } from './handlers/errorHandler' @@ -8,18 +7,36 @@ import { promoteJob } from './handlers/promoteJob' import { queuesHandler } from './handlers/queues' import { retryAll } from './handlers/retryAll' import { retryJob } from './handlers/retryJob' - -const wrapAsync = ( - fn: RequestHandler, -): RequestHandler => async (req, res, next) => - Promise.resolve(fn(req, res, next)).catch(next) +import { jobProvider } from './middlewares/jobProvider' +import { queueProvider } from './middlewares/queueProvider' +import { wrapAsync } from './middlewares/wrapAsync' export const apiRouter = Router() .get('/queues', wrapAsync(queuesHandler)) - .put('/queues/:queueName/retry', wrapAsync(retryAll)) - .put('/queues/:queueName/:id/retry', wrapAsync(retryJob)) - .put('/queues/:queueName/:id/clean', wrapAsync(cleanJob)) - .put('/queues/:queueName/:id/promote', wrapAsync(promoteJob)) - .get('/queues/:queueName/:id/logs', wrapAsync(jobLogs)) - .put('/queues/:queueName/clean/:queueStatus', wrapAsync(cleanAll)) + .put('/queues/:queueName/retry', queueProvider(), wrapAsync(retryAll)) + .put( + '/queues/:queueName/:jobId/retry', + [queueProvider(), jobProvider()], + wrapAsync(retryJob), + ) + .put( + '/queues/:queueName/:jobId/clean', + [queueProvider(), jobProvider()], + wrapAsync(cleanJob), + ) + .put( + '/queues/:queueName/:jobId/promote', + [queueProvider(), jobProvider()], + wrapAsync(promoteJob), + ) + .put( + '/queues/:queueName/clean/:queueStatus', + queueProvider(), + wrapAsync(cleanAll), + ) + .get( + '/queues/:queueName/:jobId/logs', + [queueProvider({ skipReadOnlyModeCheck: true }), jobProvider()], + wrapAsync(jobLogs), + ) .use(errorHandler) diff --git a/src/routes/handlers/cleanAll.ts b/src/routes/handlers/cleanAll.ts index 2db310cc..98441c30 100644 --- a/src/routes/handlers/cleanAll.ts +++ b/src/routes/handlers/cleanAll.ts @@ -1,5 +1,5 @@ import { Request, RequestHandler, Response } from 'express-serve-static-core' -import { BullBoardQueues, JobCleanStatus } from '../../@types/app' +import { JobCleanStatus } from '../../@types/app' type RequestParams = { queueName: string @@ -10,24 +10,11 @@ export const cleanAll: RequestHandler = async ( req: Request, res: Response, ) => { - const { queueName, queueStatus } = req.params - const { bullBoardQueues } = req.app.locals as { - bullBoardQueues: BullBoardQueues - } + const { queueStatus } = req.params + const { queue } = res.locals const GRACE_TIME_MS = 5000 - const queue = bullBoardQueues.get(queueName) - if (!queue) { - return res.status(404).send({ - error: 'Queue not found', - }) - } else if (queue.readOnlyMode) { - return res.status(405).send({ - error: 'Method not allowed on read only queue', - }) - } - await queue.clean(queueStatus as any, GRACE_TIME_MS) return res.sendStatus(200) diff --git a/src/routes/handlers/cleanJob.ts b/src/routes/handlers/cleanJob.ts index 9e335d42..c24040e6 100644 --- a/src/routes/handlers/cleanJob.ts +++ b/src/routes/handlers/cleanJob.ts @@ -1,32 +1,11 @@ import { Request, RequestHandler, Response } from 'express-serve-static-core' -import { BullBoardQueues } from '../../@types/app' +import { QueueJob } from '../../@types/app' -export const cleanJob: RequestHandler = async (req: Request, res: Response) => { - const { bullBoardQueues } = req.app.locals as { - bullBoardQueues: BullBoardQueues - } - const { queueName, id } = req.params - const queue = bullBoardQueues.get(queueName) - - if (!queue) { - return res.status(404).send({ - error: 'Queue not found', - }) - } else if (queue.readOnlyMode) { - return res.status(405).send({ - error: 'Method not allowed on read only queue', - }) - } - - const job = await queue.getJob(id) - - if (!job) { - throw new Error('xxxx') - - return res.status(404).send({ - error: 'Job not found', - }) - } +export const cleanJob: RequestHandler = async ( + _req: Request, + res: Response, +) => { + const { job } = res.locals as { job: QueueJob } await job.remove() diff --git a/src/routes/handlers/jobLogs.ts b/src/routes/handlers/jobLogs.ts index b870c560..0b0bc560 100644 --- a/src/routes/handlers/jobLogs.ts +++ b/src/routes/handlers/jobLogs.ts @@ -1,28 +1,10 @@ import { Request, RequestHandler, Response } from 'express-serve-static-core' -import { BullBoardQueues } from '../../@types/app' export const jobLogs: RequestHandler = async (req: Request, res: Response) => { - const { bullBoardQueues } = req.app.locals as { - bullBoardQueues: BullBoardQueues - } - const { queueName, id } = req.params - const queue = bullBoardQueues.get(queueName) + const { jobId } = req.params + const { queue } = res.locals - if (!queue) { - return res.status(404).send({ - error: 'Queue not found', - }) - } - - const job = await queue.getJob(id) - - if (!job) { - return res.status(404).send({ - error: 'Job not found', - }) - } - - const logs = await queue.getJobLogs(id) + const logs = await queue.getJobLogs(jobId) return res.json(logs) } diff --git a/src/routes/handlers/promoteJob.ts b/src/routes/handlers/promoteJob.ts index 2277cb1e..4820a2a4 100644 --- a/src/routes/handlers/promoteJob.ts +++ b/src/routes/handlers/promoteJob.ts @@ -1,33 +1,11 @@ import { Request, RequestHandler, Response } from 'express-serve-static-core' -import { BullBoardQueues } from '../../@types/app' +import { QueueJob } from '../../@types/app' export const promoteJob: RequestHandler = async ( - req: Request, + _req: Request, res: Response, ) => { - const { bullBoardQueues } = req.app.locals as { - bullBoardQueues: BullBoardQueues - } - const { queueName, id } = req.params - const queue = bullBoardQueues.get(queueName) - - if (!queue) { - return res.status(404).send({ - error: 'Queue not found', - }) - } else if (queue.readOnlyMode) { - return res.status(405).send({ - error: 'Method not allowed on read only queue', - }) - } - - const job = await queue.getJob(id) - - if (!job) { - return res.status(404).send({ - error: 'Job not found', - }) - } + const { job } = res.locals as { job: QueueJob } await job.promote() diff --git a/src/routes/handlers/retryAll.ts b/src/routes/handlers/retryAll.ts index 8d946a63..2e3f38e4 100644 --- a/src/routes/handlers/retryAll.ts +++ b/src/routes/handlers/retryAll.ts @@ -1,21 +1,11 @@ import { Request, RequestHandler, Response } from 'express-serve-static-core' +import { BaseAdapter } from '../../queueAdapters/base' -import { BullBoardQueues } from '../../@types/app' - -export const retryAll: RequestHandler = async (req: Request, res: Response) => { - const { queueName } = req.params - const { bullBoardQueues } = req.app.locals as { - bullBoardQueues: BullBoardQueues - } - - const queue = bullBoardQueues.get(queueName) - if (!queue) { - return res.status(404).send({ error: 'queue not found' }) - } else if (queue.readOnlyMode) { - return res.status(405).send({ - error: 'Method not allowed on read only queue', - }) - } +export const retryAll: RequestHandler = async ( + _req: Request, + res: Response, +) => { + const { queue } = res.locals as { queue: BaseAdapter } const jobs = await queue.getJobs(['failed']) await Promise.all(jobs.map((job) => job.retry())) diff --git a/src/routes/handlers/retryJob.ts b/src/routes/handlers/retryJob.ts index 2e50d01c..ed384bb3 100644 --- a/src/routes/handlers/retryJob.ts +++ b/src/routes/handlers/retryJob.ts @@ -1,30 +1,11 @@ import { Request, RequestHandler, Response } from 'express-serve-static-core' -import { BullBoardQueues } from '../../@types/app' +import { QueueJob } from '../../@types/app' -export const retryJob: RequestHandler = async (req: Request, res: Response) => { - const { bullBoardQueues } = req.app.locals as { - bullBoardQueues: BullBoardQueues - } - const { queueName, id } = req.params - const queue = bullBoardQueues.get(queueName) - - if (!queue) { - return res.status(404).send({ - error: 'Queue not found', - }) - } else if (queue.readOnlyMode) { - return res.status(405).send({ - error: 'Method not allowed on read only queue', - }) - } - - const job = await queue.getJob(id) - - if (!job) { - return res.status(404).send({ - error: 'Job not found', - }) - } +export const retryJob: RequestHandler = async ( + _req: Request, + res: Response, +) => { + const { job } = res.locals as { job: QueueJob } await job.retry() diff --git a/src/routes/middlewares/jobProvider.ts b/src/routes/middlewares/jobProvider.ts new file mode 100644 index 00000000..9393efd3 --- /dev/null +++ b/src/routes/middlewares/jobProvider.ts @@ -0,0 +1,25 @@ +import { NextFunction, Request, Response } from 'express-serve-static-core' +import { BaseAdapter } from '../../queueAdapters/base' + +export function jobProvider() { + return async (req: Request, res: Response, next: NextFunction) => { + const { jobId } = req.params + const { queue } = res.locals as { queue: BaseAdapter } + + if (!jobId || !queue) { + return next(new Error('Invalid data')) + } + + const job = await queue.getJob(jobId) + + if (!job) { + return res.status(404).send({ + error: 'Job not found', + }) + } + + res.locals.job = job + + next() + } +} diff --git a/src/routes/middlewares/queueProvider.ts b/src/routes/middlewares/queueProvider.ts new file mode 100644 index 00000000..fecd3477 --- /dev/null +++ b/src/routes/middlewares/queueProvider.ts @@ -0,0 +1,33 @@ +import { NextFunction, Request, Response } from 'express-serve-static-core' +import { BullBoardQueues } from '../../@types/app' + +export function queueProvider({ + skipReadOnlyModeCheck = false, +}: { + skipReadOnlyModeCheck?: boolean +} = {}) { + return async (req: Request, res: Response, next: NextFunction) => { + const { queueName } = req.params + + if (typeof queueName === 'undefined') { + return next() + } + + const { bullBoardQueues } = req.app.locals as { + bullBoardQueues: BullBoardQueues + } + + const queue = bullBoardQueues.get(queueName) + if (!queue) { + return res.status(404).send({ error: 'Queue not found' }) + } else if (queue.readOnlyMode && !skipReadOnlyModeCheck) { + return res.status(405).send({ + error: 'Method not allowed on read only queue', + }) + } + + res.locals.queue = queue + + next() + } +} diff --git a/src/routes/middlewares/wrapAsync.ts b/src/routes/middlewares/wrapAsync.ts new file mode 100644 index 00000000..e88ea8fc --- /dev/null +++ b/src/routes/middlewares/wrapAsync.ts @@ -0,0 +1,6 @@ +import { ParamsDictionary, RequestHandler } from 'express-serve-static-core' + +export const wrapAsync = ( + fn: RequestHandler, +): RequestHandler => async (req, res, next) => + Promise.resolve(fn(req, res, next)).catch(next)