refactor: prepare the code to handle task abstraction at execute
[poolifier.git] / tests / pools / selection-strategies / selection-strategies.test.js
1 const { expect } = require('expect')
2 const {
3 WorkerChoiceStrategies,
4 DynamicThreadPool,
5 FixedThreadPool,
6 FixedClusterPool
7 } = require('../../../lib/index')
8
9 describe('Selection strategies test suite', () => {
10 const min = 0
11 const max = 3
12
13 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
14 expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN')
15 expect(WorkerChoiceStrategies.LESS_USED).toBe('LESS_USED')
16 expect(WorkerChoiceStrategies.LESS_BUSY).toBe('LESS_BUSY')
17 expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE')
18 expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe(
19 'WEIGHTED_ROUND_ROBIN'
20 )
21 })
22
23 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
24 const pool = new DynamicThreadPool(
25 min,
26 max,
27 './tests/worker-files/thread/testWorker.js'
28 )
29 expect(pool.opts.workerChoiceStrategy).toBe(
30 WorkerChoiceStrategies.ROUND_ROBIN
31 )
32 // We need to clean up the resources after our test
33 await pool.destroy()
34 })
35
36 it('Verify ROUND_ROBIN strategy is taken at pool creation', async () => {
37 const pool = new FixedThreadPool(
38 max,
39 './tests/worker-files/thread/testWorker.js',
40 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
41 )
42 expect(pool.opts.workerChoiceStrategy).toBe(
43 WorkerChoiceStrategies.ROUND_ROBIN
44 )
45 expect(
46 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
47 WorkerChoiceStrategies.ROUND_ROBIN
48 ).nextWorkerNodeId
49 ).toBe(0)
50 // We need to clean up the resources after our test
51 await pool.destroy()
52 })
53
54 it('Verify ROUND_ROBIN strategy can be set after pool creation', async () => {
55 const pool = new DynamicThreadPool(
56 min,
57 max,
58 './tests/worker-files/thread/testWorker.js'
59 )
60 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
61 expect(pool.opts.workerChoiceStrategy).toBe(
62 WorkerChoiceStrategies.ROUND_ROBIN
63 )
64 // We need to clean up the resources after our test
65 await pool.destroy()
66 })
67
68 it('Verify ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
69 let pool = new FixedThreadPool(
70 max,
71 './tests/worker-files/thread/testWorker.js'
72 )
73 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
74 expect(
75 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
76 ).toBe(false)
77 expect(
78 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
79 ).toBe(false)
80 expect(
81 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
82 ).toBe(false)
83 await pool.destroy()
84 pool = new DynamicThreadPool(
85 min,
86 max,
87 './tests/worker-files/thread/testWorker.js'
88 )
89 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
90 expect(
91 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
92 ).toBe(false)
93 expect(
94 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
95 ).toBe(false)
96 expect(
97 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
98 ).toBe(false)
99 // We need to clean up the resources after our test
100 await pool.destroy()
101 })
102
103 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
104 const pool = new FixedThreadPool(
105 max,
106 './tests/worker-files/thread/testWorker.js',
107 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
108 )
109 expect(pool.opts.workerChoiceStrategy).toBe(
110 WorkerChoiceStrategies.ROUND_ROBIN
111 )
112 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
113 const promises = []
114 for (let i = 0; i < max * 2; i++) {
115 promises.push(pool.execute())
116 }
117 await Promise.all(promises)
118 // We need to clean up the resources after our test
119 await pool.destroy()
120 })
121
122 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
123 const pool = new DynamicThreadPool(
124 min,
125 max,
126 './tests/worker-files/thread/testWorker.js',
127 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
128 )
129 expect(pool.opts.workerChoiceStrategy).toBe(
130 WorkerChoiceStrategies.ROUND_ROBIN
131 )
132 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
133 const promises = []
134 for (let i = 0; i < max * 2; i++) {
135 promises.push(pool.execute())
136 }
137 await Promise.all(promises)
138 // We need to clean up the resources after our test
139 await pool.destroy()
140 })
141
142 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
143 let pool = new FixedClusterPool(
144 max,
145 './tests/worker-files/cluster/testWorker.js'
146 )
147 let results = new Set()
148 for (let i = 0; i < max; i++) {
149 results.add(pool.chooseWorkerNode()[1].worker.id)
150 }
151 expect(results.size).toBe(max)
152 await pool.destroy()
153 pool = new FixedThreadPool(max, './tests/worker-files/thread/testWorker.js')
154 results = new Set()
155 for (let i = 0; i < max; i++) {
156 results.add(pool.chooseWorkerNode()[1].worker.threadId)
157 }
158 expect(results.size).toBe(max)
159 await pool.destroy()
160 })
161
162 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
163 let pool = new FixedThreadPool(
164 max,
165 './tests/worker-files/thread/testWorker.js',
166 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
167 )
168 expect(
169 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
170 WorkerChoiceStrategies.ROUND_ROBIN
171 ).nextWorkerNodeId
172 ).toBeDefined()
173 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
174 expect(
175 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
176 WorkerChoiceStrategies.ROUND_ROBIN
177 ).nextWorkerNodeId
178 ).toBe(0)
179 await pool.destroy()
180 pool = new DynamicThreadPool(
181 min,
182 max,
183 './tests/worker-files/thread/testWorker.js',
184 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
185 )
186 expect(
187 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
188 WorkerChoiceStrategies.ROUND_ROBIN
189 ).nextWorkerNodeId
190 ).toBeDefined()
191 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
192 expect(
193 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
194 WorkerChoiceStrategies.ROUND_ROBIN
195 ).nextWorkerNodeId
196 ).toBe(0)
197 // We need to clean up the resources after our test
198 await pool.destroy()
199 })
200
201 it('Verify LESS_USED strategy is taken at pool creation', async () => {
202 const pool = new FixedThreadPool(
203 max,
204 './tests/worker-files/thread/testWorker.js',
205 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED }
206 )
207 expect(pool.opts.workerChoiceStrategy).toBe(
208 WorkerChoiceStrategies.LESS_USED
209 )
210 // We need to clean up the resources after our test
211 await pool.destroy()
212 })
213
214 it('Verify LESS_USED strategy can be set after pool creation', async () => {
215 const pool = new FixedThreadPool(
216 max,
217 './tests/worker-files/thread/testWorker.js'
218 )
219 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_USED)
220 expect(pool.opts.workerChoiceStrategy).toBe(
221 WorkerChoiceStrategies.LESS_USED
222 )
223 // We need to clean up the resources after our test
224 await pool.destroy()
225 })
226
227 it('Verify LESS_USED strategy default tasks usage statistics requirements', async () => {
228 let pool = new FixedThreadPool(
229 max,
230 './tests/worker-files/thread/testWorker.js'
231 )
232 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_USED)
233 expect(
234 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
235 ).toBe(false)
236 expect(
237 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
238 ).toBe(false)
239 expect(
240 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
241 ).toBe(false)
242 await pool.destroy()
243 pool = new DynamicThreadPool(
244 min,
245 max,
246 './tests/worker-files/thread/testWorker.js'
247 )
248 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_USED)
249 expect(
250 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
251 ).toBe(false)
252 expect(
253 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
254 ).toBe(false)
255 expect(
256 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
257 ).toBe(false)
258 // We need to clean up the resources after our test
259 await pool.destroy()
260 })
261
262 it('Verify LESS_USED strategy can be run in a fixed pool', async () => {
263 const pool = new FixedThreadPool(
264 max,
265 './tests/worker-files/thread/testWorker.js',
266 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED }
267 )
268 // TODO: Create a better test to cover `LessUsedWorkerChoiceStrategy#choose`
269 const promises = []
270 for (let i = 0; i < max * 2; i++) {
271 promises.push(pool.execute())
272 }
273 await Promise.all(promises)
274 // We need to clean up the resources after our test
275 await pool.destroy()
276 })
277
278 it('Verify LESS_USED strategy can be run in a dynamic pool', async () => {
279 const pool = new DynamicThreadPool(
280 min,
281 max,
282 './tests/worker-files/thread/testWorker.js',
283 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED }
284 )
285 // TODO: Create a better test to cover `LessUsedWorkerChoiceStrategy#choose`
286 const promises = []
287 for (let i = 0; i < max * 2; i++) {
288 promises.push(pool.execute())
289 }
290 await Promise.all(promises)
291 // We need to clean up the resources after our test
292 await pool.destroy()
293 })
294
295 it('Verify LESS_BUSY strategy is taken at pool creation', async () => {
296 const pool = new FixedThreadPool(
297 max,
298 './tests/worker-files/thread/testWorker.js',
299 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_BUSY }
300 )
301 expect(pool.opts.workerChoiceStrategy).toBe(
302 WorkerChoiceStrategies.LESS_BUSY
303 )
304 // We need to clean up the resources after our test
305 await pool.destroy()
306 })
307
308 it('Verify LESS_BUSY strategy can be set after pool creation', async () => {
309 const pool = new FixedThreadPool(
310 max,
311 './tests/worker-files/thread/testWorker.js'
312 )
313 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_BUSY)
314 expect(pool.opts.workerChoiceStrategy).toBe(
315 WorkerChoiceStrategies.LESS_BUSY
316 )
317 // We need to clean up the resources after our test
318 await pool.destroy()
319 })
320
321 it('Verify LESS_BUSY strategy default tasks usage statistics requirements', async () => {
322 let pool = new FixedThreadPool(
323 max,
324 './tests/worker-files/thread/testWorker.js'
325 )
326 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_BUSY)
327 expect(
328 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
329 ).toBe(true)
330 expect(
331 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
332 ).toBe(false)
333 expect(
334 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
335 ).toBe(false)
336 await pool.destroy()
337 pool = new DynamicThreadPool(
338 min,
339 max,
340 './tests/worker-files/thread/testWorker.js'
341 )
342 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_BUSY)
343 expect(
344 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
345 ).toBe(true)
346 expect(
347 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
348 ).toBe(false)
349 expect(
350 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
351 ).toBe(false)
352 // We need to clean up the resources after our test
353 await pool.destroy()
354 })
355
356 it('Verify LESS_BUSY strategy can be run in a fixed pool', async () => {
357 const pool = new FixedThreadPool(
358 max,
359 './tests/worker-files/thread/testWorker.js',
360 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_BUSY }
361 )
362 // TODO: Create a better test to cover `LessBusyWorkerChoiceStrategy#choose`
363 const promises = []
364 for (let i = 0; i < max * 2; i++) {
365 promises.push(pool.execute())
366 }
367 await Promise.all(promises)
368 // We need to clean up the resources after our test
369 await pool.destroy()
370 })
371
372 it('Verify LESS_BUSY strategy can be run in a dynamic pool', async () => {
373 const pool = new DynamicThreadPool(
374 min,
375 max,
376 './tests/worker-files/thread/testWorker.js',
377 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_BUSY }
378 )
379 // TODO: Create a better test to cover `LessBusyWorkerChoiceStrategy#choose`
380 const promises = []
381 for (let i = 0; i < max * 2; i++) {
382 promises.push(pool.execute())
383 }
384 await Promise.all(promises)
385 // We need to clean up the resources after our test
386 await pool.destroy()
387 })
388
389 it('Verify FAIR_SHARE strategy is taken at pool creation', async () => {
390 const pool = new FixedThreadPool(
391 max,
392 './tests/worker-files/thread/testWorker.js',
393 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
394 )
395 expect(pool.opts.workerChoiceStrategy).toBe(
396 WorkerChoiceStrategies.FAIR_SHARE
397 )
398 for (const workerNodeKey of pool.workerChoiceStrategyContext.workerChoiceStrategies
399 .get(WorkerChoiceStrategies.FAIR_SHARE)
400 .workerLastVirtualTaskTimestamp.keys()) {
401 expect(
402 pool.workerChoiceStrategyContext.workerChoiceStrategies
403 .get(WorkerChoiceStrategies.FAIR_SHARE)
404 .workerLastVirtualTaskTimestamp.get(workerNodeKey).start
405 ).toBe(0)
406 expect(
407 pool.workerChoiceStrategyContext.workerChoiceStrategies
408 .get(WorkerChoiceStrategies.FAIR_SHARE)
409 .workerLastVirtualTaskTimestamp.get(workerNodeKey).end
410 ).toBe(0)
411 }
412 // We need to clean up the resources after our test
413 await pool.destroy()
414 })
415
416 it('Verify FAIR_SHARE strategy can be set after pool creation', async () => {
417 const pool = new FixedThreadPool(
418 max,
419 './tests/worker-files/thread/testWorker.js'
420 )
421 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
422 expect(pool.opts.workerChoiceStrategy).toBe(
423 WorkerChoiceStrategies.FAIR_SHARE
424 )
425 // We need to clean up the resources after our test
426 await pool.destroy()
427 })
428
429 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
430 let pool = new FixedThreadPool(
431 max,
432 './tests/worker-files/thread/testWorker.js'
433 )
434 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
435 expect(
436 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
437 ).toBe(true)
438 expect(
439 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
440 ).toBe(true)
441 expect(
442 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
443 ).toBe(false)
444 await pool.destroy()
445 pool = new DynamicThreadPool(
446 min,
447 max,
448 './tests/worker-files/thread/testWorker.js'
449 )
450 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
451 expect(
452 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
453 ).toBe(true)
454 expect(
455 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
456 ).toBe(true)
457 expect(
458 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
459 ).toBe(false)
460 // We need to clean up the resources after our test
461 await pool.destroy()
462 })
463
464 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
465 const pool = new FixedThreadPool(
466 max,
467 './tests/worker-files/thread/testWorker.js',
468 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
469 )
470 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
471 const promises = []
472 for (let i = 0; i < max * 2; i++) {
473 promises.push(pool.execute())
474 }
475 await Promise.all(promises)
476 expect(
477 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
478 WorkerChoiceStrategies.FAIR_SHARE
479 ).workerLastVirtualTaskTimestamp.size
480 ).toBe(pool.workerNodes.length)
481 // We need to clean up the resources after our test
482 await pool.destroy()
483 })
484
485 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
486 const pool = new DynamicThreadPool(
487 min,
488 max,
489 './tests/worker-files/thread/testWorker.js',
490 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
491 )
492 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
493 const promises = []
494 const maxMultiplier = 2
495 for (let i = 0; i < max * maxMultiplier; i++) {
496 promises.push(pool.execute())
497 }
498 await Promise.all(promises)
499 // if (process.platform !== 'win32') {
500 // expect(
501 // pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
502 // WorkerChoiceStrategies.FAIR_SHARE
503 // ).workerLastVirtualTaskTimestamp.size
504 // ).toBe(pool.workerNodes.length)
505 // }
506 // We need to clean up the resources after our test
507 await pool.destroy()
508 })
509
510 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
511 let pool = new FixedThreadPool(
512 max,
513 './tests/worker-files/thread/testWorker.js'
514 )
515 expect(
516 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
517 WorkerChoiceStrategies.FAIR_SHARE
518 ).workerLastVirtualTaskTimestamp
519 ).toBeDefined()
520 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
521 for (const workerNodeKey of pool.workerChoiceStrategyContext.workerChoiceStrategies
522 .get(WorkerChoiceStrategies.FAIR_SHARE)
523 .workerLastVirtualTaskTimestamp.keys()) {
524 expect(
525 pool.workerChoiceStrategyContext.workerChoiceStrategies
526 .get(WorkerChoiceStrategies.FAIR_SHARE)
527 .workerLastVirtualTaskTimestamp.get(workerNodeKey).start
528 ).toBe(0)
529 expect(
530 pool.workerChoiceStrategyContext.workerChoiceStrategies
531 .get(WorkerChoiceStrategies.FAIR_SHARE)
532 .workerLastVirtualTaskTimestamp.get(workerNodeKey).end
533 ).toBe(0)
534 }
535 await pool.destroy()
536 pool = new DynamicThreadPool(
537 min,
538 max,
539 './tests/worker-files/thread/testWorker.js'
540 )
541 expect(
542 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
543 WorkerChoiceStrategies.FAIR_SHARE
544 ).workerLastVirtualTaskTimestamp
545 ).toBeDefined()
546 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
547 for (const workerNodeKey of pool.workerChoiceStrategyContext.workerChoiceStrategies
548 .get(WorkerChoiceStrategies.FAIR_SHARE)
549 .workerLastVirtualTaskTimestamp.keys()) {
550 expect(
551 pool.workerChoiceStrategyContext.workerChoiceStrategies
552 .get(WorkerChoiceStrategies.FAIR_SHARE)
553 .workerLastVirtualTaskTimestamp.get(workerNodeKey).start
554 ).toBe(0)
555 expect(
556 pool.workerChoiceStrategyContext.workerChoiceStrategies
557 .get(WorkerChoiceStrategies.FAIR_SHARE)
558 .workerLastVirtualTaskTimestamp.get(workerNodeKey).end
559 ).toBe(0)
560 }
561 // We need to clean up the resources after our test
562 await pool.destroy()
563 })
564
565 it('Verify WEIGHTED_ROUND_ROBIN strategy is taken at pool creation', async () => {
566 const pool = new FixedThreadPool(
567 max,
568 './tests/worker-files/thread/testWorker.js',
569 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
570 )
571 expect(pool.opts.workerChoiceStrategy).toBe(
572 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
573 )
574 expect(
575 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
576 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
577 ).currentWorkerNodeId
578 ).toBe(0)
579 expect(
580 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
581 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
582 ).defaultWorkerWeight
583 ).toBeGreaterThan(0)
584 for (const workerNodeKey of pool.workerChoiceStrategyContext.workerChoiceStrategies
585 .get(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
586 .workersTaskRunTime.keys()) {
587 expect(
588 pool.workerChoiceStrategyContext.workerChoiceStrategies
589 .get(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
590 .workersTaskRunTime.get(workerNodeKey).weight
591 ).toBeGreaterThan(0)
592 expect(
593 pool.workerChoiceStrategyContext.workerChoiceStrategies
594 .get(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
595 .workersTaskRunTime.get(workerNodeKey).runTime
596 ).toBe(0)
597 }
598 // We need to clean up the resources after our test
599 await pool.destroy()
600 })
601
602 it('Verify WEIGHTED_ROUND_ROBIN strategy can be set after pool creation', async () => {
603 const pool = new FixedThreadPool(
604 max,
605 './tests/worker-files/thread/testWorker.js'
606 )
607 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
608 expect(pool.opts.workerChoiceStrategy).toBe(
609 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
610 )
611 // We need to clean up the resources after our test
612 await pool.destroy()
613 })
614
615 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
616 let pool = new FixedThreadPool(
617 max,
618 './tests/worker-files/thread/testWorker.js'
619 )
620 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
621 expect(
622 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
623 ).toBe(true)
624 expect(
625 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
626 ).toBe(true)
627 expect(
628 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
629 ).toBe(false)
630 await pool.destroy()
631 pool = new DynamicThreadPool(
632 min,
633 max,
634 './tests/worker-files/thread/testWorker.js'
635 )
636 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
637 expect(
638 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
639 ).toBe(true)
640 expect(
641 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
642 ).toBe(true)
643 expect(
644 pool.workerChoiceStrategyContext.getRequiredStatistics().medRunTime
645 ).toBe(false)
646 // We need to clean up the resources after our test
647 await pool.destroy()
648 })
649
650 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
651 const pool = new FixedThreadPool(
652 max,
653 './tests/worker-files/thread/testWorker.js',
654 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
655 )
656 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
657 const promises = []
658 for (let i = 0; i < max * 2; i++) {
659 promises.push(pool.execute())
660 }
661 await Promise.all(promises)
662 expect(
663 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
664 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
665 ).workersTaskRunTime.size
666 ).toBe(pool.workerNodes.length)
667 // We need to clean up the resources after our test
668 await pool.destroy()
669 })
670
671 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
672 const pool = new DynamicThreadPool(
673 min,
674 max,
675 './tests/worker-files/thread/testWorker.js',
676 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
677 )
678 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
679 const promises = []
680 const maxMultiplier =
681 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
682 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
683 ).defaultWorkerWeight * 50
684 for (let i = 0; i < max * maxMultiplier; i++) {
685 promises.push(pool.execute())
686 }
687 await Promise.all(promises)
688 if (process.platform !== 'win32') {
689 expect(
690 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
691 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
692 ).workersTaskRunTime.size
693 ).toBe(pool.workerNodes.length)
694 }
695 // We need to clean up the resources after our test
696 await pool.destroy()
697 })
698
699 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
700 let pool = new FixedThreadPool(
701 max,
702 './tests/worker-files/thread/testWorker.js'
703 )
704 expect(
705 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
706 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
707 ).currentWorkerNodeId
708 ).toBeDefined()
709 expect(
710 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
711 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
712 ).defaultWorkerWeight
713 ).toBeDefined()
714 expect(
715 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
716 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
717 ).workersTaskRunTime
718 ).toBeDefined()
719 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
720 expect(
721 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
722 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
723 ).currentWorkerNodeId
724 ).toBe(0)
725 expect(
726 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
727 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
728 ).defaultWorkerWeight
729 ).toBeGreaterThan(0)
730 for (const workerNodeKey of pool.workerChoiceStrategyContext.workerChoiceStrategies
731 .get(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
732 .workersTaskRunTime.keys()) {
733 expect(
734 pool.workerChoiceStrategyContext.workerChoiceStrategies
735 .get(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
736 .workersTaskRunTime.get(workerNodeKey).runTime
737 ).toBe(0)
738 }
739 await pool.destroy()
740 pool = new DynamicThreadPool(
741 min,
742 max,
743 './tests/worker-files/thread/testWorker.js'
744 )
745 expect(
746 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
747 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
748 ).currentWorkerNodeId
749 ).toBeDefined()
750 expect(
751 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
752 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
753 ).defaultWorkerWeight
754 ).toBeDefined()
755 expect(
756 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
757 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
758 ).workersTaskRunTime
759 ).toBeDefined()
760 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
761 expect(
762 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
763 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
764 ).currentWorkerNodeId
765 ).toBe(0)
766 expect(
767 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
768 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
769 ).defaultWorkerWeight
770 ).toBeGreaterThan(0)
771 for (const workerNodeKey of pool.workerChoiceStrategyContext.workerChoiceStrategies
772 .get(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
773 .workersTaskRunTime.keys()) {
774 expect(
775 pool.workerChoiceStrategyContext.workerChoiceStrategies
776 .get(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
777 .workersTaskRunTime.get(workerNodeKey).runTime
778 ).toBe(0)
779 }
780 // We need to clean up the resources after our test
781 await pool.destroy()
782 })
783
784 it('Verify unknown strategies throw error', () => {
785 expect(
786 () =>
787 new DynamicThreadPool(
788 min,
789 max,
790 './tests/worker-files/thread/testWorker.js',
791 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
792 )
793 ).toThrowError(
794 new Error("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")
795 )
796 })
797 })