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()
135 pool
= new DynamicThreadPool(
138 './tests/worker-files/thread/testWorker.js',
139 { workerChoiceStrategy
}
142 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
151 // We need to clean up the resources after our test
155 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
156 const pool
= new FixedThreadPool(
158 './tests/worker-files/thread/testWorker.js',
159 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
161 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
162 const promises
= new Set()
163 const maxMultiplier
= 2
164 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
165 promises
.add(pool
.execute())
167 await Promise
.all(promises
)
168 for (const workerNode
of pool
.workerNodes
) {
169 expect(workerNode
.tasksUsage
).toStrictEqual({
173 runTimeHistory
: expect
.any(CircularArray
),
177 waitTimeHistory
: expect
.any(CircularArray
),
184 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
185 WorkerChoiceStrategies
.ROUND_ROBIN
188 // We need to clean up the resources after our test
192 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
193 const pool
= new DynamicThreadPool(
196 './tests/worker-files/thread/testWorker.js',
197 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
199 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
200 const promises
= new Set()
201 const maxMultiplier
= 2
202 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
203 promises
.add(pool
.execute())
205 await Promise
.all(promises
)
206 for (const workerNode
of pool
.workerNodes
) {
207 expect(workerNode
.tasksUsage
).toStrictEqual({
211 runTimeHistory
: expect
.any(CircularArray
),
215 waitTimeHistory
: expect
.any(CircularArray
),
222 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
223 WorkerChoiceStrategies
.ROUND_ROBIN
226 // We need to clean up the resources after our test
230 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
231 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
232 let pool
= new FixedClusterPool(
234 './tests/worker-files/cluster/testWorker.js',
235 { workerChoiceStrategy
}
237 let results
= new Set()
238 for (let i
= 0; i
< max
; i
++) {
239 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.id
)
241 expect(results
.size
).toBe(max
)
243 pool
= new FixedThreadPool(
245 './tests/worker-files/thread/testWorker.js',
246 { workerChoiceStrategy
}
249 for (let i
= 0; i
< max
; i
++) {
250 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.threadId
)
252 expect(results
.size
).toBe(max
)
256 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
257 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
258 let pool
= new FixedThreadPool(
260 './tests/worker-files/thread/testWorker.js',
261 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
264 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
268 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
270 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
271 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
275 pool
= new DynamicThreadPool(
278 './tests/worker-files/thread/testWorker.js',
279 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
282 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
286 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
288 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
289 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
292 // We need to clean up the resources after our test
296 it('Verify LEAST_USED strategy default tasks usage statistics requirements', async () => {
297 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
298 let pool
= new FixedThreadPool(
300 './tests/worker-files/thread/testWorker.js',
301 { workerChoiceStrategy
}
304 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
314 pool
= new DynamicThreadPool(
317 './tests/worker-files/thread/testWorker.js',
318 { workerChoiceStrategy
}
321 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
330 // We need to clean up the resources after our test
334 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
335 const pool
= new FixedThreadPool(
337 './tests/worker-files/thread/testWorker.js',
338 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
340 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
341 const promises
= new Set()
342 const maxMultiplier
= 2
343 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
344 promises
.add(pool
.execute())
346 await Promise
.all(promises
)
347 for (const workerNode
of pool
.workerNodes
) {
348 expect(workerNode
.tasksUsage
).toStrictEqual({
352 runTimeHistory
: expect
.any(CircularArray
),
356 waitTimeHistory
: expect
.any(CircularArray
),
362 // We need to clean up the resources after our test
366 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
367 const pool
= new DynamicThreadPool(
370 './tests/worker-files/thread/testWorker.js',
371 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
373 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
374 const promises
= new Set()
375 const maxMultiplier
= 2
376 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
377 promises
.add(pool
.execute())
379 await Promise
.all(promises
)
380 for (const workerNode
of pool
.workerNodes
) {
381 expect(workerNode
.tasksUsage
).toStrictEqual({
385 runTimeHistory
: expect
.any(CircularArray
),
389 waitTimeHistory
: expect
.any(CircularArray
),
395 // We need to clean up the resources after our test
399 it('Verify LEAST_BUSY strategy default tasks usage statistics requirements', async () => {
400 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
401 let pool
= new FixedThreadPool(
403 './tests/worker-files/thread/testWorker.js',
404 { workerChoiceStrategy
}
407 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
417 pool
= new DynamicThreadPool(
420 './tests/worker-files/thread/testWorker.js',
421 { workerChoiceStrategy
}
424 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
433 // We need to clean up the resources after our test
437 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
438 const pool
= new FixedThreadPool(
440 './tests/worker-files/thread/testWorker.js',
441 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
443 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
444 const promises
= new Set()
445 const maxMultiplier
= 2
446 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
447 promises
.add(pool
.execute())
449 await Promise
.all(promises
)
450 for (const workerNode
of pool
.workerNodes
) {
451 expect(workerNode
.tasksUsage
).toStrictEqual({
452 ran
: expect
.any(Number
),
454 runTime
: expect
.any(Number
),
455 runTimeHistory
: expect
.any(CircularArray
),
459 waitTimeHistory
: expect
.any(CircularArray
),
464 expect(workerNode
.tasksUsage
.ran
).toBeGreaterThan(0)
465 expect(workerNode
.tasksUsage
.ran
).toBeLessThanOrEqual(max
* maxMultiplier
)
466 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
468 // We need to clean up the resources after our test
472 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
473 const pool
= new DynamicThreadPool(
476 './tests/worker-files/thread/testWorker.js',
477 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
479 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
480 const promises
= new Set()
481 const maxMultiplier
= 2
482 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
483 promises
.add(pool
.execute())
485 await Promise
.all(promises
)
486 for (const workerNode
of pool
.workerNodes
) {
487 expect(workerNode
.tasksUsage
).toStrictEqual({
488 ran
: expect
.any(Number
),
490 runTime
: expect
.any(Number
),
491 runTimeHistory
: expect
.any(CircularArray
),
495 waitTimeHistory
: expect
.any(CircularArray
),
500 expect(workerNode
.tasksUsage
.ran
).toBeGreaterThan(0)
501 expect(workerNode
.tasksUsage
.ran
).toBeLessThanOrEqual(max
* maxMultiplier
)
502 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
504 // We need to clean up the resources after our test
508 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
509 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
510 let pool
= new FixedThreadPool(
512 './tests/worker-files/thread/testWorker.js',
513 { workerChoiceStrategy
}
516 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
526 pool
= new DynamicThreadPool(
529 './tests/worker-files/thread/testWorker.js',
530 { workerChoiceStrategy
}
533 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
542 // We need to clean up the resources after our test
546 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
547 const pool
= new FixedThreadPool(
549 './tests/worker-files/thread/testWorker.js',
550 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
552 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
553 const promises
= new Set()
554 const maxMultiplier
= 2
555 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
556 promises
.add(pool
.execute())
558 await Promise
.all(promises
)
559 for (const workerNode
of pool
.workerNodes
) {
560 expect(workerNode
.tasksUsage
).toStrictEqual({
563 runTime
: expect
.any(Number
),
564 runTimeHistory
: expect
.any(CircularArray
),
565 avgRunTime
: expect
.any(Number
),
568 waitTimeHistory
: expect
.any(CircularArray
),
573 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
574 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThan(0)
577 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
578 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
579 ).workersVirtualTaskEndTimestamp
.length
580 ).toBe(pool
.workerNodes
.length
)
581 // We need to clean up the resources after our test
585 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
586 const pool
= new DynamicThreadPool(
589 './tests/worker-files/thread/testWorker.js',
590 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
592 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
593 const promises
= new Set()
594 const maxMultiplier
= 2
595 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
596 promises
.add(pool
.execute())
598 await Promise
.all(promises
)
599 for (const workerNode
of pool
.workerNodes
) {
600 expect(workerNode
.tasksUsage
).toStrictEqual({
603 runTime
: expect
.any(Number
),
604 runTimeHistory
: expect
.any(CircularArray
),
605 avgRunTime
: expect
.any(Number
),
608 waitTimeHistory
: expect
.any(CircularArray
),
613 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
614 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThan(0)
617 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
618 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
619 ).workersVirtualTaskEndTimestamp
.length
620 ).toBe(pool
.workerNodes
.length
)
621 // We need to clean up the resources after our test
625 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
626 const pool
= new DynamicThreadPool(
629 './tests/worker-files/thread/testWorker.js',
631 workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
,
632 workerChoiceStrategyOptions
: {
637 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
638 const promises
= new Set()
639 const maxMultiplier
= 2
640 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
641 promises
.add(pool
.execute())
643 await Promise
.all(promises
)
644 for (const workerNode
of pool
.workerNodes
) {
645 expect(workerNode
.tasksUsage
).toStrictEqual({
648 runTime
: expect
.any(Number
),
649 runTimeHistory
: expect
.any(CircularArray
),
651 medRunTime
: expect
.any(Number
),
653 waitTimeHistory
: expect
.any(CircularArray
),
658 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
659 expect(workerNode
.tasksUsage
.medRunTime
).toBeGreaterThan(0)
662 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
663 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
664 ).workersVirtualTaskEndTimestamp
.length
665 ).toBe(pool
.workerNodes
.length
)
666 // We need to clean up the resources after our test
670 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
671 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
672 let pool
= new FixedThreadPool(
674 './tests/worker-files/thread/testWorker.js'
677 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
679 ).workersVirtualTaskEndTimestamp
680 ).toBeInstanceOf(Array
)
682 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
684 ).workersVirtualTaskEndTimestamp
.length
686 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
688 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
690 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
692 ).workersVirtualTaskEndTimestamp
.length
694 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
696 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
698 ).workersVirtualTaskEndTimestamp
699 ).toBeInstanceOf(Array
)
701 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
703 ).workersVirtualTaskEndTimestamp
.length
706 pool
= new DynamicThreadPool(
709 './tests/worker-files/thread/testWorker.js'
712 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
714 ).workersVirtualTaskEndTimestamp
715 ).toBeInstanceOf(Array
)
717 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
719 ).workersVirtualTaskEndTimestamp
.length
721 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
723 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
725 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
727 ).workersVirtualTaskEndTimestamp
.length
729 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
731 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
733 ).workersVirtualTaskEndTimestamp
734 ).toBeInstanceOf(Array
)
736 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
738 ).workersVirtualTaskEndTimestamp
.length
740 // We need to clean up the resources after our test
744 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
745 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
746 let pool
= new FixedThreadPool(
748 './tests/worker-files/thread/testWorker.js',
749 { workerChoiceStrategy
}
752 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
762 pool
= new DynamicThreadPool(
765 './tests/worker-files/thread/testWorker.js',
766 { workerChoiceStrategy
}
769 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
778 // We need to clean up the resources after our test
782 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
783 const pool
= new FixedThreadPool(
785 './tests/worker-files/thread/testWorker.js',
786 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
788 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
789 const promises
= new Set()
790 const maxMultiplier
= 2
791 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
792 promises
.add(pool
.execute())
794 await Promise
.all(promises
)
795 for (const workerNode
of pool
.workerNodes
) {
796 expect(workerNode
.tasksUsage
).toStrictEqual({
797 ran
: expect
.any(Number
),
799 runTime
: expect
.any(Number
),
800 runTimeHistory
: expect
.any(CircularArray
),
801 avgRunTime
: expect
.any(Number
),
804 waitTimeHistory
: expect
.any(CircularArray
),
809 expect(workerNode
.tasksUsage
.ran
).toBeGreaterThanOrEqual(0)
810 expect(workerNode
.tasksUsage
.ran
).toBeLessThanOrEqual(max
* maxMultiplier
)
811 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThanOrEqual(0)
812 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThanOrEqual(0)
815 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
816 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
817 ).defaultWorkerWeight
820 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
821 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
822 ).workerVirtualTaskRunTime
823 ).toBeGreaterThanOrEqual(0)
824 // We need to clean up the resources after our test
828 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
829 const pool
= new DynamicThreadPool(
832 './tests/worker-files/thread/testWorker.js',
833 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
835 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
836 const promises
= new Set()
837 const maxMultiplier
= 2
838 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
839 promises
.add(pool
.execute())
841 await Promise
.all(promises
)
842 for (const workerNode
of pool
.workerNodes
) {
843 expect(workerNode
.tasksUsage
).toStrictEqual({
844 ran
: expect
.any(Number
),
846 runTime
: expect
.any(Number
),
847 runTimeHistory
: expect
.any(CircularArray
),
848 avgRunTime
: expect
.any(Number
),
851 waitTimeHistory
: expect
.any(CircularArray
),
856 expect(workerNode
.tasksUsage
.ran
).toBeGreaterThan(0)
857 expect(workerNode
.tasksUsage
.ran
).toBeLessThanOrEqual(max
* maxMultiplier
)
858 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
859 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThan(0)
862 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
863 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
864 ).defaultWorkerWeight
867 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
868 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
869 ).workerVirtualTaskRunTime
870 ).toBeGreaterThanOrEqual(0)
871 // We need to clean up the resources after our test
875 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
876 const pool
= new DynamicThreadPool(
879 './tests/worker-files/thread/testWorker.js',
881 workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
,
882 workerChoiceStrategyOptions
: {
887 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
888 const promises
= new Set()
889 const maxMultiplier
= 2
890 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
891 promises
.add(pool
.execute())
893 await Promise
.all(promises
)
894 for (const workerNode
of pool
.workerNodes
) {
895 expect(workerNode
.tasksUsage
).toStrictEqual({
896 ran
: expect
.any(Number
),
898 runTime
: expect
.any(Number
),
899 runTimeHistory
: expect
.any(CircularArray
),
901 medRunTime
: expect
.any(Number
),
903 waitTimeHistory
: expect
.any(CircularArray
),
908 expect(workerNode
.tasksUsage
.ran
).toBeGreaterThan(0)
909 expect(workerNode
.tasksUsage
.ran
).toBeLessThanOrEqual(max
* maxMultiplier
)
910 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
911 expect(workerNode
.tasksUsage
.medRunTime
).toBeGreaterThan(0)
914 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
915 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
916 ).defaultWorkerWeight
919 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
920 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
921 ).workerVirtualTaskRunTime
922 ).toBeGreaterThanOrEqual(0)
923 // We need to clean up the resources after our test
927 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
928 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
929 let pool
= new FixedThreadPool(
931 './tests/worker-files/thread/testWorker.js'
934 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
936 ).currentWorkerNodeId
939 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
941 ).defaultWorkerWeight
944 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
946 ).workerVirtualTaskRunTime
948 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
950 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
951 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
952 ).currentWorkerNodeId
955 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
956 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
957 ).defaultWorkerWeight
960 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
962 ).workerVirtualTaskRunTime
965 pool
= new DynamicThreadPool(
968 './tests/worker-files/thread/testWorker.js'
971 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
973 ).currentWorkerNodeId
976 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
978 ).defaultWorkerWeight
981 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
983 ).workerVirtualTaskRunTime
985 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
987 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
988 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
989 ).currentWorkerNodeId
992 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
993 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
994 ).defaultWorkerWeight
997 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
999 ).workerVirtualTaskRunTime
1001 // We need to clean up the resources after our test
1002 await pool
.destroy()
1005 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1006 const workerChoiceStrategy
=
1007 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1008 let pool
= new FixedThreadPool(
1010 './tests/worker-files/thread/testWorker.js',
1011 { workerChoiceStrategy
}
1014 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
1023 await pool
.destroy()
1024 pool
= new DynamicThreadPool(
1027 './tests/worker-files/thread/testWorker.js',
1028 { workerChoiceStrategy
}
1031 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
1040 // We need to clean up the resources after our test
1041 await pool
.destroy()
1044 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1045 const pool
= new FixedThreadPool(
1047 './tests/worker-files/thread/testWorker.js',
1049 workerChoiceStrategy
:
1050 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1053 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1054 const promises
= new Set()
1055 const maxMultiplier
= 2
1056 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1057 promises
.add(pool
.execute())
1059 await Promise
.all(promises
)
1060 for (const workerNode
of pool
.workerNodes
) {
1061 expect(workerNode
.tasksUsage
).toStrictEqual({
1065 runTimeHistory
: expect
.any(CircularArray
),
1069 waitTimeHistory
: expect
.any(CircularArray
),
1076 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1077 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1078 ).defaultWorkerWeight
1079 ).toBeGreaterThan(0)
1081 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1082 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1086 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1087 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1088 ).currentWorkerNodeId
1091 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1092 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1095 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1096 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1097 ).defaultWorkerWeight
1099 // We need to clean up the resources after our test
1100 await pool
.destroy()
1103 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1104 const pool
= new DynamicThreadPool(
1107 './tests/worker-files/thread/testWorker.js',
1109 workerChoiceStrategy
:
1110 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1113 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1114 const promises
= new Set()
1115 const maxMultiplier
= 2
1116 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1117 promises
.add(pool
.execute())
1119 await Promise
.all(promises
)
1120 for (const workerNode
of pool
.workerNodes
) {
1121 expect(workerNode
.tasksUsage
).toStrictEqual({
1125 runTimeHistory
: expect
.any(CircularArray
),
1129 waitTimeHistory
: expect
.any(CircularArray
),
1136 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1137 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1138 ).defaultWorkerWeight
1139 ).toBeGreaterThan(0)
1141 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1142 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1146 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1147 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1148 ).currentWorkerNodeId
1151 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1152 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1155 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1156 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1157 ).defaultWorkerWeight
1159 // We need to clean up the resources after our test
1160 await pool
.destroy()
1163 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1164 const workerChoiceStrategy
=
1165 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1166 let pool
= new FixedThreadPool(
1168 './tests/worker-files/thread/testWorker.js'
1171 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1172 workerChoiceStrategy
1176 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1177 workerChoiceStrategy
1178 ).currentWorkerNodeId
1181 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1182 workerChoiceStrategy
1183 ).defaultWorkerWeight
1186 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1187 workerChoiceStrategy
1190 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1192 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1193 workerChoiceStrategy
1197 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1198 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1199 ).currentWorkerNodeId
1202 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1203 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1204 ).defaultWorkerWeight
1205 ).toBeGreaterThan(0)
1207 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1208 workerChoiceStrategy
1211 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1212 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1213 ).defaultWorkerWeight
1215 await pool
.destroy()
1216 pool
= new DynamicThreadPool(
1219 './tests/worker-files/thread/testWorker.js'
1222 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1223 workerChoiceStrategy
1227 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1228 workerChoiceStrategy
1229 ).currentWorkerNodeId
1232 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1233 workerChoiceStrategy
1234 ).defaultWorkerWeight
1237 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1238 workerChoiceStrategy
1241 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1243 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1244 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1245 ).currentWorkerNodeId
1248 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1249 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1250 ).defaultWorkerWeight
1251 ).toBeGreaterThan(0)
1253 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1254 workerChoiceStrategy
1257 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1258 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1259 ).defaultWorkerWeight
1261 // We need to clean up the resources after our test
1262 await pool
.destroy()
1265 it('Verify unknown strategy throw error', () => {
1268 new DynamicThreadPool(
1271 './tests/worker-files/thread/testWorker.js',
1272 { workerChoiceStrategy
: 'UNKNOWN_STRATEGY' }
1274 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")