diff options
-rw-r--r-- | server/controllers/api/runners/jobs-files.ts | 10 | ||||
-rw-r--r-- | server/controllers/api/runners/jobs.ts | 14 | ||||
-rw-r--r-- | server/middlewares/validators/runners/jobs.ts | 66 | ||||
-rw-r--r-- | server/tests/api/check-params/runners.ts | 8 |
4 files changed, 53 insertions, 45 deletions
diff --git a/server/controllers/api/runners/jobs-files.ts b/server/controllers/api/runners/jobs-files.ts index cb4eff570..d28f43701 100644 --- a/server/controllers/api/runners/jobs-files.ts +++ b/server/controllers/api/runners/jobs-files.ts | |||
@@ -4,12 +4,12 @@ import { proxifyHLS, proxifyWebVideoFile } from '@server/lib/object-storage' | |||
4 | import { VideoPathManager } from '@server/lib/video-path-manager' | 4 | import { VideoPathManager } from '@server/lib/video-path-manager' |
5 | import { getStudioTaskFilePath } from '@server/lib/video-studio' | 5 | import { getStudioTaskFilePath } from '@server/lib/video-studio' |
6 | import { apiRateLimiter, asyncMiddleware } from '@server/middlewares' | 6 | import { apiRateLimiter, asyncMiddleware } from '@server/middlewares' |
7 | import { jobOfRunnerGetValidator } from '@server/middlewares/validators/runners' | 7 | import { jobOfRunnerGetValidatorFactory } from '@server/middlewares/validators/runners' |
8 | import { | 8 | import { |
9 | runnerJobGetVideoStudioTaskFileValidator, | 9 | runnerJobGetVideoStudioTaskFileValidator, |
10 | runnerJobGetVideoTranscodingFileValidator | 10 | runnerJobGetVideoTranscodingFileValidator |
11 | } from '@server/middlewares/validators/runners/job-files' | 11 | } from '@server/middlewares/validators/runners/job-files' |
12 | import { VideoStorage } from '@shared/models' | 12 | import { RunnerJobState, VideoStorage } from '@shared/models' |
13 | 13 | ||
14 | const lTags = loggerTagsFactory('api', 'runner') | 14 | const lTags = loggerTagsFactory('api', 'runner') |
15 | 15 | ||
@@ -17,21 +17,21 @@ const runnerJobFilesRouter = express.Router() | |||
17 | 17 | ||
18 | runnerJobFilesRouter.post('/jobs/:jobUUID/files/videos/:videoId/max-quality', | 18 | runnerJobFilesRouter.post('/jobs/:jobUUID/files/videos/:videoId/max-quality', |
19 | apiRateLimiter, | 19 | apiRateLimiter, |
20 | asyncMiddleware(jobOfRunnerGetValidator), | 20 | asyncMiddleware(jobOfRunnerGetValidatorFactory([ RunnerJobState.PROCESSING ])), |
21 | asyncMiddleware(runnerJobGetVideoTranscodingFileValidator), | 21 | asyncMiddleware(runnerJobGetVideoTranscodingFileValidator), |
22 | asyncMiddleware(getMaxQualityVideoFile) | 22 | asyncMiddleware(getMaxQualityVideoFile) |
23 | ) | 23 | ) |
24 | 24 | ||
25 | runnerJobFilesRouter.post('/jobs/:jobUUID/files/videos/:videoId/previews/max-quality', | 25 | runnerJobFilesRouter.post('/jobs/:jobUUID/files/videos/:videoId/previews/max-quality', |
26 | apiRateLimiter, | 26 | apiRateLimiter, |
27 | asyncMiddleware(jobOfRunnerGetValidator), | 27 | asyncMiddleware(jobOfRunnerGetValidatorFactory([ RunnerJobState.PROCESSING ])), |
28 | asyncMiddleware(runnerJobGetVideoTranscodingFileValidator), | 28 | asyncMiddleware(runnerJobGetVideoTranscodingFileValidator), |
29 | getMaxQualityVideoPreview | 29 | getMaxQualityVideoPreview |
30 | ) | 30 | ) |
31 | 31 | ||
32 | runnerJobFilesRouter.post('/jobs/:jobUUID/files/videos/:videoId/studio/task-files/:filename', | 32 | runnerJobFilesRouter.post('/jobs/:jobUUID/files/videos/:videoId/studio/task-files/:filename', |
33 | apiRateLimiter, | 33 | apiRateLimiter, |
34 | asyncMiddleware(jobOfRunnerGetValidator), | 34 | asyncMiddleware(jobOfRunnerGetValidatorFactory([ RunnerJobState.PROCESSING ])), |
35 | asyncMiddleware(runnerJobGetVideoTranscodingFileValidator), | 35 | asyncMiddleware(runnerJobGetVideoTranscodingFileValidator), |
36 | runnerJobGetVideoStudioTaskFileValidator, | 36 | runnerJobGetVideoStudioTaskFileValidator, |
37 | getVideoStudioTaskFile | 37 | getVideoStudioTaskFile |
diff --git a/server/controllers/api/runners/jobs.ts b/server/controllers/api/runners/jobs.ts index 5d687e689..be5911b53 100644 --- a/server/controllers/api/runners/jobs.ts +++ b/server/controllers/api/runners/jobs.ts | |||
@@ -22,7 +22,7 @@ import { | |||
22 | cancelRunnerJobValidator, | 22 | cancelRunnerJobValidator, |
23 | errorRunnerJobValidator, | 23 | errorRunnerJobValidator, |
24 | getRunnerFromTokenValidator, | 24 | getRunnerFromTokenValidator, |
25 | jobOfRunnerGetValidator, | 25 | jobOfRunnerGetValidatorFactory, |
26 | runnerJobGetValidator, | 26 | runnerJobGetValidator, |
27 | successRunnerJobValidator, | 27 | successRunnerJobValidator, |
28 | updateRunnerJobValidator | 28 | updateRunnerJobValidator |
@@ -85,7 +85,7 @@ runnerJobsRouter.post('/jobs/:jobUUID/accept', | |||
85 | 85 | ||
86 | runnerJobsRouter.post('/jobs/:jobUUID/abort', | 86 | runnerJobsRouter.post('/jobs/:jobUUID/abort', |
87 | apiRateLimiter, | 87 | apiRateLimiter, |
88 | asyncMiddleware(jobOfRunnerGetValidator), | 88 | asyncMiddleware(jobOfRunnerGetValidatorFactory([ RunnerJobState.PROCESSING ])), |
89 | abortRunnerJobValidator, | 89 | abortRunnerJobValidator, |
90 | asyncMiddleware(abortRunnerJob) | 90 | asyncMiddleware(abortRunnerJob) |
91 | ) | 91 | ) |
@@ -93,13 +93,13 @@ runnerJobsRouter.post('/jobs/:jobUUID/abort', | |||
93 | runnerJobsRouter.post('/jobs/:jobUUID/update', | 93 | runnerJobsRouter.post('/jobs/:jobUUID/update', |
94 | runnerJobUpdateVideoFiles, | 94 | runnerJobUpdateVideoFiles, |
95 | apiRateLimiter, // Has to be after multer middleware to parse runner token | 95 | apiRateLimiter, // Has to be after multer middleware to parse runner token |
96 | asyncMiddleware(jobOfRunnerGetValidator), | 96 | asyncMiddleware(jobOfRunnerGetValidatorFactory([ RunnerJobState.PROCESSING, RunnerJobState.COMPLETING, RunnerJobState.COMPLETED ])), |
97 | updateRunnerJobValidator, | 97 | updateRunnerJobValidator, |
98 | asyncMiddleware(updateRunnerJobController) | 98 | asyncMiddleware(updateRunnerJobController) |
99 | ) | 99 | ) |
100 | 100 | ||
101 | runnerJobsRouter.post('/jobs/:jobUUID/error', | 101 | runnerJobsRouter.post('/jobs/:jobUUID/error', |
102 | asyncMiddleware(jobOfRunnerGetValidator), | 102 | asyncMiddleware(jobOfRunnerGetValidatorFactory([ RunnerJobState.PROCESSING ])), |
103 | errorRunnerJobValidator, | 103 | errorRunnerJobValidator, |
104 | asyncMiddleware(errorRunnerJob) | 104 | asyncMiddleware(errorRunnerJob) |
105 | ) | 105 | ) |
@@ -107,7 +107,7 @@ runnerJobsRouter.post('/jobs/:jobUUID/error', | |||
107 | runnerJobsRouter.post('/jobs/:jobUUID/success', | 107 | runnerJobsRouter.post('/jobs/:jobUUID/success', |
108 | postRunnerJobSuccessVideoFiles, | 108 | postRunnerJobSuccessVideoFiles, |
109 | apiRateLimiter, // Has to be after multer middleware to parse runner token | 109 | apiRateLimiter, // Has to be after multer middleware to parse runner token |
110 | asyncMiddleware(jobOfRunnerGetValidator), | 110 | asyncMiddleware(jobOfRunnerGetValidatorFactory([ RunnerJobState.PROCESSING ])), |
111 | successRunnerJobValidator, | 111 | successRunnerJobValidator, |
112 | asyncMiddleware(postRunnerJobSuccess) | 112 | asyncMiddleware(postRunnerJobSuccess) |
113 | ) | 113 | ) |
@@ -272,6 +272,10 @@ async function updateRunnerJobController (req: express.Request, res: express.Res | |||
272 | const runner = runnerJob.Runner | 272 | const runner = runnerJob.Runner |
273 | const body: RunnerJobUpdateBody = req.body | 273 | const body: RunnerJobUpdateBody = req.body |
274 | 274 | ||
275 | if (runnerJob.state === RunnerJobState.COMPLETING || runnerJob.state === RunnerJobState.COMPLETED) { | ||
276 | return res.sendStatus(HttpStatusCode.NO_CONTENT_204) | ||
277 | } | ||
278 | |||
275 | const payloadBuilder = jobUpdateBuilders[runnerJob.type] | 279 | const payloadBuilder = jobUpdateBuilders[runnerJob.type] |
276 | const updatePayload = payloadBuilder | 280 | const updatePayload = payloadBuilder |
277 | ? payloadBuilder(body.payload, req.files as UploadFiles) | 281 | ? payloadBuilder(body.payload, req.files as UploadFiles) |
diff --git a/server/middlewares/validators/runners/jobs.ts b/server/middlewares/validators/runners/jobs.ts index 75cc0bdbb..384b209ba 100644 --- a/server/middlewares/validators/runners/jobs.ts +++ b/server/middlewares/validators/runners/jobs.ts | |||
@@ -159,44 +159,46 @@ export const runnerJobGetValidator = [ | |||
159 | } | 159 | } |
160 | ] | 160 | ] |
161 | 161 | ||
162 | export const jobOfRunnerGetValidator = [ | 162 | export function jobOfRunnerGetValidatorFactory (allowedStates: RunnerJobState[]) { |
163 | param('jobUUID').custom(isUUIDValid), | 163 | return [ |
164 | param('jobUUID').custom(isUUIDValid), | ||
164 | 165 | ||
165 | body('runnerToken').custom(isRunnerTokenValid), | 166 | body('runnerToken').custom(isRunnerTokenValid), |
166 | body('jobToken').custom(isRunnerJobTokenValid), | 167 | body('jobToken').custom(isRunnerJobTokenValid), |
167 | 168 | ||
168 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | 169 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { |
169 | if (areValidationErrors(req, res, { tags })) return cleanUpReqFiles(req) | 170 | if (areValidationErrors(req, res, { tags })) return cleanUpReqFiles(req) |
170 | 171 | ||
171 | const runnerJob = await RunnerJobModel.loadByRunnerAndJobTokensWithRunner({ | 172 | const runnerJob = await RunnerJobModel.loadByRunnerAndJobTokensWithRunner({ |
172 | uuid: req.params.jobUUID, | 173 | uuid: req.params.jobUUID, |
173 | runnerToken: req.body.runnerToken, | 174 | runnerToken: req.body.runnerToken, |
174 | jobToken: req.body.jobToken | 175 | jobToken: req.body.jobToken |
175 | }) | 176 | }) |
176 | 177 | ||
177 | if (!runnerJob) { | 178 | if (!runnerJob) { |
178 | cleanUpReqFiles(req) | 179 | cleanUpReqFiles(req) |
179 | 180 | ||
180 | return res.fail({ | 181 | return res.fail({ |
181 | status: HttpStatusCode.NOT_FOUND_404, | 182 | status: HttpStatusCode.NOT_FOUND_404, |
182 | message: 'Unknown runner job', | 183 | message: 'Unknown runner job', |
183 | tags | 184 | tags |
184 | }) | 185 | }) |
185 | } | 186 | } |
186 | 187 | ||
187 | if (runnerJob.state !== RunnerJobState.PROCESSING) { | 188 | if (!allowedStates.includes(runnerJob.state)) { |
188 | cleanUpReqFiles(req) | 189 | cleanUpReqFiles(req) |
189 | 190 | ||
190 | return res.fail({ | 191 | return res.fail({ |
191 | status: HttpStatusCode.BAD_REQUEST_400, | 192 | status: HttpStatusCode.BAD_REQUEST_400, |
192 | type: ServerErrorCode.RUNNER_JOB_NOT_IN_PROCESSING_STATE, | 193 | type: ServerErrorCode.RUNNER_JOB_NOT_IN_PROCESSING_STATE, |
193 | message: 'Job is not in "processing" state', | 194 | message: 'Job is not in "processing" state', |
194 | tags | 195 | tags |
195 | }) | 196 | }) |
196 | } | 197 | } |
197 | 198 | ||
198 | res.locals.runnerJob = runnerJob | 199 | res.locals.runnerJob = runnerJob |
199 | 200 | ||
200 | return next() | 201 | return next() |
201 | } | 202 | } |
202 | ] | 203 | ] |
204 | } | ||
diff --git a/server/tests/api/check-params/runners.ts b/server/tests/api/check-params/runners.ts index 7d70c412e..9112ff716 100644 --- a/server/tests/api/check-params/runners.ts +++ b/server/tests/api/check-params/runners.ts | |||
@@ -41,6 +41,7 @@ describe('Test managing runners', function () { | |||
41 | let completedJobToken: string | 41 | let completedJobToken: string |
42 | let completedJobUUID: string | 42 | let completedJobUUID: string |
43 | 43 | ||
44 | let cancelledJobToken: string | ||
44 | let cancelledJobUUID: string | 45 | let cancelledJobUUID: string |
45 | 46 | ||
46 | before(async function () { | 47 | before(async function () { |
@@ -86,6 +87,7 @@ describe('Test managing runners', function () { | |||
86 | 87 | ||
87 | { | 88 | { |
88 | const { job } = await server.runnerJobs.autoAccept({ runnerToken }) | 89 | const { job } = await server.runnerJobs.autoAccept({ runnerToken }) |
90 | cancelledJobToken = job.jobToken | ||
89 | cancelledJobUUID = job.uuid | 91 | cancelledJobUUID = job.uuid |
90 | await server.runnerJobs.cancelByAdmin({ jobUUID: cancelledJobUUID }) | 92 | await server.runnerJobs.cancelByAdmin({ jobUUID: cancelledJobUUID }) |
91 | } | 93 | } |
@@ -639,10 +641,10 @@ describe('Test managing runners', function () { | |||
639 | 641 | ||
640 | it('Should fail with a job not in processing state', async function () { | 642 | it('Should fail with a job not in processing state', async function () { |
641 | await server.runnerJobs.update({ | 643 | await server.runnerJobs.update({ |
642 | jobUUID: completedJobUUID, | 644 | jobUUID: cancelledJobUUID, |
643 | jobToken: completedJobToken, | 645 | jobToken: cancelledJobToken, |
644 | runnerToken, | 646 | runnerToken, |
645 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | 647 | expectedStatus: HttpStatusCode.NOT_FOUND_404 |
646 | }) | 648 | }) |
647 | }) | 649 | }) |
648 | }) | 650 | }) |