aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/tests/api/runners/runner-common.ts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-07-31 14:34:36 +0200
committerChocobozzz <me@florianbigard.com>2023-08-11 15:02:33 +0200
commit3a4992633ee62d5edfbb484d9c6bcb3cf158489d (patch)
treee4510b39bdac9c318fdb4b47018d08f15368b8f0 /server/tests/api/runners/runner-common.ts
parent04d1da5621d25d59bd5fa1543b725c497bf5d9a8 (diff)
downloadPeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.gz
PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.tar.zst
PeerTube-3a4992633ee62d5edfbb484d9c6bcb3cf158489d.zip
Migrate server to ESM
Sorry for the very big commit that may lead to git log issues and merge conflicts, but it's a major step forward: * Server can be faster at startup because imports() are async and we can easily lazy import big modules * Angular doesn't seem to support ES import (with .js extension), so we had to correctly organize peertube into a monorepo: * Use yarn workspace feature * Use typescript reference projects for dependencies * Shared projects have been moved into "packages", each one is now a node module (with a dedicated package.json/tsconfig.json) * server/tools have been moved into apps/ and is now a dedicated app bundled and published on NPM so users don't have to build peertube cli tools manually * server/tests have been moved into packages/ so we don't compile them every time we want to run the server * Use isolatedModule option: * Had to move from const enum to const (https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums) * Had to explictely specify "type" imports when used in decorators * Prefer tsx (that uses esbuild under the hood) instead of ts-node to load typescript files (tests with mocha or scripts): * To reduce test complexity as esbuild doesn't support decorator metadata, we only test server files that do not import server models * We still build tests files into js files for a faster CI * Remove unmaintained peertube CLI import script * Removed some barrels to speed up execution (less imports)
Diffstat (limited to 'server/tests/api/runners/runner-common.ts')
-rw-r--r--server/tests/api/runners/runner-common.ts743
1 files changed, 0 insertions, 743 deletions
diff --git a/server/tests/api/runners/runner-common.ts b/server/tests/api/runners/runner-common.ts
deleted file mode 100644
index 9b2eb8b27..000000000
--- a/server/tests/api/runners/runner-common.ts
+++ /dev/null
@@ -1,743 +0,0 @@
1/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
2
3import { expect } from 'chai'
4import { wait } from '@shared/core-utils'
5import {
6 HttpStatusCode,
7 Runner,
8 RunnerJob,
9 RunnerJobAdmin,
10 RunnerJobState,
11 RunnerJobVODWebVideoTranscodingPayload,
12 RunnerRegistrationToken
13} from '@shared/models'
14import {
15 cleanupTests,
16 createSingleServer,
17 PeerTubeServer,
18 setAccessTokensToServers,
19 setDefaultVideoChannel,
20 waitJobs
21} from '@shared/server-commands'
22
23describe('Test runner common actions', function () {
24 let server: PeerTubeServer
25 let registrationToken: string
26 let runnerToken: string
27 let jobMaxPriority: string
28
29 before(async function () {
30 this.timeout(120_000)
31
32 server = await createSingleServer(1, {
33 remote_runners: {
34 stalled_jobs: {
35 vod: '5 seconds'
36 }
37 }
38 })
39
40 await setAccessTokensToServers([ server ])
41 await setDefaultVideoChannel([ server ])
42
43 await server.config.enableTranscoding({ hls: true, webVideo: true })
44 await server.config.enableRemoteTranscoding()
45 })
46
47 describe('Managing runner registration tokens', function () {
48 let base: RunnerRegistrationToken[]
49 let registrationTokenToDelete: RunnerRegistrationToken
50
51 it('Should have a default registration token', async function () {
52 const { total, data } = await server.runnerRegistrationTokens.list()
53
54 expect(total).to.equal(1)
55 expect(data).to.have.lengthOf(1)
56
57 const token = data[0]
58 expect(token.id).to.exist
59 expect(token.createdAt).to.exist
60 expect(token.updatedAt).to.exist
61 expect(token.registeredRunnersCount).to.equal(0)
62 expect(token.registrationToken).to.exist
63 })
64
65 it('Should create other registration tokens', async function () {
66 await server.runnerRegistrationTokens.generate()
67 await server.runnerRegistrationTokens.generate()
68
69 const { total, data } = await server.runnerRegistrationTokens.list()
70 expect(total).to.equal(3)
71 expect(data).to.have.lengthOf(3)
72 })
73
74 it('Should list registration tokens', async function () {
75 {
76 const { total, data } = await server.runnerRegistrationTokens.list({ sort: 'createdAt' })
77 expect(total).to.equal(3)
78 expect(data).to.have.lengthOf(3)
79 expect(new Date(data[0].createdAt)).to.be.below(new Date(data[1].createdAt))
80 expect(new Date(data[1].createdAt)).to.be.below(new Date(data[2].createdAt))
81
82 base = data
83
84 registrationTokenToDelete = data[0]
85 registrationToken = data[1].registrationToken
86 }
87
88 {
89 const { total, data } = await server.runnerRegistrationTokens.list({ sort: '-createdAt', start: 2, count: 1 })
90 expect(total).to.equal(3)
91 expect(data).to.have.lengthOf(1)
92 expect(data[0].registrationToken).to.equal(base[0].registrationToken)
93 }
94 })
95
96 it('Should have appropriate registeredRunnersCount for registration tokens', async function () {
97 await server.runners.register({ name: 'to delete 1', registrationToken: registrationTokenToDelete.registrationToken })
98 await server.runners.register({ name: 'to delete 2', registrationToken: registrationTokenToDelete.registrationToken })
99
100 const { data } = await server.runnerRegistrationTokens.list()
101
102 for (const d of data) {
103 if (d.registrationToken === registrationTokenToDelete.registrationToken) {
104 expect(d.registeredRunnersCount).to.equal(2)
105 } else {
106 expect(d.registeredRunnersCount).to.equal(0)
107 }
108 }
109
110 const { data: runners } = await server.runners.list()
111 expect(runners).to.have.lengthOf(2)
112 })
113
114 it('Should delete a registration token', async function () {
115 await server.runnerRegistrationTokens.delete({ id: registrationTokenToDelete.id })
116
117 const { total, data } = await server.runnerRegistrationTokens.list({ sort: 'createdAt' })
118 expect(total).to.equal(2)
119 expect(data).to.have.lengthOf(2)
120
121 for (const d of data) {
122 expect(d.registeredRunnersCount).to.equal(0)
123 expect(d.registrationToken).to.not.equal(registrationTokenToDelete.registrationToken)
124 }
125 })
126
127 it('Should have removed runners of this registration token', async function () {
128 const { data: runners } = await server.runners.list()
129 expect(runners).to.have.lengthOf(0)
130 })
131 })
132
133 describe('Managing runners', function () {
134 let toDelete: Runner
135
136 it('Should not have runners available', async function () {
137 const { total, data } = await server.runners.list()
138
139 expect(data).to.have.lengthOf(0)
140 expect(total).to.equal(0)
141 })
142
143 it('Should register runners', async function () {
144 const now = new Date()
145
146 const result = await server.runners.register({
147 name: 'runner 1',
148 description: 'my super runner 1',
149 registrationToken
150 })
151 expect(result.runnerToken).to.exist
152 runnerToken = result.runnerToken
153
154 await server.runners.register({
155 name: 'runner 2',
156 registrationToken
157 })
158
159 const { total, data } = await server.runners.list({ sort: 'createdAt' })
160 expect(total).to.equal(2)
161 expect(data).to.have.lengthOf(2)
162
163 for (const d of data) {
164 expect(d.id).to.exist
165 expect(d.createdAt).to.exist
166 expect(d.updatedAt).to.exist
167 expect(new Date(d.createdAt)).to.be.above(now)
168 expect(new Date(d.updatedAt)).to.be.above(now)
169 expect(new Date(d.lastContact)).to.be.above(now)
170 expect(d.ip).to.exist
171 }
172
173 expect(data[0].name).to.equal('runner 1')
174 expect(data[0].description).to.equal('my super runner 1')
175
176 expect(data[1].name).to.equal('runner 2')
177 expect(data[1].description).to.be.null
178
179 toDelete = data[1]
180 })
181
182 it('Should list runners', async function () {
183 const { total, data } = await server.runners.list({ sort: '-createdAt', start: 1, count: 1 })
184
185 expect(total).to.equal(2)
186 expect(data).to.have.lengthOf(1)
187 expect(data[0].name).to.equal('runner 1')
188 })
189
190 it('Should delete a runner', async function () {
191 await server.runners.delete({ id: toDelete.id })
192
193 const { total, data } = await server.runners.list()
194
195 expect(total).to.equal(1)
196 expect(data).to.have.lengthOf(1)
197 expect(data[0].name).to.equal('runner 1')
198 })
199
200 it('Should unregister a runner', async function () {
201 const registered = await server.runners.autoRegisterRunner()
202
203 {
204 const { total, data } = await server.runners.list()
205 expect(total).to.equal(2)
206 expect(data).to.have.lengthOf(2)
207 }
208
209 await server.runners.unregister({ runnerToken: registered })
210
211 {
212 const { total, data } = await server.runners.list()
213 expect(total).to.equal(1)
214 expect(data).to.have.lengthOf(1)
215 expect(data[0].name).to.equal('runner 1')
216 }
217 })
218 })
219
220 describe('Managing runner jobs', function () {
221 let jobUUID: string
222 let jobToken: string
223 let lastRunnerContact: Date
224 let failedJob: RunnerJob
225
226 async function checkMainJobState (
227 mainJobState: RunnerJobState,
228 otherJobStates: RunnerJobState[] = [ RunnerJobState.PENDING, RunnerJobState.WAITING_FOR_PARENT_JOB ]
229 ) {
230 const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
231
232 for (const job of data) {
233 if (job.uuid === jobUUID) {
234 expect(job.state.id).to.equal(mainJobState)
235 } else {
236 expect(otherJobStates).to.include(job.state.id)
237 }
238 }
239 }
240
241 function getMainJob () {
242 return server.runnerJobs.getJob({ uuid: jobUUID })
243 }
244
245 describe('List jobs', function () {
246
247 it('Should not have jobs', async function () {
248 const { total, data } = await server.runnerJobs.list()
249
250 expect(data).to.have.lengthOf(0)
251 expect(total).to.equal(0)
252 })
253
254 it('Should upload a video and have available jobs', async function () {
255 await server.videos.quickUpload({ name: 'to transcode' })
256 await waitJobs([ server ])
257
258 const { total, data } = await server.runnerJobs.list()
259
260 expect(data).to.have.lengthOf(10)
261 expect(total).to.equal(10)
262
263 for (const job of data) {
264 expect(job.startedAt).to.not.exist
265 expect(job.finishedAt).to.not.exist
266 expect(job.payload).to.exist
267 expect(job.privatePayload).to.exist
268 }
269
270 const hlsJobs = data.filter(d => d.type === 'vod-hls-transcoding')
271 const webVideoJobs = data.filter(d => d.type === 'vod-web-video-transcoding')
272
273 expect(hlsJobs).to.have.lengthOf(5)
274 expect(webVideoJobs).to.have.lengthOf(5)
275
276 const pendingJobs = data.filter(d => d.state.id === RunnerJobState.PENDING)
277 const waitingJobs = data.filter(d => d.state.id === RunnerJobState.WAITING_FOR_PARENT_JOB)
278
279 expect(pendingJobs).to.have.lengthOf(1)
280 expect(waitingJobs).to.have.lengthOf(9)
281 })
282
283 it('Should upload another video and list/sort jobs', async function () {
284 await server.videos.quickUpload({ name: 'to transcode 2' })
285 await waitJobs([ server ])
286
287 {
288 const { total, data } = await server.runnerJobs.list({ start: 0, count: 30 })
289
290 expect(data).to.have.lengthOf(20)
291 expect(total).to.equal(20)
292
293 jobUUID = data[16].uuid
294 }
295
296 {
297 const { total, data } = await server.runnerJobs.list({ start: 3, count: 1, sort: 'createdAt' })
298 expect(total).to.equal(20)
299
300 expect(data).to.have.lengthOf(1)
301 expect(data[0].uuid).to.equal(jobUUID)
302 }
303
304 {
305 let previousPriority = Infinity
306 const { total, data } = await server.runnerJobs.list({ start: 0, count: 100, sort: '-priority' })
307 expect(total).to.equal(20)
308
309 for (const job of data) {
310 expect(job.priority).to.be.at.most(previousPriority)
311 previousPriority = job.priority
312
313 if (job.state.id === RunnerJobState.PENDING) {
314 jobMaxPriority = job.uuid
315 }
316 }
317 }
318 })
319
320 it('Should search jobs', async function () {
321 {
322 const { total, data } = await server.runnerJobs.list({ search: jobUUID })
323
324 expect(data).to.have.lengthOf(1)
325 expect(total).to.equal(1)
326
327 expect(data[0].uuid).to.equal(jobUUID)
328 }
329
330 {
331 const { total, data } = await server.runnerJobs.list({ search: 'toto' })
332
333 expect(data).to.have.lengthOf(0)
334 expect(total).to.equal(0)
335 }
336
337 {
338 const { total, data } = await server.runnerJobs.list({ search: 'hls' })
339
340 expect(data).to.not.have.lengthOf(0)
341 expect(total).to.not.equal(0)
342
343 for (const job of data) {
344 expect(job.type).to.include('hls')
345 }
346 }
347 })
348
349 it('Should filter jobs', async function () {
350 {
351 const { total, data } = await server.runnerJobs.list({ stateOneOf: [ RunnerJobState.WAITING_FOR_PARENT_JOB ] })
352
353 expect(data).to.not.have.lengthOf(0)
354 expect(total).to.not.equal(0)
355
356 for (const job of data) {
357 expect(job.state.label).to.equal('Waiting for parent job to finish')
358 }
359 }
360
361 {
362 const { total, data } = await server.runnerJobs.list({ stateOneOf: [ RunnerJobState.COMPLETED ] })
363
364 expect(data).to.have.lengthOf(0)
365 expect(total).to.equal(0)
366 }
367 })
368 })
369
370 describe('Accept/update/abort/process a job', function () {
371
372 it('Should request available jobs', async function () {
373 lastRunnerContact = new Date()
374
375 const { availableJobs } = await server.runnerJobs.request({ runnerToken })
376
377 // Only optimize jobs are available
378 expect(availableJobs).to.have.lengthOf(2)
379
380 for (const job of availableJobs) {
381 expect(job.uuid).to.exist
382 expect(job.payload.input).to.exist
383 expect((job.payload as RunnerJobVODWebVideoTranscodingPayload).output).to.exist
384
385 expect((job as RunnerJobAdmin).privatePayload).to.not.exist
386 }
387
388 const hlsJobs = availableJobs.filter(d => d.type === 'vod-hls-transcoding')
389 const webVideoJobs = availableJobs.filter(d => d.type === 'vod-web-video-transcoding')
390
391 expect(hlsJobs).to.have.lengthOf(0)
392 expect(webVideoJobs).to.have.lengthOf(2)
393
394 jobUUID = webVideoJobs[0].uuid
395 })
396
397 it('Should have sorted available jobs by priority', async function () {
398 const { availableJobs } = await server.runnerJobs.request({ runnerToken })
399
400 expect(availableJobs[0].uuid).to.equal(jobMaxPriority)
401 })
402
403 it('Should have last runner contact updated', async function () {
404 await wait(1000)
405
406 const { data } = await server.runners.list({ sort: 'createdAt' })
407 expect(new Date(data[0].lastContact)).to.be.above(lastRunnerContact)
408 })
409
410 it('Should accept a job', async function () {
411 const startedAt = new Date()
412
413 const { job } = await server.runnerJobs.accept({ runnerToken, jobUUID })
414 jobToken = job.jobToken
415
416 const checkProcessingJob = (job: RunnerJob & { jobToken?: string }, fromAccept: boolean) => {
417 expect(job.uuid).to.equal(jobUUID)
418
419 expect(job.type).to.equal('vod-web-video-transcoding')
420 expect(job.state.label).to.equal('Processing')
421 expect(job.state.id).to.equal(RunnerJobState.PROCESSING)
422
423 expect(job.runner).to.exist
424 expect(job.runner.name).to.equal('runner 1')
425 expect(job.runner.description).to.equal('my super runner 1')
426
427 expect(job.progress).to.be.null
428
429 expect(job.startedAt).to.exist
430 expect(new Date(job.startedAt)).to.be.above(startedAt)
431
432 expect(job.finishedAt).to.not.exist
433
434 expect(job.failures).to.equal(0)
435
436 expect(job.payload).to.exist
437
438 if (fromAccept) {
439 expect(job.jobToken).to.exist
440 expect((job as RunnerJobAdmin).privatePayload).to.not.exist
441 } else {
442 expect(job.jobToken).to.not.exist
443 expect((job as RunnerJobAdmin).privatePayload).to.exist
444 }
445 }
446
447 checkProcessingJob(job, true)
448
449 const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
450
451 const processingJob = data.find(j => j.uuid === jobUUID)
452 checkProcessingJob(processingJob, false)
453
454 await checkMainJobState(RunnerJobState.PROCESSING)
455 })
456
457 it('Should update a job', async function () {
458 await server.runnerJobs.update({ runnerToken, jobUUID, jobToken, progress: 53 })
459
460 const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
461
462 for (const job of data) {
463 if (job.state.id === RunnerJobState.PROCESSING) {
464 expect(job.progress).to.equal(53)
465 } else {
466 expect(job.progress).to.be.null
467 }
468 }
469 })
470
471 it('Should abort a job', async function () {
472 await server.runnerJobs.abort({ runnerToken, jobUUID, jobToken, reason: 'for tests' })
473
474 await checkMainJobState(RunnerJobState.PENDING)
475
476 const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
477 for (const job of data) {
478 expect(job.progress).to.be.null
479 }
480 })
481
482 it('Should accept the same job again and post a success', async function () {
483 const { availableJobs } = await server.runnerJobs.request({ runnerToken })
484 expect(availableJobs.find(j => j.uuid === jobUUID)).to.exist
485
486 const { job } = await server.runnerJobs.accept({ runnerToken, jobUUID })
487 jobToken = job.jobToken
488
489 await checkMainJobState(RunnerJobState.PROCESSING)
490
491 const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
492
493 for (const job of data) {
494 expect(job.progress).to.be.null
495 }
496
497 const payload = {
498 videoFile: 'video_short.mp4'
499 }
500
501 await server.runnerJobs.success({ runnerToken, jobUUID, jobToken, payload })
502 })
503
504 it('Should not have available jobs anymore', async function () {
505 await checkMainJobState(RunnerJobState.COMPLETED)
506
507 const job = await getMainJob()
508 expect(job.finishedAt).to.exist
509
510 const { availableJobs } = await server.runnerJobs.request({ runnerToken })
511 expect(availableJobs.find(j => j.uuid === jobUUID)).to.not.exist
512 })
513 })
514
515 describe('Error job', function () {
516
517 it('Should accept another job and post an error', async function () {
518 await server.runnerJobs.cancelAllJobs()
519 await server.videos.quickUpload({ name: 'video' })
520 await waitJobs([ server ])
521
522 const { availableJobs } = await server.runnerJobs.request({ runnerToken })
523 jobUUID = availableJobs[0].uuid
524
525 const { job } = await server.runnerJobs.accept({ runnerToken, jobUUID })
526 jobToken = job.jobToken
527
528 await server.runnerJobs.error({ runnerToken, jobUUID, jobToken, message: 'Error' })
529 })
530
531 it('Should have job failures increased', async function () {
532 const job = await getMainJob()
533 expect(job.state.id).to.equal(RunnerJobState.PENDING)
534 expect(job.failures).to.equal(1)
535 expect(job.error).to.be.null
536 expect(job.progress).to.be.null
537 expect(job.finishedAt).to.not.exist
538 })
539
540 it('Should error a job when job attempts is too big', async function () {
541 for (let i = 0; i < 4; i++) {
542 const { job } = await server.runnerJobs.accept({ runnerToken, jobUUID })
543 jobToken = job.jobToken
544
545 await server.runnerJobs.error({ runnerToken, jobUUID, jobToken, message: 'Error ' + i })
546 }
547
548 const job = await getMainJob()
549 expect(job.failures).to.equal(5)
550 expect(job.state.id).to.equal(RunnerJobState.ERRORED)
551 expect(job.state.label).to.equal('Errored')
552 expect(job.error).to.equal('Error 3')
553 expect(job.progress).to.be.null
554 expect(job.finishedAt).to.exist
555
556 failedJob = job
557 })
558
559 it('Should have failed children jobs too', async function () {
560 const { data } = await server.runnerJobs.list({ count: 50, sort: '-updatedAt' })
561
562 const children = data.filter(j => j.parent?.uuid === failedJob.uuid)
563 expect(children).to.have.lengthOf(9)
564
565 for (const child of children) {
566 expect(child.parent.uuid).to.equal(failedJob.uuid)
567 expect(child.parent.type).to.equal(failedJob.type)
568 expect(child.parent.state.id).to.equal(failedJob.state.id)
569 expect(child.parent.state.label).to.equal(failedJob.state.label)
570
571 expect(child.state.id).to.equal(RunnerJobState.PARENT_ERRORED)
572 expect(child.state.label).to.equal('Parent job failed')
573 }
574 })
575 })
576
577 describe('Cancel', function () {
578
579 it('Should cancel a pending job', async function () {
580 await server.videos.quickUpload({ name: 'video' })
581 await waitJobs([ server ])
582
583 {
584 const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
585
586 const pendingJob = data.find(j => j.state.id === RunnerJobState.PENDING)
587 jobUUID = pendingJob.uuid
588
589 await server.runnerJobs.cancelByAdmin({ jobUUID })
590 }
591
592 {
593 const job = await getMainJob()
594 expect(job.state.id).to.equal(RunnerJobState.CANCELLED)
595 expect(job.state.label).to.equal('Cancelled')
596 }
597
598 {
599 const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
600 const children = data.filter(j => j.parent?.uuid === jobUUID)
601 expect(children).to.have.lengthOf(9)
602
603 for (const child of children) {
604 expect(child.state.id).to.equal(RunnerJobState.PARENT_CANCELLED)
605 }
606 }
607 })
608
609 it('Should cancel an already accepted job and skip success/error', async function () {
610 await server.videos.quickUpload({ name: 'video' })
611 await waitJobs([ server ])
612
613 const { availableJobs } = await server.runnerJobs.request({ runnerToken })
614 jobUUID = availableJobs[0].uuid
615
616 const { job } = await server.runnerJobs.accept({ runnerToken, jobUUID })
617 jobToken = job.jobToken
618
619 await server.runnerJobs.cancelByAdmin({ jobUUID })
620
621 await server.runnerJobs.abort({ runnerToken, jobUUID, jobToken, reason: 'aborted', expectedStatus: HttpStatusCode.NOT_FOUND_404 })
622 })
623 })
624
625 describe('Remove', function () {
626
627 it('Should remove a pending job', async function () {
628 await server.videos.quickUpload({ name: 'video' })
629 await waitJobs([ server ])
630
631 {
632 const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
633
634 const pendingJob = data.find(j => j.state.id === RunnerJobState.PENDING)
635 jobUUID = pendingJob.uuid
636
637 await server.runnerJobs.deleteByAdmin({ jobUUID })
638 }
639
640 {
641 const { data } = await server.runnerJobs.list({ count: 10, sort: '-updatedAt' })
642
643 const parent = data.find(j => j.uuid === jobUUID)
644 expect(parent).to.not.exist
645
646 const children = data.filter(j => j.parent?.uuid === jobUUID)
647 expect(children).to.have.lengthOf(0)
648 }
649 })
650 })
651
652 describe('Stalled jobs', function () {
653
654 it('Should abort stalled jobs', async function () {
655 this.timeout(60000)
656
657 await server.videos.quickUpload({ name: 'video' })
658 await server.videos.quickUpload({ name: 'video' })
659 await waitJobs([ server ])
660
661 const { job: job1 } = await server.runnerJobs.autoAccept({ runnerToken })
662 const { job: stalledJob } = await server.runnerJobs.autoAccept({ runnerToken })
663
664 for (let i = 0; i < 6; i++) {
665 await wait(2000)
666
667 await server.runnerJobs.update({ runnerToken, jobToken: job1.jobToken, jobUUID: job1.uuid })
668 }
669
670 const refreshedJob1 = await server.runnerJobs.getJob({ uuid: job1.uuid })
671 const refreshedStalledJob = await server.runnerJobs.getJob({ uuid: stalledJob.uuid })
672
673 expect(refreshedJob1.state.id).to.equal(RunnerJobState.PROCESSING)
674 expect(refreshedStalledJob.state.id).to.equal(RunnerJobState.PENDING)
675 })
676 })
677
678 describe('Rate limit', function () {
679
680 before(async function () {
681 this.timeout(60000)
682
683 await server.kill()
684
685 await server.run({
686 rates_limit: {
687 api: {
688 max: 10
689 }
690 }
691 })
692 })
693
694 it('Should rate limit an unknown runner, but not a registered one', async function () {
695 this.timeout(60000)
696
697 await server.videos.quickUpload({ name: 'video' })
698 await waitJobs([ server ])
699
700 const { job } = await server.runnerJobs.autoAccept({ runnerToken })
701
702 for (let i = 0; i < 20; i++) {
703 try {
704 await server.runnerJobs.request({ runnerToken })
705 await server.runnerJobs.update({ runnerToken, jobToken: job.jobToken, jobUUID: job.uuid })
706 } catch {}
707 }
708
709 // Invalid
710 {
711 await server.runnerJobs.request({ runnerToken: 'toto', expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 })
712 await server.runnerJobs.update({
713 runnerToken: 'toto',
714 jobToken: job.jobToken,
715 jobUUID: job.uuid,
716 expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429
717 })
718 }
719
720 // Not provided
721 {
722 await server.runnerJobs.request({ runnerToken: undefined, expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429 })
723 await server.runnerJobs.update({
724 runnerToken: undefined,
725 jobToken: job.jobToken,
726 jobUUID: job.uuid,
727 expectedStatus: HttpStatusCode.TOO_MANY_REQUESTS_429
728 })
729 }
730
731 // Registered
732 {
733 await server.runnerJobs.request({ runnerToken })
734 await server.runnerJobs.update({ runnerToken, jobToken: job.jobToken, jobUUID: job.uuid })
735 }
736 })
737 })
738 })
739
740 after(async function () {
741 await cleanupTests([ server ])
742 })
743})