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
}
124 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
134 pool
= new DynamicThreadPool(
137 './tests/worker-files/thread/testWorker.js',
138 { workerChoiceStrategy
}
140 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
149 // We need to clean up the resources after our test
153 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
154 const pool
= new FixedThreadPool(
156 './tests/worker-files/thread/testWorker.js',
157 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
159 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
160 const promises
= new Set()
161 const maxMultiplier
= 2
162 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
163 promises
.add(pool
.execute())
165 await Promise
.all(promises
)
166 for (const workerNode
of pool
.workerNodes
) {
167 expect(workerNode
.tasksUsage
).toStrictEqual({
171 runTimeHistory
: expect
.any(CircularArray
),
175 waitTimeHistory
: expect
.any(CircularArray
),
183 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
184 WorkerChoiceStrategies
.ROUND_ROBIN
187 // We need to clean up the resources after our test
191 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
192 const pool
= new DynamicThreadPool(
195 './tests/worker-files/thread/testWorker.js',
196 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
198 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
199 const promises
= new Set()
200 const maxMultiplier
= 2
201 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
202 promises
.add(pool
.execute())
204 await Promise
.all(promises
)
205 for (const workerNode
of pool
.workerNodes
) {
206 expect(workerNode
.tasksUsage
).toStrictEqual({
210 runTimeHistory
: expect
.any(CircularArray
),
214 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
}
303 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
313 pool
= new DynamicThreadPool(
316 './tests/worker-files/thread/testWorker.js',
317 { workerChoiceStrategy
}
319 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
328 // We need to clean up the resources after our test
332 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
333 const pool
= new FixedThreadPool(
335 './tests/worker-files/thread/testWorker.js',
336 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
338 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
339 const promises
= new Set()
340 const maxMultiplier
= 2
341 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
342 promises
.add(pool
.execute())
344 await Promise
.all(promises
)
345 for (const workerNode
of pool
.workerNodes
) {
346 expect(workerNode
.tasksUsage
).toStrictEqual({
350 runTimeHistory
: expect
.any(CircularArray
),
354 waitTimeHistory
: expect
.any(CircularArray
),
361 // We need to clean up the resources after our test
365 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
366 const pool
= new DynamicThreadPool(
369 './tests/worker-files/thread/testWorker.js',
370 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
372 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
373 const promises
= new Set()
374 const maxMultiplier
= 2
375 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
376 promises
.add(pool
.execute())
378 await Promise
.all(promises
)
379 for (const workerNode
of pool
.workerNodes
) {
380 expect(workerNode
.tasksUsage
).toStrictEqual({
384 runTimeHistory
: expect
.any(CircularArray
),
388 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
}
406 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
416 pool
= new DynamicThreadPool(
419 './tests/worker-files/thread/testWorker.js',
420 { workerChoiceStrategy
}
422 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
431 // We need to clean up the resources after our test
435 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
436 const pool
= new FixedThreadPool(
438 './tests/worker-files/thread/testWorker.js',
439 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
441 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
442 const promises
= new Set()
443 const maxMultiplier
= 2
444 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
445 promises
.add(pool
.execute())
447 await Promise
.all(promises
)
448 for (const workerNode
of pool
.workerNodes
) {
449 expect(workerNode
.tasksUsage
).toStrictEqual({
450 ran
: expect
.any(Number
),
452 runTime
: expect
.any(Number
),
453 runTimeHistory
: expect
.any(CircularArray
),
457 waitTimeHistory
: expect
.any(CircularArray
),
463 expect(workerNode
.tasksUsage
.ran
).toBeGreaterThanOrEqual(0)
464 expect(workerNode
.tasksUsage
.ran
).toBeLessThanOrEqual(max
* maxMultiplier
)
465 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThanOrEqual(0)
467 // We need to clean up the resources after our test
471 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
472 const pool
= new DynamicThreadPool(
475 './tests/worker-files/thread/testWorker.js',
476 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
478 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
479 const promises
= new Set()
480 const maxMultiplier
= 2
481 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
482 promises
.add(pool
.execute())
484 await Promise
.all(promises
)
485 for (const workerNode
of pool
.workerNodes
) {
486 expect(workerNode
.tasksUsage
).toStrictEqual({
487 ran
: expect
.any(Number
),
489 runTime
: expect
.any(Number
),
490 runTimeHistory
: expect
.any(CircularArray
),
494 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
}
515 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
525 pool
= new DynamicThreadPool(
528 './tests/worker-files/thread/testWorker.js',
529 { workerChoiceStrategy
}
531 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
540 // We need to clean up the resources after our test
544 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
545 const pool
= new FixedThreadPool(
547 './tests/worker-files/thread/testWorker.js',
548 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
550 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
551 const promises
= new Set()
552 const maxMultiplier
= 2
553 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
554 promises
.add(pool
.execute())
556 await Promise
.all(promises
)
557 for (const workerNode
of pool
.workerNodes
) {
558 expect(workerNode
.tasksUsage
).toStrictEqual({
561 runTime
: expect
.any(Number
),
562 runTimeHistory
: expect
.any(CircularArray
),
563 avgRunTime
: expect
.any(Number
),
566 waitTimeHistory
: expect
.any(CircularArray
),
572 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
573 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThan(0)
576 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
577 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
578 ).workersVirtualTaskEndTimestamp
.length
579 ).toBe(pool
.workerNodes
.length
)
580 // We need to clean up the resources after our test
584 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
585 const pool
= new DynamicThreadPool(
588 './tests/worker-files/thread/testWorker.js',
589 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
591 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
592 const promises
= new Set()
593 const maxMultiplier
= 2
594 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
595 promises
.add(pool
.execute())
597 await Promise
.all(promises
)
598 for (const workerNode
of pool
.workerNodes
) {
599 expect(workerNode
.tasksUsage
).toStrictEqual({
602 runTime
: expect
.any(Number
),
603 runTimeHistory
: expect
.any(CircularArray
),
604 avgRunTime
: expect
.any(Number
),
607 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
),
659 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
660 expect(workerNode
.tasksUsage
.medRunTime
).toBeGreaterThan(0)
663 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
664 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
665 ).workersVirtualTaskEndTimestamp
.length
666 ).toBe(pool
.workerNodes
.length
)
667 // We need to clean up the resources after our test
671 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
672 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
673 let pool
= new FixedThreadPool(
675 './tests/worker-files/thread/testWorker.js'
678 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
680 ).workersVirtualTaskEndTimestamp
681 ).toBeInstanceOf(Array
)
683 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
685 ).workersVirtualTaskEndTimestamp
.length
687 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
689 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
691 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
693 ).workersVirtualTaskEndTimestamp
.length
695 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
697 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
699 ).workersVirtualTaskEndTimestamp
700 ).toBeInstanceOf(Array
)
702 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
704 ).workersVirtualTaskEndTimestamp
.length
707 pool
= new DynamicThreadPool(
710 './tests/worker-files/thread/testWorker.js'
713 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
715 ).workersVirtualTaskEndTimestamp
716 ).toBeInstanceOf(Array
)
718 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
720 ).workersVirtualTaskEndTimestamp
.length
722 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
724 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
726 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
728 ).workersVirtualTaskEndTimestamp
.length
730 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
732 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
734 ).workersVirtualTaskEndTimestamp
735 ).toBeInstanceOf(Array
)
737 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
739 ).workersVirtualTaskEndTimestamp
.length
741 // We need to clean up the resources after our test
745 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
746 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
747 let pool
= new FixedThreadPool(
749 './tests/worker-files/thread/testWorker.js',
750 { workerChoiceStrategy
}
752 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
762 pool
= new DynamicThreadPool(
765 './tests/worker-files/thread/testWorker.js',
766 { workerChoiceStrategy
}
768 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
777 // We need to clean up the resources after our test
781 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
782 const pool
= new FixedThreadPool(
784 './tests/worker-files/thread/testWorker.js',
785 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
787 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
788 const promises
= new Set()
789 const maxMultiplier
= 2
790 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
791 promises
.add(pool
.execute())
793 await Promise
.all(promises
)
794 for (const workerNode
of pool
.workerNodes
) {
795 expect(workerNode
.tasksUsage
).toStrictEqual({
796 ran
: expect
.any(Number
),
798 runTime
: expect
.any(Number
),
799 runTimeHistory
: expect
.any(CircularArray
),
800 avgRunTime
: expect
.any(Number
),
803 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
),
857 expect(workerNode
.tasksUsage
.ran
).toBeGreaterThan(0)
858 expect(workerNode
.tasksUsage
.ran
).toBeLessThanOrEqual(max
* maxMultiplier
)
859 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
860 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThan(0)
863 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
864 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
865 ).defaultWorkerWeight
868 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
869 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
870 ).workerVirtualTaskRunTime
871 ).toBeGreaterThanOrEqual(0)
872 // We need to clean up the resources after our test
876 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
877 const pool
= new DynamicThreadPool(
880 './tests/worker-files/thread/testWorker.js',
882 workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
,
883 workerChoiceStrategyOptions
: {
888 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
889 const promises
= new Set()
890 const maxMultiplier
= 2
891 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
892 promises
.add(pool
.execute())
894 await Promise
.all(promises
)
895 for (const workerNode
of pool
.workerNodes
) {
896 expect(workerNode
.tasksUsage
).toStrictEqual({
897 ran
: expect
.any(Number
),
899 runTime
: expect
.any(Number
),
900 runTimeHistory
: expect
.any(CircularArray
),
902 medRunTime
: expect
.any(Number
),
904 waitTimeHistory
: expect
.any(CircularArray
),
910 expect(workerNode
.tasksUsage
.ran
).toBeGreaterThan(0)
911 expect(workerNode
.tasksUsage
.ran
).toBeLessThanOrEqual(max
* maxMultiplier
)
912 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
913 expect(workerNode
.tasksUsage
.medRunTime
).toBeGreaterThan(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 internals are resets after setting it', async () => {
930 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
931 let pool
= new FixedThreadPool(
933 './tests/worker-files/thread/testWorker.js'
936 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
938 ).currentWorkerNodeId
941 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
943 ).defaultWorkerWeight
946 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
948 ).workerVirtualTaskRunTime
950 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
952 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
953 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
954 ).currentWorkerNodeId
957 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
958 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
959 ).defaultWorkerWeight
962 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
964 ).workerVirtualTaskRunTime
967 pool
= new DynamicThreadPool(
970 './tests/worker-files/thread/testWorker.js'
973 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
975 ).currentWorkerNodeId
978 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
980 ).defaultWorkerWeight
983 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
985 ).workerVirtualTaskRunTime
987 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
989 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
990 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
991 ).currentWorkerNodeId
994 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
995 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
996 ).defaultWorkerWeight
999 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1000 workerChoiceStrategy
1001 ).workerVirtualTaskRunTime
1003 // We need to clean up the resources after our test
1004 await pool
.destroy()
1007 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1008 const workerChoiceStrategy
=
1009 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1010 let pool
= new FixedThreadPool(
1012 './tests/worker-files/thread/testWorker.js',
1013 { workerChoiceStrategy
}
1015 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
1024 await pool
.destroy()
1025 pool
= new DynamicThreadPool(
1028 './tests/worker-files/thread/testWorker.js',
1029 { workerChoiceStrategy
}
1031 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
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
),
1077 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1078 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1079 ).defaultWorkerWeight
1080 ).toBeGreaterThan(0)
1082 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1083 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1087 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1088 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1089 ).currentWorkerNodeId
1092 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1093 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1096 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1097 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1098 ).defaultWorkerWeight
1100 // We need to clean up the resources after our test
1101 await pool
.destroy()
1104 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1105 const pool
= new DynamicThreadPool(
1108 './tests/worker-files/thread/testWorker.js',
1110 workerChoiceStrategy
:
1111 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1114 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1115 const promises
= new Set()
1116 const maxMultiplier
= 2
1117 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1118 promises
.add(pool
.execute())
1120 await Promise
.all(promises
)
1121 for (const workerNode
of pool
.workerNodes
) {
1122 expect(workerNode
.tasksUsage
).toStrictEqual({
1126 runTimeHistory
: expect
.any(CircularArray
),
1130 waitTimeHistory
: expect
.any(CircularArray
),
1138 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1139 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1140 ).defaultWorkerWeight
1141 ).toBeGreaterThan(0)
1143 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1144 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1148 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1149 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1150 ).currentWorkerNodeId
1153 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1154 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1157 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1158 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1159 ).defaultWorkerWeight
1161 // We need to clean up the resources after our test
1162 await pool
.destroy()
1165 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1166 const workerChoiceStrategy
=
1167 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1168 let pool
= new FixedThreadPool(
1170 './tests/worker-files/thread/testWorker.js'
1173 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1174 workerChoiceStrategy
1178 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1179 workerChoiceStrategy
1180 ).currentWorkerNodeId
1183 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1184 workerChoiceStrategy
1185 ).defaultWorkerWeight
1188 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1189 workerChoiceStrategy
1192 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1194 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1195 workerChoiceStrategy
1199 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1200 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1201 ).currentWorkerNodeId
1204 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1205 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1206 ).defaultWorkerWeight
1207 ).toBeGreaterThan(0)
1209 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1210 workerChoiceStrategy
1213 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1214 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1215 ).defaultWorkerWeight
1217 await pool
.destroy()
1218 pool
= new DynamicThreadPool(
1221 './tests/worker-files/thread/testWorker.js'
1224 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1225 workerChoiceStrategy
1229 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1230 workerChoiceStrategy
1231 ).currentWorkerNodeId
1234 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1235 workerChoiceStrategy
1236 ).defaultWorkerWeight
1239 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1240 workerChoiceStrategy
1243 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1245 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1246 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1247 ).currentWorkerNodeId
1250 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1251 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1252 ).defaultWorkerWeight
1253 ).toBeGreaterThan(0)
1255 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1256 workerChoiceStrategy
1259 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1260 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1261 ).defaultWorkerWeight
1263 // We need to clean up the resources after our test
1264 await pool
.destroy()
1267 it('Verify unknown strategy throw error', () => {
1270 new DynamicThreadPool(
1273 './tests/worker-files/thread/testWorker.js',
1274 { workerChoiceStrategy
: 'UNKNOWN_STRATEGY' }
1276 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")