1 const { expect
} = require('expect')
3 WorkerChoiceStrategies
,
7 } = require('../../../lib')
8 const { CircularArray
} = require('../../../lib/circular-array')
10 describe('Selection strategies test suite', () => {
14 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
15 expect(WorkerChoiceStrategies
.ROUND_ROBIN
).toBe('ROUND_ROBIN')
16 expect(WorkerChoiceStrategies
.LEAST_USED
).toBe('LEAST_USED')
17 expect(WorkerChoiceStrategies
.LEAST_BUSY
).toBe('LEAST_BUSY')
18 expect(WorkerChoiceStrategies
.FAIR_SHARE
).toBe('FAIR_SHARE')
19 expect(WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
).toBe(
20 'WEIGHTED_ROUND_ROBIN'
24 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
25 const pool
= new DynamicThreadPool(
28 './tests/worker-files/thread/testWorker.js'
30 expect(pool
.opts
.workerChoiceStrategy
).toBe(
31 WorkerChoiceStrategies
.ROUND_ROBIN
33 // We need to clean up the resources after our test
37 it('Verify available strategies are taken at pool creation', async () => {
38 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
39 const pool
= new FixedThreadPool(
41 './tests/worker-files/thread/testWorker.js',
42 { workerChoiceStrategy
}
44 expect(pool
.opts
.workerChoiceStrategy
).toBe(workerChoiceStrategy
)
45 expect(pool
.workerChoiceStrategyContext
.workerChoiceStrategy
).toBe(
52 it('Verify available strategies can be set after pool creation', async () => {
53 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
54 const pool
= new DynamicThreadPool(
57 './tests/worker-files/thread/testWorker.js'
59 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
60 expect(pool
.opts
.workerChoiceStrategy
).toBe(workerChoiceStrategy
)
61 expect(pool
.workerChoiceStrategyContext
.workerChoiceStrategy
).toBe(
68 it('Verify available strategies default internals at pool creation', async () => {
69 const pool
= new FixedThreadPool(
71 './tests/worker-files/thread/testWorker.js'
73 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
74 if (workerChoiceStrategy
=== WorkerChoiceStrategies
.ROUND_ROBIN
) {
76 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
80 } else if (workerChoiceStrategy
=== WorkerChoiceStrategies
.FAIR_SHARE
) {
82 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
84 ).workersVirtualTaskEndTimestamp
85 ).toBeInstanceOf(Array
)
87 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
89 ).workersVirtualTaskEndTimestamp
.length
92 workerChoiceStrategy
=== WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
95 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
100 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
102 ).defaultWorkerWeight
105 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
107 ).workerVirtualTaskRunTime
114 it('Verify ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
115 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
116 let pool
= new FixedThreadPool(
118 './tests/worker-files/thread/testWorker.js',
119 { workerChoiceStrategy
}
122 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
132 pool
= new DynamicThreadPool(
135 './tests/worker-files/thread/testWorker.js',
136 { workerChoiceStrategy
}
139 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
148 // We need to clean up the resources after our test
152 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
153 const pool
= new FixedThreadPool(
155 './tests/worker-files/thread/testWorker.js',
156 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
158 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
159 const promises
= new Set()
160 const maxMultiplier
= 2
161 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
162 promises
.add(pool
.execute())
164 await Promise
.all(promises
)
165 for (const workerNode
of pool
.workerNodes
) {
166 expect(workerNode
.tasksUsage
).toStrictEqual({
167 run
: expect
.any(Number
),
170 runTimeHistory
: expect
.any(CircularArray
),
174 waitTimeHistory
: expect
.any(CircularArray
),
179 expect(workerNode
.tasksUsage
.run
).toBeGreaterThan(0)
180 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
182 // We need to clean up the resources after our test
186 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
187 const pool
= new DynamicThreadPool(
190 './tests/worker-files/thread/testWorker.js',
191 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
193 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
194 const promises
= new Set()
195 const maxMultiplier
= 2
196 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
197 promises
.add(pool
.execute())
199 await Promise
.all(promises
)
200 for (const workerNode
of pool
.workerNodes
) {
201 expect(workerNode
.tasksUsage
).toStrictEqual({
202 run
: expect
.any(Number
),
205 runTimeHistory
: expect
.any(CircularArray
),
209 waitTimeHistory
: expect
.any(CircularArray
),
214 expect(workerNode
.tasksUsage
.run
).toBeGreaterThan(0)
215 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
217 // We need to clean up the resources after our test
221 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
222 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
223 let pool
= new FixedClusterPool(
225 './tests/worker-files/cluster/testWorker.js',
226 { workerChoiceStrategy
}
228 let results
= new Set()
229 for (let i
= 0; i
< max
; i
++) {
230 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.id
)
232 expect(results
.size
).toBe(max
)
234 pool
= new FixedThreadPool(
236 './tests/worker-files/thread/testWorker.js',
237 { workerChoiceStrategy
}
240 for (let i
= 0; i
< max
; i
++) {
241 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.threadId
)
243 expect(results
.size
).toBe(max
)
247 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
248 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
249 let pool
= new FixedThreadPool(
251 './tests/worker-files/thread/testWorker.js',
252 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
255 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
259 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
261 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
262 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
266 pool
= new DynamicThreadPool(
269 './tests/worker-files/thread/testWorker.js',
270 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
273 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
277 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
279 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
280 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
283 // We need to clean up the resources after our test
287 it('Verify LEAST_USED strategy default tasks usage statistics requirements', async () => {
288 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
289 let pool
= new FixedThreadPool(
291 './tests/worker-files/thread/testWorker.js',
292 { workerChoiceStrategy
}
295 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
305 pool
= new DynamicThreadPool(
308 './tests/worker-files/thread/testWorker.js',
309 { workerChoiceStrategy
}
312 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
321 // We need to clean up the resources after our test
325 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
326 const pool
= new FixedThreadPool(
328 './tests/worker-files/thread/testWorker.js',
329 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
331 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
332 const promises
= new Set()
333 const maxMultiplier
= 2
334 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
335 promises
.add(pool
.execute())
337 await Promise
.all(promises
)
338 for (const workerNode
of pool
.workerNodes
) {
339 expect(workerNode
.tasksUsage
).toStrictEqual({
340 run
: expect
.any(Number
),
343 runTimeHistory
: expect
.any(CircularArray
),
347 waitTimeHistory
: expect
.any(CircularArray
),
352 expect(workerNode
.tasksUsage
.run
).toBeGreaterThan(0)
353 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
355 // We need to clean up the resources after our test
359 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
360 const pool
= new DynamicThreadPool(
363 './tests/worker-files/thread/testWorker.js',
364 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
366 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
367 const promises
= new Set()
368 const maxMultiplier
= 2
369 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
370 promises
.add(pool
.execute())
372 await Promise
.all(promises
)
373 for (const workerNode
of pool
.workerNodes
) {
374 expect(workerNode
.tasksUsage
).toStrictEqual({
375 run
: expect
.any(Number
),
378 runTimeHistory
: expect
.any(CircularArray
),
382 waitTimeHistory
: expect
.any(CircularArray
),
387 expect(workerNode
.tasksUsage
.run
).toBeGreaterThan(0)
388 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
390 // We need to clean up the resources after our test
394 it('Verify LEAST_BUSY strategy default tasks usage statistics requirements', async () => {
395 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
396 let pool
= new FixedThreadPool(
398 './tests/worker-files/thread/testWorker.js',
399 { workerChoiceStrategy
}
402 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
412 pool
= new DynamicThreadPool(
415 './tests/worker-files/thread/testWorker.js',
416 { workerChoiceStrategy
}
419 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
428 // We need to clean up the resources after our test
432 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
433 const pool
= new FixedThreadPool(
435 './tests/worker-files/thread/testWorker.js',
436 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
438 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
439 const promises
= new Set()
440 const maxMultiplier
= 2
441 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
442 promises
.add(pool
.execute())
444 await Promise
.all(promises
)
445 for (const workerNode
of pool
.workerNodes
) {
446 expect(workerNode
.tasksUsage
).toStrictEqual({
447 run
: expect
.any(Number
),
449 runTime
: expect
.any(Number
),
450 runTimeHistory
: expect
.any(CircularArray
),
454 waitTimeHistory
: expect
.any(CircularArray
),
459 expect(workerNode
.tasksUsage
.run
).toBeGreaterThan(0)
460 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
461 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
463 // We need to clean up the resources after our test
467 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
468 const pool
= new DynamicThreadPool(
471 './tests/worker-files/thread/testWorker.js',
472 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
474 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
475 const promises
= new Set()
476 const maxMultiplier
= 2
477 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
478 promises
.add(pool
.execute())
480 await Promise
.all(promises
)
481 for (const workerNode
of pool
.workerNodes
) {
482 expect(workerNode
.tasksUsage
).toStrictEqual({
483 run
: expect
.any(Number
),
485 runTime
: expect
.any(Number
),
486 runTimeHistory
: expect
.any(CircularArray
),
490 waitTimeHistory
: expect
.any(CircularArray
),
495 expect(workerNode
.tasksUsage
.run
).toBeGreaterThan(0)
496 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
497 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
499 // We need to clean up the resources after our test
503 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
504 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
505 let pool
= new FixedThreadPool(
507 './tests/worker-files/thread/testWorker.js',
508 { workerChoiceStrategy
}
511 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
521 pool
= new DynamicThreadPool(
524 './tests/worker-files/thread/testWorker.js',
525 { workerChoiceStrategy
}
528 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
537 // We need to clean up the resources after our test
541 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
542 const pool
= new FixedThreadPool(
544 './tests/worker-files/thread/testWorker.js',
545 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
547 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
548 const promises
= new Set()
549 const maxMultiplier
= 2
550 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
551 promises
.add(pool
.execute())
553 await Promise
.all(promises
)
554 for (const workerNode
of pool
.workerNodes
) {
555 expect(workerNode
.tasksUsage
).toStrictEqual({
556 run
: expect
.any(Number
),
558 runTime
: expect
.any(Number
),
559 runTimeHistory
: expect
.any(CircularArray
),
560 avgRunTime
: expect
.any(Number
),
563 waitTimeHistory
: expect
.any(CircularArray
),
568 expect(workerNode
.tasksUsage
.run
).toBeGreaterThan(0)
569 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
570 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
571 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThan(0)
574 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
575 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
576 ).workersVirtualTaskEndTimestamp
.length
577 ).toBe(pool
.workerNodes
.length
)
578 // We need to clean up the resources after our test
582 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
583 const pool
= new DynamicThreadPool(
586 './tests/worker-files/thread/testWorker.js',
587 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
589 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
590 const promises
= new Set()
591 const maxMultiplier
= 2
592 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
593 promises
.add(pool
.execute())
595 await Promise
.all(promises
)
596 for (const workerNode
of pool
.workerNodes
) {
597 expect(workerNode
.tasksUsage
).toStrictEqual({
598 run
: expect
.any(Number
),
600 runTime
: expect
.any(Number
),
601 runTimeHistory
: expect
.any(CircularArray
),
602 avgRunTime
: expect
.any(Number
),
605 waitTimeHistory
: expect
.any(CircularArray
),
610 expect(workerNode
.tasksUsage
.run
).toBeGreaterThan(0)
611 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
612 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
613 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThan(0)
616 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
617 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
618 ).workersVirtualTaskEndTimestamp
.length
619 ).toBe(pool
.workerNodes
.length
)
620 // We need to clean up the resources after our test
624 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
625 const pool
= new DynamicThreadPool(
628 './tests/worker-files/thread/testWorker.js',
630 workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
,
631 workerChoiceStrategyOptions
: {
636 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
637 const promises
= new Set()
638 const maxMultiplier
= 2
639 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
640 promises
.add(pool
.execute())
642 await Promise
.all(promises
)
643 for (const workerNode
of pool
.workerNodes
) {
644 expect(workerNode
.tasksUsage
).toStrictEqual({
645 run
: expect
.any(Number
),
647 runTime
: expect
.any(Number
),
648 runTimeHistory
: expect
.any(CircularArray
),
650 medRunTime
: expect
.any(Number
),
652 waitTimeHistory
: expect
.any(CircularArray
),
657 expect(workerNode
.tasksUsage
.run
).toBeGreaterThan(0)
658 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
659 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
660 expect(workerNode
.tasksUsage
.medRunTime
).toBeGreaterThan(0)
663 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
664 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
665 ).workersVirtualTaskEndTimestamp
.length
666 ).toBe(pool
.workerNodes
.length
)
667 // We need to clean up the resources after our test
671 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
672 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
673 let pool
= new FixedThreadPool(
675 './tests/worker-files/thread/testWorker.js'
678 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
680 ).workersVirtualTaskEndTimestamp
681 ).toBeInstanceOf(Array
)
683 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
685 ).workersVirtualTaskEndTimestamp
.length
687 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
689 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
691 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
693 ).workersVirtualTaskEndTimestamp
.length
695 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
697 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
699 ).workersVirtualTaskEndTimestamp
700 ).toBeInstanceOf(Array
)
702 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
704 ).workersVirtualTaskEndTimestamp
.length
707 pool
= new DynamicThreadPool(
710 './tests/worker-files/thread/testWorker.js'
713 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
715 ).workersVirtualTaskEndTimestamp
716 ).toBeInstanceOf(Array
)
718 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
720 ).workersVirtualTaskEndTimestamp
.length
722 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
724 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
726 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
728 ).workersVirtualTaskEndTimestamp
.length
730 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
732 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
734 ).workersVirtualTaskEndTimestamp
735 ).toBeInstanceOf(Array
)
737 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
739 ).workersVirtualTaskEndTimestamp
.length
741 // We need to clean up the resources after our test
745 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
746 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
747 let pool
= new FixedThreadPool(
749 './tests/worker-files/thread/testWorker.js',
750 { workerChoiceStrategy
}
753 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
763 pool
= new DynamicThreadPool(
766 './tests/worker-files/thread/testWorker.js',
767 { workerChoiceStrategy
}
770 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
779 // We need to clean up the resources after our test
783 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
784 const pool
= new FixedThreadPool(
786 './tests/worker-files/thread/testWorker.js',
787 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
789 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
790 const promises
= new Set()
791 const maxMultiplier
= 2
792 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
793 promises
.add(pool
.execute())
795 await Promise
.all(promises
)
796 for (const workerNode
of pool
.workerNodes
) {
797 expect(workerNode
.tasksUsage
).toStrictEqual({
798 run
: expect
.any(Number
),
800 runTime
: expect
.any(Number
),
801 runTimeHistory
: expect
.any(CircularArray
),
802 avgRunTime
: expect
.any(Number
),
805 waitTimeHistory
: expect
.any(CircularArray
),
810 expect(workerNode
.tasksUsage
.run
).toBeGreaterThanOrEqual(0)
811 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
812 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThanOrEqual(0)
813 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThanOrEqual(0)
816 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
817 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
818 ).defaultWorkerWeight
821 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
822 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
823 ).workerVirtualTaskRunTime
824 ).toBeGreaterThanOrEqual(0)
825 // We need to clean up the resources after our test
829 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
830 const pool
= new DynamicThreadPool(
833 './tests/worker-files/thread/testWorker.js',
834 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
836 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
837 const promises
= new Set()
838 const maxMultiplier
= 2
839 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
840 promises
.add(pool
.execute())
842 await Promise
.all(promises
)
843 for (const workerNode
of pool
.workerNodes
) {
844 expect(workerNode
.tasksUsage
).toStrictEqual({
845 run
: expect
.any(Number
),
847 runTime
: expect
.any(Number
),
848 runTimeHistory
: expect
.any(CircularArray
),
849 avgRunTime
: expect
.any(Number
),
852 waitTimeHistory
: expect
.any(CircularArray
),
857 expect(workerNode
.tasksUsage
.run
).toBeGreaterThan(0)
858 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
859 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
860 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThan(0)
863 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
864 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
865 ).defaultWorkerWeight
868 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
869 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
870 ).workerVirtualTaskRunTime
871 ).toBeGreaterThanOrEqual(0)
872 // We need to clean up the resources after our test
876 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
877 const pool
= new DynamicThreadPool(
880 './tests/worker-files/thread/testWorker.js',
882 workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
,
883 workerChoiceStrategyOptions
: {
888 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
889 const promises
= new Set()
890 const maxMultiplier
= 2
891 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
892 promises
.add(pool
.execute())
894 await Promise
.all(promises
)
895 for (const workerNode
of pool
.workerNodes
) {
896 expect(workerNode
.tasksUsage
).toStrictEqual({
897 run
: expect
.any(Number
),
899 runTime
: expect
.any(Number
),
900 runTimeHistory
: expect
.any(CircularArray
),
902 medRunTime
: expect
.any(Number
),
904 waitTimeHistory
: expect
.any(CircularArray
),
909 expect(workerNode
.tasksUsage
.run
).toBeGreaterThan(0)
910 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
911 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
912 expect(workerNode
.tasksUsage
.medRunTime
).toBeGreaterThan(0)
915 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
916 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
917 ).defaultWorkerWeight
920 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
921 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
922 ).workerVirtualTaskRunTime
923 ).toBeGreaterThanOrEqual(0)
924 // We need to clean up the resources after our test
928 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
929 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
930 let pool
= new FixedThreadPool(
932 './tests/worker-files/thread/testWorker.js'
935 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
937 ).currentWorkerNodeId
940 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
942 ).defaultWorkerWeight
945 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
947 ).workerVirtualTaskRunTime
949 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
951 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
952 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
953 ).currentWorkerNodeId
956 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
957 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
958 ).defaultWorkerWeight
961 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
963 ).workerVirtualTaskRunTime
966 pool
= new DynamicThreadPool(
969 './tests/worker-files/thread/testWorker.js'
972 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
974 ).currentWorkerNodeId
977 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
979 ).defaultWorkerWeight
982 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
984 ).workerVirtualTaskRunTime
986 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
988 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
989 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
990 ).currentWorkerNodeId
993 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
994 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
995 ).defaultWorkerWeight
998 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1000 ).workerVirtualTaskRunTime
1002 // We need to clean up the resources after our test
1003 await pool
.destroy()
1006 it('Verify unknown strategy throw error', () => {
1009 new DynamicThreadPool(
1012 './tests/worker-files/thread/testWorker.js',
1013 { workerChoiceStrategy
: 'UNKNOWN_STRATEGY' }
1015 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")