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
),
183 // We need to clean up the resources after our test
187 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
188 const pool
= new DynamicThreadPool(
191 './tests/worker-files/thread/testWorker.js',
192 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
194 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
195 const promises
= new Set()
196 const maxMultiplier
= 2
197 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
198 promises
.add(pool
.execute())
200 await Promise
.all(promises
)
201 for (const workerNode
of pool
.workerNodes
) {
202 expect(workerNode
.tasksUsage
).toStrictEqual({
206 runTimeHistory
: expect
.any(CircularArray
),
210 waitTimeHistory
: expect
.any(CircularArray
),
216 // We need to clean up the resources after our test
220 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
221 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
222 let pool
= new FixedClusterPool(
224 './tests/worker-files/cluster/testWorker.js',
225 { workerChoiceStrategy
}
227 let results
= new Set()
228 for (let i
= 0; i
< max
; i
++) {
229 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.id
)
231 expect(results
.size
).toBe(max
)
233 pool
= new FixedThreadPool(
235 './tests/worker-files/thread/testWorker.js',
236 { workerChoiceStrategy
}
239 for (let i
= 0; i
< max
; i
++) {
240 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.threadId
)
242 expect(results
.size
).toBe(max
)
246 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
247 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
248 let pool
= new FixedThreadPool(
250 './tests/worker-files/thread/testWorker.js',
251 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
254 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
258 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
260 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
261 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
265 pool
= new DynamicThreadPool(
268 './tests/worker-files/thread/testWorker.js',
269 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
272 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
276 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
278 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
279 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
282 // We need to clean up the resources after our test
286 it('Verify LEAST_USED strategy default tasks usage statistics requirements', async () => {
287 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
288 let pool
= new FixedThreadPool(
290 './tests/worker-files/thread/testWorker.js',
291 { workerChoiceStrategy
}
294 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
304 pool
= new DynamicThreadPool(
307 './tests/worker-files/thread/testWorker.js',
308 { workerChoiceStrategy
}
311 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
320 // We need to clean up the resources after our test
324 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
325 const pool
= new FixedThreadPool(
327 './tests/worker-files/thread/testWorker.js',
328 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
330 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
331 const promises
= new Set()
332 const maxMultiplier
= 2
333 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
334 promises
.add(pool
.execute())
336 await Promise
.all(promises
)
337 for (const workerNode
of pool
.workerNodes
) {
338 expect(workerNode
.tasksUsage
).toStrictEqual({
342 runTimeHistory
: expect
.any(CircularArray
),
346 waitTimeHistory
: expect
.any(CircularArray
),
352 // We need to clean up the resources after our test
356 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
357 const pool
= new DynamicThreadPool(
360 './tests/worker-files/thread/testWorker.js',
361 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
363 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
364 const promises
= new Set()
365 const maxMultiplier
= 2
366 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
367 promises
.add(pool
.execute())
369 await Promise
.all(promises
)
370 for (const workerNode
of pool
.workerNodes
) {
371 expect(workerNode
.tasksUsage
).toStrictEqual({
375 runTimeHistory
: expect
.any(CircularArray
),
379 waitTimeHistory
: expect
.any(CircularArray
),
385 // We need to clean up the resources after our test
389 it('Verify LEAST_BUSY strategy default tasks usage statistics requirements', async () => {
390 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
391 let pool
= new FixedThreadPool(
393 './tests/worker-files/thread/testWorker.js',
394 { workerChoiceStrategy
}
397 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
407 pool
= new DynamicThreadPool(
410 './tests/worker-files/thread/testWorker.js',
411 { workerChoiceStrategy
}
414 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
423 // We need to clean up the resources after our test
427 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
428 const pool
= new FixedThreadPool(
430 './tests/worker-files/thread/testWorker.js',
431 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
433 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
434 const promises
= new Set()
435 const maxMultiplier
= 2
436 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
437 promises
.add(pool
.execute())
439 await Promise
.all(promises
)
440 for (const workerNode
of pool
.workerNodes
) {
441 expect(workerNode
.tasksUsage
).toStrictEqual({
442 run
: expect
.any(Number
),
444 runTime
: expect
.any(Number
),
445 runTimeHistory
: expect
.any(CircularArray
),
449 waitTimeHistory
: expect
.any(CircularArray
),
454 expect(workerNode
.tasksUsage
.run
).toBeGreaterThan(0)
455 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
456 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
458 // We need to clean up the resources after our test
462 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
463 const pool
= new DynamicThreadPool(
466 './tests/worker-files/thread/testWorker.js',
467 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
469 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
470 const promises
= new Set()
471 const maxMultiplier
= 2
472 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
473 promises
.add(pool
.execute())
475 await Promise
.all(promises
)
476 for (const workerNode
of pool
.workerNodes
) {
477 expect(workerNode
.tasksUsage
).toStrictEqual({
478 run
: expect
.any(Number
),
480 runTime
: expect
.any(Number
),
481 runTimeHistory
: expect
.any(CircularArray
),
485 waitTimeHistory
: expect
.any(CircularArray
),
490 expect(workerNode
.tasksUsage
.run
).toBeGreaterThan(0)
491 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
492 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
494 // We need to clean up the resources after our test
498 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
499 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
500 let pool
= new FixedThreadPool(
502 './tests/worker-files/thread/testWorker.js',
503 { workerChoiceStrategy
}
506 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
516 pool
= new DynamicThreadPool(
519 './tests/worker-files/thread/testWorker.js',
520 { workerChoiceStrategy
}
523 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
532 // We need to clean up the resources after our test
536 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
537 const pool
= new FixedThreadPool(
539 './tests/worker-files/thread/testWorker.js',
540 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
542 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
543 const promises
= new Set()
544 const maxMultiplier
= 2
545 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
546 promises
.add(pool
.execute())
548 await Promise
.all(promises
)
549 for (const workerNode
of pool
.workerNodes
) {
550 expect(workerNode
.tasksUsage
).toStrictEqual({
553 runTime
: expect
.any(Number
),
554 runTimeHistory
: expect
.any(CircularArray
),
555 avgRunTime
: expect
.any(Number
),
558 waitTimeHistory
: expect
.any(CircularArray
),
563 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
564 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThan(0)
567 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
568 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
569 ).workersVirtualTaskEndTimestamp
.length
570 ).toBe(pool
.workerNodes
.length
)
571 // We need to clean up the resources after our test
575 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
576 const pool
= new DynamicThreadPool(
579 './tests/worker-files/thread/testWorker.js',
580 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
582 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
583 const promises
= new Set()
584 const maxMultiplier
= 2
585 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
586 promises
.add(pool
.execute())
588 await Promise
.all(promises
)
589 for (const workerNode
of pool
.workerNodes
) {
590 expect(workerNode
.tasksUsage
).toStrictEqual({
593 runTime
: expect
.any(Number
),
594 runTimeHistory
: expect
.any(CircularArray
),
595 avgRunTime
: expect
.any(Number
),
598 waitTimeHistory
: expect
.any(CircularArray
),
603 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
604 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThan(0)
607 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
608 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
609 ).workersVirtualTaskEndTimestamp
.length
610 ).toBe(pool
.workerNodes
.length
)
611 // We need to clean up the resources after our test
615 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
616 const pool
= new DynamicThreadPool(
619 './tests/worker-files/thread/testWorker.js',
621 workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
,
622 workerChoiceStrategyOptions
: {
627 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
628 const promises
= new Set()
629 const maxMultiplier
= 2
630 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
631 promises
.add(pool
.execute())
633 await Promise
.all(promises
)
634 for (const workerNode
of pool
.workerNodes
) {
635 expect(workerNode
.tasksUsage
).toStrictEqual({
638 runTime
: expect
.any(Number
),
639 runTimeHistory
: expect
.any(CircularArray
),
641 medRunTime
: expect
.any(Number
),
643 waitTimeHistory
: expect
.any(CircularArray
),
648 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
649 expect(workerNode
.tasksUsage
.medRunTime
).toBeGreaterThan(0)
652 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
653 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
654 ).workersVirtualTaskEndTimestamp
.length
655 ).toBe(pool
.workerNodes
.length
)
656 // We need to clean up the resources after our test
660 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
661 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
662 let pool
= new FixedThreadPool(
664 './tests/worker-files/thread/testWorker.js'
667 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
669 ).workersVirtualTaskEndTimestamp
670 ).toBeInstanceOf(Array
)
672 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
674 ).workersVirtualTaskEndTimestamp
.length
676 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
678 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
680 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
682 ).workersVirtualTaskEndTimestamp
.length
684 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
686 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
688 ).workersVirtualTaskEndTimestamp
689 ).toBeInstanceOf(Array
)
691 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
693 ).workersVirtualTaskEndTimestamp
.length
696 pool
= new DynamicThreadPool(
699 './tests/worker-files/thread/testWorker.js'
702 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
704 ).workersVirtualTaskEndTimestamp
705 ).toBeInstanceOf(Array
)
707 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
709 ).workersVirtualTaskEndTimestamp
.length
711 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
713 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
715 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
717 ).workersVirtualTaskEndTimestamp
.length
719 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
721 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
723 ).workersVirtualTaskEndTimestamp
724 ).toBeInstanceOf(Array
)
726 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
728 ).workersVirtualTaskEndTimestamp
.length
730 // We need to clean up the resources after our test
734 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
735 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
736 let pool
= new FixedThreadPool(
738 './tests/worker-files/thread/testWorker.js',
739 { workerChoiceStrategy
}
742 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
752 pool
= new DynamicThreadPool(
755 './tests/worker-files/thread/testWorker.js',
756 { workerChoiceStrategy
}
759 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
768 // We need to clean up the resources after our test
772 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
773 const pool
= new FixedThreadPool(
775 './tests/worker-files/thread/testWorker.js',
776 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
778 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
779 const promises
= new Set()
780 const maxMultiplier
= 2
781 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
782 promises
.add(pool
.execute())
784 await Promise
.all(promises
)
785 for (const workerNode
of pool
.workerNodes
) {
786 expect(workerNode
.tasksUsage
).toStrictEqual({
787 run
: expect
.any(Number
),
789 runTime
: expect
.any(Number
),
790 runTimeHistory
: expect
.any(CircularArray
),
791 avgRunTime
: expect
.any(Number
),
794 waitTimeHistory
: expect
.any(CircularArray
),
799 expect(workerNode
.tasksUsage
.run
).toBeGreaterThanOrEqual(0)
800 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
801 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThanOrEqual(0)
802 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThanOrEqual(0)
805 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
806 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
807 ).defaultWorkerWeight
810 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
811 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
812 ).workerVirtualTaskRunTime
813 ).toBeGreaterThanOrEqual(0)
814 // We need to clean up the resources after our test
818 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
819 const pool
= new DynamicThreadPool(
822 './tests/worker-files/thread/testWorker.js',
823 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
825 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
826 const promises
= new Set()
827 const maxMultiplier
= 2
828 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
829 promises
.add(pool
.execute())
831 await Promise
.all(promises
)
832 for (const workerNode
of pool
.workerNodes
) {
833 expect(workerNode
.tasksUsage
).toStrictEqual({
834 run
: expect
.any(Number
),
836 runTime
: expect
.any(Number
),
837 runTimeHistory
: expect
.any(CircularArray
),
838 avgRunTime
: expect
.any(Number
),
841 waitTimeHistory
: expect
.any(CircularArray
),
846 expect(workerNode
.tasksUsage
.run
).toBeGreaterThan(0)
847 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
848 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
849 expect(workerNode
.tasksUsage
.avgRunTime
).toBeGreaterThan(0)
852 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
853 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
854 ).defaultWorkerWeight
857 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
858 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
859 ).workerVirtualTaskRunTime
860 ).toBeGreaterThanOrEqual(0)
861 // We need to clean up the resources after our test
865 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
866 const pool
= new DynamicThreadPool(
869 './tests/worker-files/thread/testWorker.js',
871 workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
,
872 workerChoiceStrategyOptions
: {
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
.tasksUsage
).toStrictEqual({
886 run
: expect
.any(Number
),
888 runTime
: expect
.any(Number
),
889 runTimeHistory
: expect
.any(CircularArray
),
891 medRunTime
: expect
.any(Number
),
893 waitTimeHistory
: expect
.any(CircularArray
),
898 expect(workerNode
.tasksUsage
.run
).toBeGreaterThan(0)
899 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(max
* maxMultiplier
)
900 expect(workerNode
.tasksUsage
.runTime
).toBeGreaterThan(0)
901 expect(workerNode
.tasksUsage
.medRunTime
).toBeGreaterThan(0)
904 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
905 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
906 ).defaultWorkerWeight
909 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
910 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
911 ).workerVirtualTaskRunTime
912 ).toBeGreaterThanOrEqual(0)
913 // We need to clean up the resources after our test
917 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
918 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
919 let pool
= new FixedThreadPool(
921 './tests/worker-files/thread/testWorker.js'
924 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
926 ).currentWorkerNodeId
929 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
931 ).defaultWorkerWeight
934 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
936 ).workerVirtualTaskRunTime
938 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
940 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
941 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
942 ).currentWorkerNodeId
945 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
946 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
947 ).defaultWorkerWeight
950 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
952 ).workerVirtualTaskRunTime
955 pool
= new DynamicThreadPool(
958 './tests/worker-files/thread/testWorker.js'
961 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
963 ).currentWorkerNodeId
966 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
968 ).defaultWorkerWeight
971 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
973 ).workerVirtualTaskRunTime
975 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
977 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
978 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
979 ).currentWorkerNodeId
982 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
983 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
984 ).defaultWorkerWeight
987 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
989 ).workerVirtualTaskRunTime
991 // We need to clean up the resources after our test
995 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
996 const workerChoiceStrategy
=
997 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
998 let pool
= new FixedThreadPool(
1000 './tests/worker-files/thread/testWorker.js',
1001 { workerChoiceStrategy
}
1004 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
1013 await pool
.destroy()
1014 pool
= new DynamicThreadPool(
1017 './tests/worker-files/thread/testWorker.js',
1018 { workerChoiceStrategy
}
1021 pool
.workerChoiceStrategyContext
.getRequiredStatistics()
1030 // We need to clean up the resources after our test
1031 await pool
.destroy()
1034 it('Verify unknown strategy throw error', () => {
1037 new DynamicThreadPool(
1040 './tests/worker-files/thread/testWorker.js',
1041 { workerChoiceStrategy
: 'UNKNOWN_STRATEGY' }
1043 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")