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_ELU
).toBe('LEAST_ELU')
18 expect(WorkerChoiceStrategies
.LEAST_BUSY
).toBe('LEAST_BUSY')
19 expect(WorkerChoiceStrategies
.FAIR_SHARE
).toBe('FAIR_SHARE')
20 expect(WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
).toBe(
21 'WEIGHTED_ROUND_ROBIN'
23 expect(WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
).toBe(
24 'INTERLEAVED_WEIGHTED_ROUND_ROBIN'
28 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
29 const pool
= new DynamicThreadPool(
32 './tests/worker-files/thread/testWorker.js'
34 expect(pool
.opts
.workerChoiceStrategy
).toBe(
35 WorkerChoiceStrategies
.ROUND_ROBIN
37 // We need to clean up the resources after our test
41 it('Verify available strategies are taken at pool creation', async () => {
42 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
43 const pool
= new FixedThreadPool(
45 './tests/worker-files/thread/testWorker.js',
46 { workerChoiceStrategy
}
48 expect(pool
.opts
.workerChoiceStrategy
).toBe(workerChoiceStrategy
)
49 expect(pool
.workerChoiceStrategyContext
.workerChoiceStrategy
).toBe(
56 it('Verify available strategies can be set after pool creation', async () => {
57 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
58 const pool
= new DynamicThreadPool(
61 './tests/worker-files/thread/testWorker.js'
63 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
64 expect(pool
.opts
.workerChoiceStrategy
).toBe(workerChoiceStrategy
)
65 expect(pool
.workerChoiceStrategyContext
.workerChoiceStrategy
).toBe(
72 it('Verify available strategies default internals at pool creation', async () => {
73 const pool
= new FixedThreadPool(
75 './tests/worker-files/thread/testWorker.js'
77 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
78 if (workerChoiceStrategy
=== WorkerChoiceStrategies
.ROUND_ROBIN
) {
80 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
84 } else if (workerChoiceStrategy
=== WorkerChoiceStrategies
.FAIR_SHARE
) {
86 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
88 ).workersVirtualTaskEndTimestamp
89 ).toBeInstanceOf(Array
)
91 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
93 ).workersVirtualTaskEndTimestamp
.length
96 workerChoiceStrategy
=== WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
99 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
101 ).currentWorkerNodeId
104 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
106 ).defaultWorkerWeight
109 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
111 ).workerVirtualTaskRunTime
118 it('Verify ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
119 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
120 let pool
= new FixedThreadPool(
122 './tests/worker-files/thread/testWorker.js',
123 { workerChoiceStrategy
}
125 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
135 pool
= new DynamicThreadPool(
138 './tests/worker-files/thread/testWorker.js',
139 { workerChoiceStrategy
}
141 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
150 // We need to clean up the resources after our test
154 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
155 const pool
= new FixedThreadPool(
157 './tests/worker-files/thread/testWorker.js',
158 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
160 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
161 const promises
= new Set()
162 const maxMultiplier
= 2
163 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
164 promises
.add(pool
.execute())
166 await Promise
.all(promises
)
167 for (const workerNode
of pool
.workerNodes
) {
168 expect(workerNode
.workerUsage
).toStrictEqual({
170 executed
: maxMultiplier
,
179 history
: expect
.any(CircularArray
)
185 history
: expect
.any(CircularArray
)
191 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
192 WorkerChoiceStrategies
.ROUND_ROBIN
195 // We need to clean up the resources after our test
199 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
200 const pool
= new DynamicThreadPool(
203 './tests/worker-files/thread/testWorker.js',
204 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
206 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
207 const promises
= new Set()
208 const maxMultiplier
= 2
209 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
210 promises
.add(pool
.execute())
212 await Promise
.all(promises
)
213 for (const workerNode
of pool
.workerNodes
) {
214 expect(workerNode
.workerUsage
).toStrictEqual({
216 executed
: maxMultiplier
,
225 history
: expect
.any(CircularArray
)
231 history
: expect
.any(CircularArray
)
237 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
238 WorkerChoiceStrategies
.ROUND_ROBIN
241 // We need to clean up the resources after our test
245 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
246 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
247 let pool
= new FixedClusterPool(
249 './tests/worker-files/cluster/testWorker.js',
250 { workerChoiceStrategy
}
252 let results
= new Set()
253 for (let i
= 0; i
< max
; i
++) {
254 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.id
)
256 expect(results
.size
).toBe(max
)
258 pool
= new FixedThreadPool(
260 './tests/worker-files/thread/testWorker.js',
261 { workerChoiceStrategy
}
264 for (let i
= 0; i
< max
; i
++) {
265 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.threadId
)
267 expect(results
.size
).toBe(max
)
271 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
272 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
273 let pool
= new FixedThreadPool(
275 './tests/worker-files/thread/testWorker.js',
276 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
279 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
283 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
285 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
286 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
290 pool
= new DynamicThreadPool(
293 './tests/worker-files/thread/testWorker.js',
294 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
297 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
301 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
303 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
304 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
307 // We need to clean up the resources after our test
311 it('Verify LEAST_USED strategy default tasks usage statistics requirements', async () => {
312 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
313 let pool
= new FixedThreadPool(
315 './tests/worker-files/thread/testWorker.js',
316 { workerChoiceStrategy
}
318 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
328 pool
= new DynamicThreadPool(
331 './tests/worker-files/thread/testWorker.js',
332 { workerChoiceStrategy
}
334 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
343 // We need to clean up the resources after our test
347 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
348 const pool
= new FixedThreadPool(
350 './tests/worker-files/thread/testWorker.js',
351 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
353 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
354 const promises
= new Set()
355 const maxMultiplier
= 2
356 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
357 promises
.add(pool
.execute())
359 await Promise
.all(promises
)
360 for (const workerNode
of pool
.workerNodes
) {
361 expect(workerNode
.workerUsage
).toStrictEqual({
363 executed
: maxMultiplier
,
372 history
: expect
.any(CircularArray
)
378 history
: expect
.any(CircularArray
)
383 // We need to clean up the resources after our test
387 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
388 const pool
= new DynamicThreadPool(
391 './tests/worker-files/thread/testWorker.js',
392 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
394 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
395 const promises
= new Set()
396 const maxMultiplier
= 2
397 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
398 promises
.add(pool
.execute())
400 await Promise
.all(promises
)
401 for (const workerNode
of pool
.workerNodes
) {
402 expect(workerNode
.workerUsage
).toStrictEqual({
404 executed
: maxMultiplier
,
413 history
: expect
.any(CircularArray
)
419 history
: expect
.any(CircularArray
)
425 // We need to clean up the resources after our test
429 it('Verify LEAST_BUSY strategy default tasks usage statistics requirements', async () => {
430 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
431 let pool
= new FixedThreadPool(
433 './tests/worker-files/thread/testWorker.js',
434 { workerChoiceStrategy
}
436 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
446 pool
= new DynamicThreadPool(
449 './tests/worker-files/thread/testWorker.js',
450 { workerChoiceStrategy
}
452 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
461 // We need to clean up the resources after our test
465 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
466 const pool
= new FixedThreadPool(
468 './tests/worker-files/thread/testWorker.js',
469 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
471 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
472 const promises
= new Set()
473 const maxMultiplier
= 2
474 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
475 promises
.add(pool
.execute())
477 await Promise
.all(promises
)
478 for (const workerNode
of pool
.workerNodes
) {
479 expect(workerNode
.workerUsage
).toStrictEqual({
481 executed
: expect
.any(Number
),
487 aggregation
: expect
.any(Number
),
490 history
: expect
.any(CircularArray
)
496 history
: expect
.any(CircularArray
)
500 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
501 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
504 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThanOrEqual(
508 // We need to clean up the resources after our test
512 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
513 const pool
= new DynamicThreadPool(
516 './tests/worker-files/thread/testWorker.js',
517 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
519 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
520 const promises
= new Set()
521 const maxMultiplier
= 2
522 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
523 promises
.add(pool
.execute())
525 await Promise
.all(promises
)
526 for (const workerNode
of pool
.workerNodes
) {
527 expect(workerNode
.workerUsage
).toStrictEqual({
529 executed
: expect
.any(Number
),
535 aggregation
: expect
.any(Number
),
538 history
: expect
.any(CircularArray
)
544 history
: expect
.any(CircularArray
)
548 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
549 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
552 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
554 // We need to clean up the resources after our test
558 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
559 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
560 let pool
= new FixedThreadPool(
562 './tests/worker-files/thread/testWorker.js',
563 { workerChoiceStrategy
}
565 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
575 pool
= new DynamicThreadPool(
578 './tests/worker-files/thread/testWorker.js',
579 { workerChoiceStrategy
}
581 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
590 // We need to clean up the resources after our test
594 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
595 const pool
= new FixedThreadPool(
597 './tests/worker-files/thread/testWorker.js',
598 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
600 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
601 const promises
= new Set()
602 const maxMultiplier
= 2
603 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
604 promises
.add(pool
.execute())
606 await Promise
.all(promises
)
607 for (const workerNode
of pool
.workerNodes
) {
608 expect(workerNode
.workerUsage
).toStrictEqual({
610 executed
: maxMultiplier
,
616 aggregation
: expect
.any(Number
),
617 average
: expect
.any(Number
),
619 history
: expect
.any(CircularArray
)
625 history
: expect
.any(CircularArray
)
629 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
630 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
633 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
634 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
635 ).workersVirtualTaskEndTimestamp
.length
636 ).toBe(pool
.workerNodes
.length
)
637 // We need to clean up the resources after our test
641 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
642 const pool
= new DynamicThreadPool(
645 './tests/worker-files/thread/testWorker.js',
646 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
648 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
649 const promises
= new Set()
650 const maxMultiplier
= 2
651 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
652 promises
.add(pool
.execute())
654 await Promise
.all(promises
)
655 for (const workerNode
of pool
.workerNodes
) {
656 expect(workerNode
.workerUsage
).toStrictEqual({
658 executed
: maxMultiplier
,
664 aggregation
: expect
.any(Number
),
665 average
: expect
.any(Number
),
667 history
: expect
.any(CircularArray
)
673 history
: expect
.any(CircularArray
)
677 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
678 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
681 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
682 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
683 ).workersVirtualTaskEndTimestamp
.length
684 ).toBe(pool
.workerNodes
.length
)
685 // We need to clean up the resources after our test
689 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
690 const pool
= new DynamicThreadPool(
693 './tests/worker-files/thread/testWorker.js',
695 workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
,
696 workerChoiceStrategyOptions
: {
701 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
702 const promises
= new Set()
703 const maxMultiplier
= 2
704 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
705 promises
.add(pool
.execute())
707 await Promise
.all(promises
)
708 for (const workerNode
of pool
.workerNodes
) {
709 expect(workerNode
.workerUsage
).toStrictEqual({
711 executed
: maxMultiplier
,
717 aggregation
: expect
.any(Number
),
719 median
: expect
.any(Number
),
720 history
: expect
.any(CircularArray
)
726 history
: expect
.any(CircularArray
)
730 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
731 expect(workerNode
.workerUsage
.runTime
.median
).toBeGreaterThan(0)
734 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
735 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
736 ).workersVirtualTaskEndTimestamp
.length
737 ).toBe(pool
.workerNodes
.length
)
738 // We need to clean up the resources after our test
742 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
743 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
744 let pool
= new FixedThreadPool(
746 './tests/worker-files/thread/testWorker.js'
749 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
751 ).workersVirtualTaskEndTimestamp
752 ).toBeInstanceOf(Array
)
754 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
756 ).workersVirtualTaskEndTimestamp
.length
758 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
760 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
762 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
764 ).workersVirtualTaskEndTimestamp
.length
766 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
768 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
770 ).workersVirtualTaskEndTimestamp
771 ).toBeInstanceOf(Array
)
773 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
775 ).workersVirtualTaskEndTimestamp
.length
778 pool
= new DynamicThreadPool(
781 './tests/worker-files/thread/testWorker.js'
784 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
786 ).workersVirtualTaskEndTimestamp
787 ).toBeInstanceOf(Array
)
789 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
791 ).workersVirtualTaskEndTimestamp
.length
793 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
795 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
797 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
799 ).workersVirtualTaskEndTimestamp
.length
801 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
803 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
805 ).workersVirtualTaskEndTimestamp
806 ).toBeInstanceOf(Array
)
808 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
810 ).workersVirtualTaskEndTimestamp
.length
812 // We need to clean up the resources after our test
816 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
817 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
818 let pool
= new FixedThreadPool(
820 './tests/worker-files/thread/testWorker.js',
821 { workerChoiceStrategy
}
823 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
833 pool
= new DynamicThreadPool(
836 './tests/worker-files/thread/testWorker.js',
837 { workerChoiceStrategy
}
839 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
848 // We need to clean up the resources after our test
852 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
853 const pool
= new FixedThreadPool(
855 './tests/worker-files/thread/testWorker.js',
856 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
858 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
859 const promises
= new Set()
860 const maxMultiplier
= 2
861 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
862 promises
.add(pool
.execute())
864 await Promise
.all(promises
)
865 for (const workerNode
of pool
.workerNodes
) {
866 expect(workerNode
.workerUsage
).toStrictEqual({
868 executed
: expect
.any(Number
),
874 aggregation
: expect
.any(Number
),
875 average
: expect
.any(Number
),
877 history
: expect
.any(CircularArray
)
883 history
: expect
.any(CircularArray
)
887 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
888 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
891 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThanOrEqual(
894 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThanOrEqual(0)
897 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
898 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
899 ).defaultWorkerWeight
902 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
903 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
904 ).workerVirtualTaskRunTime
905 ).toBeGreaterThanOrEqual(0)
906 // We need to clean up the resources after our test
910 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
911 const pool
= new DynamicThreadPool(
914 './tests/worker-files/thread/testWorker.js',
915 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
917 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
918 const promises
= new Set()
919 const maxMultiplier
= 2
920 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
921 promises
.add(pool
.execute())
923 await Promise
.all(promises
)
924 for (const workerNode
of pool
.workerNodes
) {
925 expect(workerNode
.workerUsage
).toStrictEqual({
927 executed
: expect
.any(Number
),
933 aggregation
: expect
.any(Number
),
934 average
: expect
.any(Number
),
936 history
: expect
.any(CircularArray
)
942 history
: expect
.any(CircularArray
)
946 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
947 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
950 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
951 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
954 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
955 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
956 ).defaultWorkerWeight
959 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
960 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
961 ).workerVirtualTaskRunTime
962 ).toBeGreaterThanOrEqual(0)
963 // We need to clean up the resources after our test
967 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
968 const pool
= new DynamicThreadPool(
971 './tests/worker-files/thread/testWorker.js',
973 workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
,
974 workerChoiceStrategyOptions
: {
979 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
980 const promises
= new Set()
981 const maxMultiplier
= 2
982 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
983 promises
.add(pool
.execute())
985 await Promise
.all(promises
)
986 for (const workerNode
of pool
.workerNodes
) {
987 expect(workerNode
.workerUsage
).toStrictEqual({
989 executed
: expect
.any(Number
),
995 aggregation
: expect
.any(Number
),
997 median
: expect
.any(Number
),
998 history
: expect
.any(CircularArray
)
1004 history
: expect
.any(CircularArray
)
1008 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
1009 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1012 expect(workerNode
.workerUsage
.runTime
.aggregation
).toBeGreaterThan(0)
1013 expect(workerNode
.workerUsage
.runTime
.median
).toBeGreaterThan(0)
1016 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1017 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1018 ).defaultWorkerWeight
1019 ).toBeGreaterThan(0)
1021 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1022 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1023 ).workerVirtualTaskRunTime
1024 ).toBeGreaterThanOrEqual(0)
1025 // We need to clean up the resources after our test
1026 await pool
.destroy()
1029 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1030 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1031 let pool
= new FixedThreadPool(
1033 './tests/worker-files/thread/testWorker.js'
1036 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1037 workerChoiceStrategy
1038 ).currentWorkerNodeId
1041 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1042 workerChoiceStrategy
1043 ).defaultWorkerWeight
1046 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1047 workerChoiceStrategy
1048 ).workerVirtualTaskRunTime
1050 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1052 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1053 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1054 ).currentWorkerNodeId
1057 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1058 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1059 ).defaultWorkerWeight
1060 ).toBeGreaterThan(0)
1062 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1063 workerChoiceStrategy
1064 ).workerVirtualTaskRunTime
1066 await pool
.destroy()
1067 pool
= new DynamicThreadPool(
1070 './tests/worker-files/thread/testWorker.js'
1073 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1074 workerChoiceStrategy
1075 ).currentWorkerNodeId
1078 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1079 workerChoiceStrategy
1080 ).defaultWorkerWeight
1083 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1084 workerChoiceStrategy
1085 ).workerVirtualTaskRunTime
1087 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1089 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1090 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1091 ).currentWorkerNodeId
1094 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1095 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1096 ).defaultWorkerWeight
1097 ).toBeGreaterThan(0)
1099 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1100 workerChoiceStrategy
1101 ).workerVirtualTaskRunTime
1103 // We need to clean up the resources after our test
1104 await pool
.destroy()
1107 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1108 const workerChoiceStrategy
=
1109 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1110 let pool
= new FixedThreadPool(
1112 './tests/worker-files/thread/testWorker.js',
1113 { workerChoiceStrategy
}
1115 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
1124 await pool
.destroy()
1125 pool
= new DynamicThreadPool(
1128 './tests/worker-files/thread/testWorker.js',
1129 { workerChoiceStrategy
}
1131 expect(pool
.workerChoiceStrategyContext
.getTaskStatistics()).toStrictEqual({
1140 // We need to clean up the resources after our test
1141 await pool
.destroy()
1144 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1145 const pool
= new FixedThreadPool(
1147 './tests/worker-files/thread/testWorker.js',
1149 workerChoiceStrategy
:
1150 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1153 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1154 const promises
= new Set()
1155 const maxMultiplier
= 2
1156 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1157 promises
.add(pool
.execute())
1159 await Promise
.all(promises
)
1160 for (const workerNode
of pool
.workerNodes
) {
1161 expect(workerNode
.workerUsage
).toStrictEqual({
1163 executed
: maxMultiplier
,
1172 history
: expect
.any(CircularArray
)
1178 history
: expect
.any(CircularArray
)
1184 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1185 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1186 ).defaultWorkerWeight
1187 ).toBeGreaterThan(0)
1189 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1190 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1194 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1195 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1196 ).currentWorkerNodeId
1199 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1200 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1203 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1204 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1205 ).defaultWorkerWeight
1207 // We need to clean up the resources after our test
1208 await pool
.destroy()
1211 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1212 const pool
= new DynamicThreadPool(
1215 './tests/worker-files/thread/testWorker.js',
1217 workerChoiceStrategy
:
1218 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1221 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1222 const promises
= new Set()
1223 const maxMultiplier
= 2
1224 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1225 promises
.add(pool
.execute())
1227 await Promise
.all(promises
)
1228 for (const workerNode
of pool
.workerNodes
) {
1229 expect(workerNode
.workerUsage
).toStrictEqual({
1231 executed
: maxMultiplier
,
1240 history
: expect
.any(CircularArray
)
1246 history
: expect
.any(CircularArray
)
1252 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1253 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1254 ).defaultWorkerWeight
1255 ).toBeGreaterThan(0)
1257 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1258 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1262 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1263 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1264 ).currentWorkerNodeId
1267 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1268 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1271 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1272 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1273 ).defaultWorkerWeight
1275 // We need to clean up the resources after our test
1276 await pool
.destroy()
1279 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1280 const workerChoiceStrategy
=
1281 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1282 let pool
= new FixedThreadPool(
1284 './tests/worker-files/thread/testWorker.js'
1287 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1288 workerChoiceStrategy
1292 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1293 workerChoiceStrategy
1294 ).currentWorkerNodeId
1297 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1298 workerChoiceStrategy
1299 ).defaultWorkerWeight
1302 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1303 workerChoiceStrategy
1306 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1308 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1309 workerChoiceStrategy
1313 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1314 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1315 ).currentWorkerNodeId
1318 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1319 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1320 ).defaultWorkerWeight
1321 ).toBeGreaterThan(0)
1323 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1324 workerChoiceStrategy
1327 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1328 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1329 ).defaultWorkerWeight
1331 await pool
.destroy()
1332 pool
= new DynamicThreadPool(
1335 './tests/worker-files/thread/testWorker.js'
1338 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1339 workerChoiceStrategy
1343 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1344 workerChoiceStrategy
1345 ).currentWorkerNodeId
1348 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1349 workerChoiceStrategy
1350 ).defaultWorkerWeight
1353 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1354 workerChoiceStrategy
1357 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1359 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1360 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1361 ).currentWorkerNodeId
1364 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1365 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1366 ).defaultWorkerWeight
1367 ).toBeGreaterThan(0)
1369 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1370 workerChoiceStrategy
1373 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1374 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1375 ).defaultWorkerWeight
1377 // We need to clean up the resources after our test
1378 await pool
.destroy()
1381 it('Verify unknown strategy throw error', () => {
1384 new DynamicThreadPool(
1387 './tests/worker-files/thread/testWorker.js',
1388 { workerChoiceStrategy
: 'UNKNOWN_STRATEGY' }
1390 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")