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
.getTaskStatisticsRequirements()
136 pool
= new DynamicThreadPool(
139 './tests/worker-files/thread/testWorker.js',
140 { workerChoiceStrategy
}
143 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
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
.workerUsage
).toStrictEqual({
173 executed
: maxMultiplier
,
182 history
: expect
.any(CircularArray
)
188 history
: expect
.any(CircularArray
)
194 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
195 WorkerChoiceStrategies
.ROUND_ROBIN
198 // We need to clean up the resources after our test
202 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
203 const pool
= new DynamicThreadPool(
206 './tests/worker-files/thread/testWorker.js',
207 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
209 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
210 const promises
= new Set()
211 const maxMultiplier
= 2
212 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
213 promises
.add(pool
.execute())
215 await Promise
.all(promises
)
216 for (const workerNode
of pool
.workerNodes
) {
217 expect(workerNode
.workerUsage
).toStrictEqual({
219 executed
: maxMultiplier
,
228 history
: expect
.any(CircularArray
)
234 history
: expect
.any(CircularArray
)
240 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
241 WorkerChoiceStrategies
.ROUND_ROBIN
244 // We need to clean up the resources after our test
248 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
249 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
250 let pool
= new FixedClusterPool(
252 './tests/worker-files/cluster/testWorker.js',
253 { workerChoiceStrategy
}
255 let results
= new Set()
256 for (let i
= 0; i
< max
; i
++) {
257 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.id
)
259 expect(results
.size
).toBe(max
)
261 pool
= new FixedThreadPool(
263 './tests/worker-files/thread/testWorker.js',
264 { workerChoiceStrategy
}
267 for (let i
= 0; i
< max
; i
++) {
268 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.threadId
)
270 expect(results
.size
).toBe(max
)
274 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
275 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
276 let pool
= new FixedThreadPool(
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
293 pool
= new DynamicThreadPool(
296 './tests/worker-files/thread/testWorker.js',
297 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
300 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
304 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
306 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
307 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
310 // We need to clean up the resources after our test
314 it('Verify LEAST_USED strategy default tasks usage statistics requirements', async () => {
315 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
316 let pool
= new FixedThreadPool(
318 './tests/worker-files/thread/testWorker.js',
319 { workerChoiceStrategy
}
322 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
333 pool
= new DynamicThreadPool(
336 './tests/worker-files/thread/testWorker.js',
337 { workerChoiceStrategy
}
340 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
350 // We need to clean up the resources after our test
354 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
355 const pool
= new FixedThreadPool(
357 './tests/worker-files/thread/testWorker.js',
358 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
360 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
361 const promises
= new Set()
362 const maxMultiplier
= 2
363 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
364 promises
.add(pool
.execute())
366 await Promise
.all(promises
)
367 for (const workerNode
of pool
.workerNodes
) {
368 expect(workerNode
.workerUsage
).toStrictEqual({
370 executed
: maxMultiplier
,
379 history
: expect
.any(CircularArray
)
385 history
: expect
.any(CircularArray
)
390 // We need to clean up the resources after our test
394 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
395 const pool
= new DynamicThreadPool(
398 './tests/worker-files/thread/testWorker.js',
399 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
401 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
402 const promises
= new Set()
403 const maxMultiplier
= 2
404 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
405 promises
.add(pool
.execute())
407 await Promise
.all(promises
)
408 for (const workerNode
of pool
.workerNodes
) {
409 expect(workerNode
.workerUsage
).toStrictEqual({
411 executed
: maxMultiplier
,
420 history
: expect
.any(CircularArray
)
426 history
: expect
.any(CircularArray
)
432 // We need to clean up the resources after our test
436 it('Verify LEAST_BUSY strategy default tasks usage statistics requirements', async () => {
437 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
438 let pool
= new FixedThreadPool(
440 './tests/worker-files/thread/testWorker.js',
441 { workerChoiceStrategy
}
444 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
455 pool
= new DynamicThreadPool(
458 './tests/worker-files/thread/testWorker.js',
459 { workerChoiceStrategy
}
462 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
472 // We need to clean up the resources after our test
476 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
477 const pool
= new FixedThreadPool(
479 './tests/worker-files/thread/testWorker.js',
480 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
482 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
483 const promises
= new Set()
484 const maxMultiplier
= 2
485 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
486 promises
.add(pool
.execute())
488 await Promise
.all(promises
)
489 for (const workerNode
of pool
.workerNodes
) {
490 expect(workerNode
.workerUsage
).toStrictEqual({
492 executed
: expect
.any(Number
),
498 aggregation
: expect
.any(Number
),
501 history
: expect
.any(CircularArray
)
507 history
: expect
.any(CircularArray
)
511 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
512 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
515 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThanOrEqual(
519 // We need to clean up the resources after our test
523 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
524 const pool
= new DynamicThreadPool(
527 './tests/worker-files/thread/testWorker.js',
528 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
530 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
531 const promises
= new Set()
532 const maxMultiplier
= 2
533 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
534 promises
.add(pool
.execute())
536 await Promise
.all(promises
)
537 for (const workerNode
of pool
.workerNodes
) {
538 expect(workerNode
.workerUsage
).toStrictEqual({
540 executed
: expect
.any(Number
),
546 aggregation
: expect
.any(Number
),
549 history
: expect
.any(CircularArray
)
555 history
: expect
.any(CircularArray
)
559 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
560 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
563 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
565 // We need to clean up the resources after our test
569 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
570 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
571 let pool
= new FixedThreadPool(
573 './tests/worker-files/thread/testWorker.js',
574 { workerChoiceStrategy
}
577 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
588 pool
= new DynamicThreadPool(
591 './tests/worker-files/thread/testWorker.js',
592 { workerChoiceStrategy
}
595 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
605 // We need to clean up the resources after our test
609 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
610 const pool
= new FixedThreadPool(
612 './tests/worker-files/thread/testWorker.js',
613 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
615 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
616 const promises
= new Set()
617 const maxMultiplier
= 2
618 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
619 promises
.add(pool
.execute())
621 await Promise
.all(promises
)
622 for (const workerNode
of pool
.workerNodes
) {
623 expect(workerNode
.workerUsage
).toStrictEqual({
625 executed
: maxMultiplier
,
631 aggregation
: expect
.any(Number
),
632 average
: expect
.any(Number
),
634 history
: expect
.any(CircularArray
)
640 history
: expect
.any(CircularArray
)
644 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
645 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
648 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
649 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
650 ).workersVirtualTaskEndTimestamp
.length
651 ).toBe(pool
.workerNodes
.length
)
652 // We need to clean up the resources after our test
656 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
657 const pool
= new DynamicThreadPool(
660 './tests/worker-files/thread/testWorker.js',
661 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
663 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
664 const promises
= new Set()
665 const maxMultiplier
= 2
666 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
667 promises
.add(pool
.execute())
669 await Promise
.all(promises
)
670 for (const workerNode
of pool
.workerNodes
) {
671 expect(workerNode
.workerUsage
).toStrictEqual({
673 executed
: maxMultiplier
,
679 aggregation
: expect
.any(Number
),
680 average
: expect
.any(Number
),
682 history
: expect
.any(CircularArray
)
688 history
: expect
.any(CircularArray
)
692 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
693 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
696 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
697 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
698 ).workersVirtualTaskEndTimestamp
.length
699 ).toBe(pool
.workerNodes
.length
)
700 // We need to clean up the resources after our test
704 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
705 const pool
= new DynamicThreadPool(
708 './tests/worker-files/thread/testWorker.js',
710 workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
,
711 workerChoiceStrategyOptions
: {
716 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
717 const promises
= new Set()
718 const maxMultiplier
= 2
719 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
720 promises
.add(pool
.execute())
722 await Promise
.all(promises
)
723 for (const workerNode
of pool
.workerNodes
) {
724 expect(workerNode
.workerUsage
).toStrictEqual({
726 executed
: maxMultiplier
,
732 aggregation
: expect
.any(Number
),
734 median
: expect
.any(Number
),
735 history
: expect
.any(CircularArray
)
741 history
: expect
.any(CircularArray
)
745 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
746 expect(workerNode
.workerUsage
.runTime
.median
).toBeGreaterThan(0)
749 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
750 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
751 ).workersVirtualTaskEndTimestamp
.length
752 ).toBe(pool
.workerNodes
.length
)
753 // We need to clean up the resources after our test
757 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
758 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
759 let pool
= new FixedThreadPool(
761 './tests/worker-files/thread/testWorker.js'
764 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
766 ).workersVirtualTaskEndTimestamp
767 ).toBeInstanceOf(Array
)
769 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
771 ).workersVirtualTaskEndTimestamp
.length
773 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
775 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
777 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
779 ).workersVirtualTaskEndTimestamp
.length
781 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
783 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
785 ).workersVirtualTaskEndTimestamp
786 ).toBeInstanceOf(Array
)
788 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
790 ).workersVirtualTaskEndTimestamp
.length
793 pool
= new DynamicThreadPool(
796 './tests/worker-files/thread/testWorker.js'
799 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
801 ).workersVirtualTaskEndTimestamp
802 ).toBeInstanceOf(Array
)
804 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
806 ).workersVirtualTaskEndTimestamp
.length
808 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
810 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
812 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
814 ).workersVirtualTaskEndTimestamp
.length
816 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
818 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
820 ).workersVirtualTaskEndTimestamp
821 ).toBeInstanceOf(Array
)
823 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
825 ).workersVirtualTaskEndTimestamp
.length
827 // We need to clean up the resources after our test
831 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
832 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
833 let pool
= new FixedThreadPool(
835 './tests/worker-files/thread/testWorker.js',
836 { workerChoiceStrategy
}
839 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
850 pool
= new DynamicThreadPool(
853 './tests/worker-files/thread/testWorker.js',
854 { workerChoiceStrategy
}
857 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
867 // We need to clean up the resources after our test
871 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
872 const pool
= new FixedThreadPool(
874 './tests/worker-files/thread/testWorker.js',
875 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
877 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
878 const promises
= new Set()
879 const maxMultiplier
= 2
880 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
881 promises
.add(pool
.execute())
883 await Promise
.all(promises
)
884 for (const workerNode
of pool
.workerNodes
) {
885 expect(workerNode
.workerUsage
).toStrictEqual({
887 executed
: expect
.any(Number
),
893 aggregation
: expect
.any(Number
),
894 average
: expect
.any(Number
),
896 history
: expect
.any(CircularArray
)
902 history
: expect
.any(CircularArray
)
906 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
907 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
910 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThanOrEqual(
913 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThanOrEqual(0)
916 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
917 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
918 ).defaultWorkerWeight
921 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
922 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
923 ).workerVirtualTaskRunTime
924 ).toBeGreaterThanOrEqual(0)
925 // We need to clean up the resources after our test
929 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
930 const pool
= new DynamicThreadPool(
933 './tests/worker-files/thread/testWorker.js',
934 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
936 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
937 const promises
= new Set()
938 const maxMultiplier
= 2
939 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
940 promises
.add(pool
.execute())
942 await Promise
.all(promises
)
943 for (const workerNode
of pool
.workerNodes
) {
944 expect(workerNode
.workerUsage
).toStrictEqual({
946 executed
: expect
.any(Number
),
952 aggregation
: expect
.any(Number
),
953 average
: expect
.any(Number
),
955 history
: expect
.any(CircularArray
)
961 history
: expect
.any(CircularArray
)
965 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
966 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
969 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
970 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
973 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
974 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
975 ).defaultWorkerWeight
978 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
979 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
980 ).workerVirtualTaskRunTime
981 ).toBeGreaterThanOrEqual(0)
982 // We need to clean up the resources after our test
986 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
987 const pool
= new DynamicThreadPool(
990 './tests/worker-files/thread/testWorker.js',
992 workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
,
993 workerChoiceStrategyOptions
: {
998 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
999 const promises
= new Set()
1000 const maxMultiplier
= 2
1001 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1002 promises
.add(pool
.execute())
1004 await Promise
.all(promises
)
1005 for (const workerNode
of pool
.workerNodes
) {
1006 expect(workerNode
.workerUsage
).toStrictEqual({
1008 executed
: expect
.any(Number
),
1014 aggregation
: expect
.any(Number
),
1016 median
: expect
.any(Number
),
1017 history
: expect
.any(CircularArray
)
1023 history
: expect
.any(CircularArray
)
1027 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
1028 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1031 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
1032 expect(workerNode
.workerUsage
.runTime
.median
).toBeGreaterThan(0)
1035 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1036 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1037 ).defaultWorkerWeight
1038 ).toBeGreaterThan(0)
1040 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1041 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1042 ).workerVirtualTaskRunTime
1043 ).toBeGreaterThanOrEqual(0)
1044 // We need to clean up the resources after our test
1045 await pool
.destroy()
1048 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1049 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1050 let pool
= new FixedThreadPool(
1052 './tests/worker-files/thread/testWorker.js'
1055 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1056 workerChoiceStrategy
1057 ).currentWorkerNodeId
1060 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1061 workerChoiceStrategy
1062 ).defaultWorkerWeight
1065 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1066 workerChoiceStrategy
1067 ).workerVirtualTaskRunTime
1069 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1071 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1072 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1073 ).currentWorkerNodeId
1076 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1077 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1078 ).defaultWorkerWeight
1079 ).toBeGreaterThan(0)
1081 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1082 workerChoiceStrategy
1083 ).workerVirtualTaskRunTime
1085 await pool
.destroy()
1086 pool
= new DynamicThreadPool(
1089 './tests/worker-files/thread/testWorker.js'
1092 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1093 workerChoiceStrategy
1094 ).currentWorkerNodeId
1097 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1098 workerChoiceStrategy
1099 ).defaultWorkerWeight
1102 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1103 workerChoiceStrategy
1104 ).workerVirtualTaskRunTime
1106 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1108 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1109 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1110 ).currentWorkerNodeId
1113 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1114 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1115 ).defaultWorkerWeight
1116 ).toBeGreaterThan(0)
1118 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1119 workerChoiceStrategy
1120 ).workerVirtualTaskRunTime
1122 // We need to clean up the resources after our test
1123 await pool
.destroy()
1126 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1127 const workerChoiceStrategy
=
1128 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1129 let pool
= new FixedThreadPool(
1131 './tests/worker-files/thread/testWorker.js',
1132 { workerChoiceStrategy
}
1135 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1145 await pool
.destroy()
1146 pool
= new DynamicThreadPool(
1149 './tests/worker-files/thread/testWorker.js',
1150 { workerChoiceStrategy
}
1153 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1163 // We need to clean up the resources after our test
1164 await pool
.destroy()
1167 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1168 const pool
= new FixedThreadPool(
1170 './tests/worker-files/thread/testWorker.js',
1172 workerChoiceStrategy
:
1173 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1176 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1177 const promises
= new Set()
1178 const maxMultiplier
= 2
1179 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1180 promises
.add(pool
.execute())
1182 await Promise
.all(promises
)
1183 for (const workerNode
of pool
.workerNodes
) {
1184 expect(workerNode
.workerUsage
).toStrictEqual({
1186 executed
: maxMultiplier
,
1195 history
: expect
.any(CircularArray
)
1201 history
: expect
.any(CircularArray
)
1207 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1208 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1209 ).defaultWorkerWeight
1210 ).toBeGreaterThan(0)
1212 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1213 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1217 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1218 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1219 ).currentWorkerNodeId
1222 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1223 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1226 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1227 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1228 ).defaultWorkerWeight
1230 // We need to clean up the resources after our test
1231 await pool
.destroy()
1234 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1235 const pool
= new DynamicThreadPool(
1238 './tests/worker-files/thread/testWorker.js',
1240 workerChoiceStrategy
:
1241 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1244 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1245 const promises
= new Set()
1246 const maxMultiplier
= 2
1247 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1248 promises
.add(pool
.execute())
1250 await Promise
.all(promises
)
1251 for (const workerNode
of pool
.workerNodes
) {
1252 expect(workerNode
.workerUsage
).toStrictEqual({
1254 executed
: maxMultiplier
,
1263 history
: expect
.any(CircularArray
)
1269 history
: expect
.any(CircularArray
)
1275 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1276 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1277 ).defaultWorkerWeight
1278 ).toBeGreaterThan(0)
1280 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1281 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1285 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1286 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1287 ).currentWorkerNodeId
1290 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1291 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1294 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1295 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1296 ).defaultWorkerWeight
1298 // We need to clean up the resources after our test
1299 await pool
.destroy()
1302 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1303 const workerChoiceStrategy
=
1304 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1305 let pool
= new FixedThreadPool(
1307 './tests/worker-files/thread/testWorker.js'
1310 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1311 workerChoiceStrategy
1315 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1316 workerChoiceStrategy
1317 ).currentWorkerNodeId
1320 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1321 workerChoiceStrategy
1322 ).defaultWorkerWeight
1325 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1326 workerChoiceStrategy
1329 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1331 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1332 workerChoiceStrategy
1336 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1337 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1338 ).currentWorkerNodeId
1341 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1342 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1343 ).defaultWorkerWeight
1344 ).toBeGreaterThan(0)
1346 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1347 workerChoiceStrategy
1350 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1351 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1352 ).defaultWorkerWeight
1354 await pool
.destroy()
1355 pool
= new DynamicThreadPool(
1358 './tests/worker-files/thread/testWorker.js'
1361 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1362 workerChoiceStrategy
1366 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1367 workerChoiceStrategy
1368 ).currentWorkerNodeId
1371 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1372 workerChoiceStrategy
1373 ).defaultWorkerWeight
1376 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1377 workerChoiceStrategy
1380 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1382 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1383 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1384 ).currentWorkerNodeId
1387 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1388 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1389 ).defaultWorkerWeight
1390 ).toBeGreaterThan(0)
1392 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1393 workerChoiceStrategy
1396 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1397 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1398 ).defaultWorkerWeight
1400 // We need to clean up the resources after our test
1401 await pool
.destroy()
1404 it('Verify unknown strategy throw error', () => {
1407 new DynamicThreadPool(
1410 './tests/worker-files/thread/testWorker.js',
1411 { workerChoiceStrategy
: 'UNKNOWN_STRATEGY' }
1413 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")