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