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'
22 expect(WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
).toBe(
23 'INTERLEAVED_WEIGHTED_ROUND_ROBIN'
27 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
28 const pool
= new DynamicThreadPool(
31 './tests/worker-files/thread/testWorker.js'
33 expect(pool
.opts
.workerChoiceStrategy
).toBe(
34 WorkerChoiceStrategies
.ROUND_ROBIN
36 // We need to clean up the resources after our test
40 it('Verify available strategies are taken at pool creation', async () => {
41 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
42 const pool
= new FixedThreadPool(
44 './tests/worker-files/thread/testWorker.js',
45 { workerChoiceStrategy
}
47 expect(pool
.opts
.workerChoiceStrategy
).toBe(workerChoiceStrategy
)
48 expect(pool
.workerChoiceStrategyContext
.workerChoiceStrategy
).toBe(
55 it('Verify available strategies can be set after pool creation', async () => {
56 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
57 const pool
= new DynamicThreadPool(
60 './tests/worker-files/thread/testWorker.js'
62 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
63 expect(pool
.opts
.workerChoiceStrategy
).toBe(workerChoiceStrategy
)
64 expect(pool
.workerChoiceStrategyContext
.workerChoiceStrategy
).toBe(
71 it('Verify available strategies default internals at pool creation', async () => {
72 const pool
= new FixedThreadPool(
74 './tests/worker-files/thread/testWorker.js'
76 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
77 if (workerChoiceStrategy
=== WorkerChoiceStrategies
.ROUND_ROBIN
) {
79 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
83 } else if (workerChoiceStrategy
=== WorkerChoiceStrategies
.FAIR_SHARE
) {
85 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
87 ).workersVirtualTaskEndTimestamp
88 ).toBeInstanceOf(Array
)
90 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
92 ).workersVirtualTaskEndTimestamp
.length
95 workerChoiceStrategy
=== WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
98 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
100 ).currentWorkerNodeId
103 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
105 ).defaultWorkerWeight
108 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
110 ).workerVirtualTaskRunTime
117 it('Verify ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
118 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
119 let pool
= new FixedThreadPool(
121 './tests/worker-files/thread/testWorker.js',
122 { workerChoiceStrategy
}
125 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
136 pool
= new DynamicThreadPool(
139 './tests/worker-files/thread/testWorker.js',
140 { workerChoiceStrategy
}
143 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
153 // We need to clean up the resources after our test
157 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
158 const pool
= new FixedThreadPool(
160 './tests/worker-files/thread/testWorker.js',
161 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
163 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
164 const promises
= new Set()
165 const maxMultiplier
= 2
166 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
167 promises
.add(pool
.execute())
169 await Promise
.all(promises
)
170 for (const workerNode
of pool
.workerNodes
) {
171 expect(workerNode
.tasksUsage
).toStrictEqual({
175 runTimeHistory
: expect
.any(CircularArray
),
179 waitTimeHistory
: expect
.any(CircularArray
),
187 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
188 WorkerChoiceStrategies
.ROUND_ROBIN
191 // We need to clean up the resources after our test
195 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
196 const pool
= new DynamicThreadPool(
199 './tests/worker-files/thread/testWorker.js',
200 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
202 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
203 const promises
= new Set()
204 const maxMultiplier
= 2
205 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
206 promises
.add(pool
.execute())
208 await Promise
.all(promises
)
209 for (const workerNode
of pool
.workerNodes
) {
210 expect(workerNode
.tasksUsage
).toStrictEqual({
214 runTimeHistory
: expect
.any(CircularArray
),
218 waitTimeHistory
: expect
.any(CircularArray
),
226 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
227 WorkerChoiceStrategies
.ROUND_ROBIN
230 // We need to clean up the resources after our test
234 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
235 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
236 let pool
= new FixedClusterPool(
238 './tests/worker-files/cluster/testWorker.js',
239 { workerChoiceStrategy
}
241 let results
= new Set()
242 for (let i
= 0; i
< max
; i
++) {
243 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.id
)
245 expect(results
.size
).toBe(max
)
247 pool
= new FixedThreadPool(
249 './tests/worker-files/thread/testWorker.js',
250 { workerChoiceStrategy
}
253 for (let i
= 0; i
< max
; i
++) {
254 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.threadId
)
256 expect(results
.size
).toBe(max
)
260 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
261 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
262 let pool
= new FixedThreadPool(
264 './tests/worker-files/thread/testWorker.js',
265 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
268 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
272 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
274 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
275 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
279 pool
= new DynamicThreadPool(
282 './tests/worker-files/thread/testWorker.js',
283 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
286 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
290 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
292 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
293 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
296 // We need to clean up the resources after our test
300 it('Verify LEAST_USED strategy default tasks usage statistics requirements', async () => {
301 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
302 let pool
= new FixedThreadPool(
304 './tests/worker-files/thread/testWorker.js',
305 { workerChoiceStrategy
}
308 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
319 pool
= new DynamicThreadPool(
322 './tests/worker-files/thread/testWorker.js',
323 { workerChoiceStrategy
}
326 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
336 // We need to clean up the resources after our test
340 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
341 const pool
= new FixedThreadPool(
343 './tests/worker-files/thread/testWorker.js',
344 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
346 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
347 const promises
= new Set()
348 const maxMultiplier
= 2
349 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
350 promises
.add(pool
.execute())
352 await Promise
.all(promises
)
353 for (const workerNode
of pool
.workerNodes
) {
354 expect(workerNode
.tasksUsage
).toStrictEqual({
358 runTimeHistory
: expect
.any(CircularArray
),
362 waitTimeHistory
: expect
.any(CircularArray
),
369 // We need to clean up the resources after our test
373 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
374 const pool
= new DynamicThreadPool(
377 './tests/worker-files/thread/testWorker.js',
378 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
380 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
381 const promises
= new Set()
382 const maxMultiplier
= 2
383 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
384 promises
.add(pool
.execute())
386 await Promise
.all(promises
)
387 for (const workerNode
of pool
.workerNodes
) {
388 expect(workerNode
.tasksUsage
).toStrictEqual({
392 runTimeHistory
: expect
.any(CircularArray
),
396 waitTimeHistory
: expect
.any(CircularArray
),
403 // We need to clean up the resources after our test
407 it('Verify LEAST_BUSY strategy default tasks usage statistics requirements', async () => {
408 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
409 let pool
= new FixedThreadPool(
411 './tests/worker-files/thread/testWorker.js',
412 { workerChoiceStrategy
}
415 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
426 pool
= new DynamicThreadPool(
429 './tests/worker-files/thread/testWorker.js',
430 { workerChoiceStrategy
}
433 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
443 // We need to clean up the resources after our test
447 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
448 const pool
= new FixedThreadPool(
450 './tests/worker-files/thread/testWorker.js',
451 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
453 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
454 const promises
= new Set()
455 const maxMultiplier
= 2
456 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
457 promises
.add(pool
.execute())
459 await Promise
.all(promises
)
460 for (const workerNode
of pool
.workerNodes
) {
461 expect(workerNode
.tasksUsage
).toStrictEqual({
462 ran
: expect
.any(Number
),
464 runTime
: expect
.any(Number
),
465 runTimeHistory
: expect
.any(CircularArray
),
469 waitTimeHistory
: expect
.any(CircularArray
),
475 expect(workerNode
.tasksUsage
.ran
).toBeGreaterThan(0)
476 expect(workerNode
.tasksUsage
.ran
).toBeLessThanOrEqual(max
* maxMultiplier
)
477 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
479 // We need to clean up the resources after our test
483 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
484 const pool
= new DynamicThreadPool(
487 './tests/worker-files/thread/testWorker.js',
488 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
490 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
491 const promises
= new Set()
492 const maxMultiplier
= 2
493 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
494 promises
.add(pool
.execute())
496 await Promise
.all(promises
)
497 for (const workerNode
of pool
.workerNodes
) {
498 expect(workerNode
.tasksUsage
).toStrictEqual({
499 ran
: expect
.any(Number
),
501 runTime
: expect
.any(Number
),
502 runTimeHistory
: expect
.any(CircularArray
),
506 waitTimeHistory
: expect
.any(CircularArray
),
512 expect(workerNode
.tasksUsage
.ran
).toBeGreaterThan(0)
513 expect(workerNode
.tasksUsage
.ran
).toBeLessThanOrEqual(max
* maxMultiplier
)
514 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
516 // We need to clean up the resources after our test
520 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
521 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
522 let pool
= new FixedThreadPool(
524 './tests/worker-files/thread/testWorker.js',
525 { workerChoiceStrategy
}
528 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
539 pool
= new DynamicThreadPool(
542 './tests/worker-files/thread/testWorker.js',
543 { workerChoiceStrategy
}
546 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
556 // We need to clean up the resources after our test
560 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
561 const pool
= new FixedThreadPool(
563 './tests/worker-files/thread/testWorker.js',
564 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
566 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
567 const promises
= new Set()
568 const maxMultiplier
= 2
569 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
570 promises
.add(pool
.execute())
572 await Promise
.all(promises
)
573 for (const workerNode
of pool
.workerNodes
) {
574 expect(workerNode
.tasksUsage
).toStrictEqual({
577 runTime
: expect
.any(Number
),
578 runTimeHistory
: expect
.any(CircularArray
),
579 avgRunTime
: expect
.any(Number
),
582 waitTimeHistory
: expect
.any(CircularArray
),
588 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
589 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThan(0)
592 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
593 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
594 ).workersVirtualTaskEndTimestamp
.length
595 ).toBe(pool
.workerNodes
.length
)
596 // We need to clean up the resources after our test
600 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
601 const pool
= new DynamicThreadPool(
604 './tests/worker-files/thread/testWorker.js',
605 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
607 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
608 const promises
= new Set()
609 const maxMultiplier
= 2
610 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
611 promises
.add(pool
.execute())
613 await Promise
.all(promises
)
614 for (const workerNode
of pool
.workerNodes
) {
615 expect(workerNode
.tasksUsage
).toStrictEqual({
618 runTime
: expect
.any(Number
),
619 runTimeHistory
: expect
.any(CircularArray
),
620 avgRunTime
: expect
.any(Number
),
623 waitTimeHistory
: expect
.any(CircularArray
),
629 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
630 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThan(0)
633 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
634 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
635 ).workersVirtualTaskEndTimestamp
.length
636 ).toBe(pool
.workerNodes
.length
)
637 // We need to clean up the resources after our test
641 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
642 const pool
= new DynamicThreadPool(
645 './tests/worker-files/thread/testWorker.js',
647 workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
,
648 workerChoiceStrategyOptions
: {
653 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
654 const promises
= new Set()
655 const maxMultiplier
= 2
656 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
657 promises
.add(pool
.execute())
659 await Promise
.all(promises
)
660 for (const workerNode
of pool
.workerNodes
) {
661 expect(workerNode
.tasksUsage
).toStrictEqual({
664 runTime
: expect
.any(Number
),
665 runTimeHistory
: expect
.any(CircularArray
),
667 medRunTime
: expect
.any(Number
),
669 waitTimeHistory
: expect
.any(CircularArray
),
675 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
676 expect(workerNode
.tasksUsage
.medRunTime
).toBeGreaterThan(0)
679 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
680 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
681 ).workersVirtualTaskEndTimestamp
.length
682 ).toBe(pool
.workerNodes
.length
)
683 // We need to clean up the resources after our test
687 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
688 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
689 let pool
= new FixedThreadPool(
691 './tests/worker-files/thread/testWorker.js'
694 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
696 ).workersVirtualTaskEndTimestamp
697 ).toBeInstanceOf(Array
)
699 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
701 ).workersVirtualTaskEndTimestamp
.length
703 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
705 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
707 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
709 ).workersVirtualTaskEndTimestamp
.length
711 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
713 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
715 ).workersVirtualTaskEndTimestamp
716 ).toBeInstanceOf(Array
)
718 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
720 ).workersVirtualTaskEndTimestamp
.length
723 pool
= new DynamicThreadPool(
726 './tests/worker-files/thread/testWorker.js'
729 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
731 ).workersVirtualTaskEndTimestamp
732 ).toBeInstanceOf(Array
)
734 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
736 ).workersVirtualTaskEndTimestamp
.length
738 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
740 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
742 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
744 ).workersVirtualTaskEndTimestamp
.length
746 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
748 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
750 ).workersVirtualTaskEndTimestamp
751 ).toBeInstanceOf(Array
)
753 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
755 ).workersVirtualTaskEndTimestamp
.length
757 // We need to clean up the resources after our test
761 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
762 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
763 let pool
= new FixedThreadPool(
765 './tests/worker-files/thread/testWorker.js',
766 { workerChoiceStrategy
}
769 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
780 pool
= new DynamicThreadPool(
783 './tests/worker-files/thread/testWorker.js',
784 { workerChoiceStrategy
}
787 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
797 // We need to clean up the resources after our test
801 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
802 const pool
= new FixedThreadPool(
804 './tests/worker-files/thread/testWorker.js',
805 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
807 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
808 const promises
= new Set()
809 const maxMultiplier
= 2
810 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
811 promises
.add(pool
.execute())
813 await Promise
.all(promises
)
814 for (const workerNode
of pool
.workerNodes
) {
815 expect(workerNode
.tasksUsage
).toStrictEqual({
816 ran
: expect
.any(Number
),
818 runTime
: expect
.any(Number
),
819 runTimeHistory
: expect
.any(CircularArray
),
820 avgRunTime
: expect
.any(Number
),
823 waitTimeHistory
: expect
.any(CircularArray
),
829 expect(workerNode
.tasksUsage
.ran
).toBeGreaterThanOrEqual(0)
830 expect(workerNode
.tasksUsage
.ran
).toBeLessThanOrEqual(max
* maxMultiplier
)
831 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThanOrEqual(0)
832 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThanOrEqual(0)
835 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
836 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
837 ).defaultWorkerWeight
840 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
841 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
842 ).workerVirtualTaskRunTime
843 ).toBeGreaterThanOrEqual(0)
844 // We need to clean up the resources after our test
848 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
849 const pool
= new DynamicThreadPool(
852 './tests/worker-files/thread/testWorker.js',
853 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
855 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
856 const promises
= new Set()
857 const maxMultiplier
= 2
858 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
859 promises
.add(pool
.execute())
861 await Promise
.all(promises
)
862 for (const workerNode
of pool
.workerNodes
) {
863 expect(workerNode
.tasksUsage
).toStrictEqual({
864 ran
: expect
.any(Number
),
866 runTime
: expect
.any(Number
),
867 runTimeHistory
: expect
.any(CircularArray
),
868 avgRunTime
: expect
.any(Number
),
871 waitTimeHistory
: expect
.any(CircularArray
),
877 expect(workerNode
.tasksUsage
.ran
).toBeGreaterThan(0)
878 expect(workerNode
.tasksUsage
.ran
).toBeLessThanOrEqual(max
* maxMultiplier
)
879 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
880 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThan(0)
883 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
884 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
885 ).defaultWorkerWeight
888 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
889 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
890 ).workerVirtualTaskRunTime
891 ).toBeGreaterThanOrEqual(0)
892 // We need to clean up the resources after our test
896 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
897 const pool
= new DynamicThreadPool(
900 './tests/worker-files/thread/testWorker.js',
902 workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
,
903 workerChoiceStrategyOptions
: {
908 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
909 const promises
= new Set()
910 const maxMultiplier
= 2
911 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
912 promises
.add(pool
.execute())
914 await Promise
.all(promises
)
915 for (const workerNode
of pool
.workerNodes
) {
916 expect(workerNode
.tasksUsage
).toStrictEqual({
917 ran
: expect
.any(Number
),
919 runTime
: expect
.any(Number
),
920 runTimeHistory
: expect
.any(CircularArray
),
922 medRunTime
: expect
.any(Number
),
924 waitTimeHistory
: expect
.any(CircularArray
),
930 expect(workerNode
.tasksUsage
.ran
).toBeGreaterThan(0)
931 expect(workerNode
.tasksUsage
.ran
).toBeLessThanOrEqual(max
* maxMultiplier
)
932 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
933 expect(workerNode
.tasksUsage
.medRunTime
).toBeGreaterThan(0)
936 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
937 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
938 ).defaultWorkerWeight
941 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
942 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
943 ).workerVirtualTaskRunTime
944 ).toBeGreaterThanOrEqual(0)
945 // We need to clean up the resources after our test
949 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
950 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
951 let pool
= new FixedThreadPool(
953 './tests/worker-files/thread/testWorker.js'
956 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
958 ).currentWorkerNodeId
961 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
963 ).defaultWorkerWeight
966 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
968 ).workerVirtualTaskRunTime
970 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
972 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
973 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
974 ).currentWorkerNodeId
977 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
978 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
979 ).defaultWorkerWeight
982 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
984 ).workerVirtualTaskRunTime
987 pool
= new DynamicThreadPool(
990 './tests/worker-files/thread/testWorker.js'
993 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
995 ).currentWorkerNodeId
998 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1000 ).defaultWorkerWeight
1003 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1004 workerChoiceStrategy
1005 ).workerVirtualTaskRunTime
1007 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1009 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1010 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1011 ).currentWorkerNodeId
1014 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1015 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1016 ).defaultWorkerWeight
1017 ).toBeGreaterThan(0)
1019 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1020 workerChoiceStrategy
1021 ).workerVirtualTaskRunTime
1023 // We need to clean up the resources after our test
1024 await pool
.destroy()
1027 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1028 const workerChoiceStrategy
=
1029 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1030 let pool
= new FixedThreadPool(
1032 './tests/worker-files/thread/testWorker.js',
1033 { workerChoiceStrategy
}
1036 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
1046 await pool
.destroy()
1047 pool
= new DynamicThreadPool(
1050 './tests/worker-files/thread/testWorker.js',
1051 { workerChoiceStrategy
}
1054 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
1064 // We need to clean up the resources after our test
1065 await pool
.destroy()
1068 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1069 const pool
= new FixedThreadPool(
1071 './tests/worker-files/thread/testWorker.js',
1073 workerChoiceStrategy
:
1074 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1077 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1078 const promises
= new Set()
1079 const maxMultiplier
= 2
1080 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1081 promises
.add(pool
.execute())
1083 await Promise
.all(promises
)
1084 for (const workerNode
of pool
.workerNodes
) {
1085 expect(workerNode
.tasksUsage
).toStrictEqual({
1089 runTimeHistory
: expect
.any(CircularArray
),
1093 waitTimeHistory
: expect
.any(CircularArray
),
1101 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1102 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1103 ).defaultWorkerWeight
1104 ).toBeGreaterThan(0)
1106 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1107 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1111 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1112 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1113 ).currentWorkerNodeId
1116 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1117 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1120 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1121 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1122 ).defaultWorkerWeight
1124 // We need to clean up the resources after our test
1125 await pool
.destroy()
1128 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1129 const pool
= new DynamicThreadPool(
1132 './tests/worker-files/thread/testWorker.js',
1134 workerChoiceStrategy
:
1135 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1138 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1139 const promises
= new Set()
1140 const maxMultiplier
= 2
1141 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1142 promises
.add(pool
.execute())
1144 await Promise
.all(promises
)
1145 for (const workerNode
of pool
.workerNodes
) {
1146 expect(workerNode
.tasksUsage
).toStrictEqual({
1150 runTimeHistory
: expect
.any(CircularArray
),
1154 waitTimeHistory
: expect
.any(CircularArray
),
1162 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1163 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1164 ).defaultWorkerWeight
1165 ).toBeGreaterThan(0)
1167 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1168 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1172 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1173 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1174 ).currentWorkerNodeId
1177 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1178 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1181 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1182 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1183 ).defaultWorkerWeight
1185 // We need to clean up the resources after our test
1186 await pool
.destroy()
1189 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1190 const workerChoiceStrategy
=
1191 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1192 let pool
= new FixedThreadPool(
1194 './tests/worker-files/thread/testWorker.js'
1197 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1198 workerChoiceStrategy
1202 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1203 workerChoiceStrategy
1204 ).currentWorkerNodeId
1207 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1208 workerChoiceStrategy
1209 ).defaultWorkerWeight
1212 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1213 workerChoiceStrategy
1216 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1218 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1219 workerChoiceStrategy
1223 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1224 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1225 ).currentWorkerNodeId
1228 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1229 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1230 ).defaultWorkerWeight
1231 ).toBeGreaterThan(0)
1233 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1234 workerChoiceStrategy
1237 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1238 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1239 ).defaultWorkerWeight
1241 await pool
.destroy()
1242 pool
= new DynamicThreadPool(
1245 './tests/worker-files/thread/testWorker.js'
1248 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1249 workerChoiceStrategy
1253 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1254 workerChoiceStrategy
1255 ).currentWorkerNodeId
1258 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1259 workerChoiceStrategy
1260 ).defaultWorkerWeight
1263 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1264 workerChoiceStrategy
1267 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1269 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1270 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1271 ).currentWorkerNodeId
1274 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1275 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1276 ).defaultWorkerWeight
1277 ).toBeGreaterThan(0)
1279 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1280 workerChoiceStrategy
1283 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1284 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1285 ).defaultWorkerWeight
1287 // We need to clean up the resources after our test
1288 await pool
.destroy()
1291 it('Verify unknown strategy throw error', () => {
1294 new DynamicThreadPool(
1297 './tests/worker-files/thread/testWorker.js',
1298 { workerChoiceStrategy
: 'UNKNOWN_STRATEGY' }
1300 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")