1 const { expect
} = require('expect')
3 WorkerChoiceStrategies
,
7 } = require('../../../lib')
8 const { CircularArray
} = require('../../../lib/circular-array')
9 const TestUtils
= require('../../test-utils')
11 describe('Selection strategies test suite', () => {
15 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
16 expect(WorkerChoiceStrategies
.ROUND_ROBIN
).toBe('ROUND_ROBIN')
17 expect(WorkerChoiceStrategies
.LEAST_USED
).toBe('LEAST_USED')
18 expect(WorkerChoiceStrategies
.LEAST_BUSY
).toBe('LEAST_BUSY')
19 expect(WorkerChoiceStrategies
.LEAST_ELU
).toBe('LEAST_ELU')
20 expect(WorkerChoiceStrategies
.FAIR_SHARE
).toBe('FAIR_SHARE')
21 expect(WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
).toBe(
22 'WEIGHTED_ROUND_ROBIN'
24 expect(WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
).toBe(
25 'INTERLEAVED_WEIGHTED_ROUND_ROBIN'
29 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
30 const pool
= new DynamicThreadPool(
33 './tests/worker-files/thread/testWorker.js'
35 expect(pool
.opts
.workerChoiceStrategy
).toBe(
36 WorkerChoiceStrategies
.ROUND_ROBIN
38 // We need to clean up the resources after our test
42 it('Verify available strategies are taken at pool creation', async () => {
43 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
44 const pool
= new FixedThreadPool(
46 './tests/worker-files/thread/testWorker.js',
47 { workerChoiceStrategy
}
49 expect(pool
.opts
.workerChoiceStrategy
).toBe(workerChoiceStrategy
)
50 expect(pool
.workerChoiceStrategyContext
.workerChoiceStrategy
).toBe(
57 it('Verify available strategies can be set after pool creation', async () => {
58 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
59 const pool
= new DynamicThreadPool(
62 './tests/worker-files/thread/testWorker.js'
64 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
65 expect(pool
.opts
.workerChoiceStrategy
).toBe(workerChoiceStrategy
)
66 expect(pool
.workerChoiceStrategyContext
.workerChoiceStrategy
).toBe(
73 it('Verify available strategies default internals at pool creation', async () => {
74 const pool
= new FixedThreadPool(
76 './tests/worker-files/thread/testWorker.js'
78 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
79 if (workerChoiceStrategy
=== WorkerChoiceStrategies
.ROUND_ROBIN
) {
81 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
85 } else if (workerChoiceStrategy
=== WorkerChoiceStrategies
.FAIR_SHARE
) {
87 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
89 ).workersVirtualTaskEndTimestamp
90 ).toBeInstanceOf(Array
)
92 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
94 ).workersVirtualTaskEndTimestamp
.length
97 workerChoiceStrategy
=== WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
100 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
102 ).currentWorkerNodeId
105 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
107 ).defaultWorkerWeight
110 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
112 ).workerVirtualTaskRunTime
119 it('Verify ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
120 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
121 let pool
= new FixedThreadPool(
123 './tests/worker-files/thread/testWorker.js',
124 { workerChoiceStrategy
}
127 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
142 pool
= new DynamicThreadPool(
145 './tests/worker-files/thread/testWorker.js',
146 { workerChoiceStrategy
}
149 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
163 // We need to clean up the resources after our test
167 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
168 const pool
= new FixedThreadPool(
170 './tests/worker-files/thread/testWorker.js',
171 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
173 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
174 const promises
= new Set()
175 const maxMultiplier
= 2
176 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
177 promises
.add(pool
.execute())
179 await Promise
.all(promises
)
180 for (const workerNode
of pool
.workerNodes
) {
181 expect(workerNode
.workerUsage
).toStrictEqual({
183 executed
: maxMultiplier
,
192 history
: expect
.any(CircularArray
)
198 history
: expect
.any(CircularArray
)
204 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
205 WorkerChoiceStrategies
.ROUND_ROBIN
208 // We need to clean up the resources after our test
212 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
213 const pool
= new DynamicThreadPool(
216 './tests/worker-files/thread/testWorker.js',
217 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
219 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
220 const promises
= new Set()
221 const maxMultiplier
= 2
222 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
223 promises
.add(pool
.execute())
225 await Promise
.all(promises
)
226 for (const workerNode
of pool
.workerNodes
) {
227 expect(workerNode
.workerUsage
).toStrictEqual({
229 executed
: maxMultiplier
,
238 history
: expect
.any(CircularArray
)
244 history
: expect
.any(CircularArray
)
250 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
251 WorkerChoiceStrategies
.ROUND_ROBIN
254 // We need to clean up the resources after our test
258 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
259 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
260 let pool
= new FixedClusterPool(
262 './tests/worker-files/cluster/testWorker.js',
263 { workerChoiceStrategy
}
265 let results
= new Set()
266 for (let i
= 0; i
< max
; i
++) {
267 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.id
)
269 expect(results
.size
).toBe(max
)
271 pool
= new FixedThreadPool(
273 './tests/worker-files/thread/testWorker.js',
274 { workerChoiceStrategy
}
277 for (let i
= 0; i
< max
; i
++) {
278 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.threadId
)
280 expect(results
.size
).toBe(max
)
284 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
285 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
286 let pool
= new FixedThreadPool(
288 './tests/worker-files/thread/testWorker.js',
289 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
292 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
296 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
298 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
299 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
303 pool
= new DynamicThreadPool(
306 './tests/worker-files/thread/testWorker.js',
307 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
310 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
314 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
316 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
317 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
320 // We need to clean up the resources after our test
324 it('Verify LEAST_USED strategy default tasks usage statistics requirements', async () => {
325 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
326 let pool
= new FixedThreadPool(
328 './tests/worker-files/thread/testWorker.js',
329 { workerChoiceStrategy
}
332 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
347 pool
= new DynamicThreadPool(
350 './tests/worker-files/thread/testWorker.js',
351 { workerChoiceStrategy
}
354 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
368 // We need to clean up the resources after our test
372 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
373 const pool
= new FixedThreadPool(
375 './tests/worker-files/thread/testWorker.js',
376 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
378 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
379 const promises
= new Set()
380 const maxMultiplier
= 2
381 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
382 promises
.add(pool
.execute())
384 await Promise
.all(promises
)
385 for (const workerNode
of pool
.workerNodes
) {
386 expect(workerNode
.workerUsage
).toStrictEqual({
388 executed
: maxMultiplier
,
397 history
: expect
.any(CircularArray
)
403 history
: expect
.any(CircularArray
)
408 // We need to clean up the resources after our test
412 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
413 const pool
= new DynamicThreadPool(
416 './tests/worker-files/thread/testWorker.js',
417 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
419 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
420 const promises
= new Set()
421 const maxMultiplier
= 2
422 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
423 promises
.add(pool
.execute())
425 await Promise
.all(promises
)
426 for (const workerNode
of pool
.workerNodes
) {
427 expect(workerNode
.workerUsage
).toStrictEqual({
429 executed
: maxMultiplier
,
438 history
: expect
.any(CircularArray
)
444 history
: expect
.any(CircularArray
)
450 // We need to clean up the resources after our test
454 it('Verify LEAST_BUSY strategy default tasks usage statistics requirements', async () => {
455 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
456 let pool
= new FixedThreadPool(
458 './tests/worker-files/thread/testWorker.js',
459 { workerChoiceStrategy
}
462 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
477 pool
= new DynamicThreadPool(
480 './tests/worker-files/thread/testWorker.js',
481 { workerChoiceStrategy
}
484 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
498 // We need to clean up the resources after our test
502 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
503 const pool
= new FixedThreadPool(
505 './tests/worker-files/thread/testWorker.js',
506 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
508 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
509 const promises
= new Set()
510 const maxMultiplier
= 2
511 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
512 promises
.add(pool
.execute())
514 await Promise
.all(promises
)
515 for (const workerNode
of pool
.workerNodes
) {
516 expect(workerNode
.workerUsage
).toStrictEqual({
518 executed
: expect
.any(Number
),
524 aggregate
: expect
.any(Number
),
527 history
: expect
.any(CircularArray
)
530 aggregate
: expect
.any(Number
),
533 history
: expect
.any(CircularArray
)
537 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
538 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
541 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThanOrEqual(0)
542 expect(workerNode
.workerUsage
.waitTime
.aggregate
).toBeGreaterThanOrEqual(
546 // We need to clean up the resources after our test
550 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
551 const pool
= new DynamicThreadPool(
554 './tests/worker-files/thread/testWorker.js',
555 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
557 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
558 const promises
= new Set()
559 const maxMultiplier
= 2
560 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
561 promises
.add(pool
.execute())
563 await Promise
.all(promises
)
564 for (const workerNode
of pool
.workerNodes
) {
565 expect(workerNode
.workerUsage
).toStrictEqual({
567 executed
: expect
.any(Number
),
573 aggregate
: expect
.any(Number
),
576 history
: expect
.any(CircularArray
)
579 aggregate
: expect
.any(Number
),
582 history
: expect
.any(CircularArray
)
586 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
587 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
590 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
591 expect(workerNode
.workerUsage
.waitTime
.aggregate
).toBeGreaterThan(0)
593 // We need to clean up the resources after our test
597 it('Verify LEAST_ELU strategy default tasks usage statistics requirements', async () => {
598 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_ELU
599 let pool
= new FixedThreadPool(
601 './tests/worker-files/thread/testWorker.js',
602 { workerChoiceStrategy
}
605 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
620 pool
= new DynamicThreadPool(
623 './tests/worker-files/thread/testWorker.js',
624 { workerChoiceStrategy
}
627 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
641 // We need to clean up the resources after our test
645 it('Verify LEAST_ELU strategy can be run in a fixed pool', async () => {
646 const pool
= new FixedThreadPool(
648 './tests/worker-files/thread/testWorker.js',
649 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_ELU
}
651 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
652 const maxMultiplier
= 2
653 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
655 if (i
!== max
* maxMultiplier
- 1) await TestUtils
.sleep(500)
657 for (const workerNode
of pool
.workerNodes
) {
658 const expectedWorkerUsage
= {
660 executed
: expect
.any(Number
),
669 history
: expect
.any(CircularArray
)
675 history
: expect
.any(CircularArray
)
678 if (workerNode
.workerUsage
.elu
=== undefined) {
679 expect(workerNode
.workerUsage
).toStrictEqual({
680 ...expectedWorkerUsage
,
684 expect(workerNode
.workerUsage
).toStrictEqual({
685 ...expectedWorkerUsage
,
687 active
: expect
.any(Number
),
693 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
694 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
698 // We need to clean up the resources after our test
702 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
703 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
704 let pool
= new FixedThreadPool(
706 './tests/worker-files/thread/testWorker.js',
707 { workerChoiceStrategy
}
710 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
725 pool
= new DynamicThreadPool(
728 './tests/worker-files/thread/testWorker.js',
729 { workerChoiceStrategy
}
732 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
746 // We need to clean up the resources after our test
750 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
751 const pool
= new FixedThreadPool(
753 './tests/worker-files/thread/testWorker.js',
754 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
756 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
757 const promises
= new Set()
758 const maxMultiplier
= 2
759 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
760 promises
.add(pool
.execute())
762 await Promise
.all(promises
)
763 for (const workerNode
of pool
.workerNodes
) {
764 expect(workerNode
.workerUsage
).toStrictEqual({
766 executed
: maxMultiplier
,
772 aggregate
: expect
.any(Number
),
773 average
: expect
.any(Number
),
775 history
: expect
.any(CircularArray
)
781 history
: expect
.any(CircularArray
)
785 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
786 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
789 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
790 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
791 ).workersVirtualTaskEndTimestamp
.length
792 ).toBe(pool
.workerNodes
.length
)
793 // We need to clean up the resources after our test
797 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
798 const pool
= new DynamicThreadPool(
801 './tests/worker-files/thread/testWorker.js',
802 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
804 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
805 const promises
= new Set()
806 const maxMultiplier
= 2
807 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
808 promises
.add(pool
.execute())
810 await Promise
.all(promises
)
811 for (const workerNode
of pool
.workerNodes
) {
812 expect(workerNode
.workerUsage
).toStrictEqual({
814 executed
: maxMultiplier
,
820 aggregate
: expect
.any(Number
),
821 average
: expect
.any(Number
),
823 history
: expect
.any(CircularArray
)
829 history
: expect
.any(CircularArray
)
833 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
834 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
837 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
838 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
839 ).workersVirtualTaskEndTimestamp
.length
840 ).toBe(pool
.workerNodes
.length
)
841 // We need to clean up the resources after our test
845 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
846 const pool
= new DynamicThreadPool(
849 './tests/worker-files/thread/testWorker.js',
851 workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
,
852 workerChoiceStrategyOptions
: {
853 runTime
: { median
: true }
857 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
858 const promises
= new Set()
859 const maxMultiplier
= 2
860 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
861 promises
.add(pool
.execute())
863 await Promise
.all(promises
)
864 for (const workerNode
of pool
.workerNodes
) {
865 expect(workerNode
.workerUsage
).toStrictEqual({
867 executed
: maxMultiplier
,
873 aggregate
: expect
.any(Number
),
875 median
: expect
.any(Number
),
876 history
: expect
.any(CircularArray
)
882 history
: expect
.any(CircularArray
)
886 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
887 expect(workerNode
.workerUsage
.runTime
.median
).toBeGreaterThan(0)
890 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
891 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
892 ).workersVirtualTaskEndTimestamp
.length
893 ).toBe(pool
.workerNodes
.length
)
894 // We need to clean up the resources after our test
898 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
899 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
900 let pool
= new FixedThreadPool(
902 './tests/worker-files/thread/testWorker.js'
905 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
907 ).workersVirtualTaskEndTimestamp
908 ).toBeInstanceOf(Array
)
910 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
912 ).workersVirtualTaskEndTimestamp
.length
914 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
916 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
918 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
920 ).workersVirtualTaskEndTimestamp
.length
922 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
924 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
926 ).workersVirtualTaskEndTimestamp
927 ).toBeInstanceOf(Array
)
929 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
931 ).workersVirtualTaskEndTimestamp
.length
934 pool
= new DynamicThreadPool(
937 './tests/worker-files/thread/testWorker.js'
940 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
942 ).workersVirtualTaskEndTimestamp
943 ).toBeInstanceOf(Array
)
945 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
947 ).workersVirtualTaskEndTimestamp
.length
949 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
951 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
953 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
955 ).workersVirtualTaskEndTimestamp
.length
957 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
959 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
961 ).workersVirtualTaskEndTimestamp
962 ).toBeInstanceOf(Array
)
964 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
966 ).workersVirtualTaskEndTimestamp
.length
968 // We need to clean up the resources after our test
972 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
973 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
974 let pool
= new FixedThreadPool(
976 './tests/worker-files/thread/testWorker.js',
977 { workerChoiceStrategy
}
980 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
995 pool
= new DynamicThreadPool(
998 './tests/worker-files/thread/testWorker.js',
999 { workerChoiceStrategy
}
1002 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1016 // We need to clean up the resources after our test
1017 await pool
.destroy()
1020 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1021 const pool
= new FixedThreadPool(
1023 './tests/worker-files/thread/testWorker.js',
1024 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
1026 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1027 const promises
= new Set()
1028 const maxMultiplier
= 2
1029 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1030 promises
.add(pool
.execute())
1032 await Promise
.all(promises
)
1033 for (const workerNode
of pool
.workerNodes
) {
1034 expect(workerNode
.workerUsage
).toStrictEqual({
1036 executed
: expect
.any(Number
),
1042 aggregate
: expect
.any(Number
),
1043 average
: expect
.any(Number
),
1045 history
: expect
.any(CircularArray
)
1051 history
: expect
.any(CircularArray
)
1055 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1056 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1059 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThanOrEqual(0)
1060 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThanOrEqual(0)
1063 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1064 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1065 ).defaultWorkerWeight
1066 ).toBeGreaterThan(0)
1068 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1069 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1070 ).workerVirtualTaskRunTime
1071 ).toBeGreaterThanOrEqual(0)
1072 // We need to clean up the resources after our test
1073 await pool
.destroy()
1076 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1077 const pool
= new DynamicThreadPool(
1080 './tests/worker-files/thread/testWorker.js',
1081 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
1083 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1084 const promises
= new Set()
1085 const maxMultiplier
= 2
1086 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1087 promises
.add(pool
.execute())
1089 await Promise
.all(promises
)
1090 for (const workerNode
of pool
.workerNodes
) {
1091 expect(workerNode
.workerUsage
).toStrictEqual({
1093 executed
: expect
.any(Number
),
1099 aggregate
: expect
.any(Number
),
1100 average
: expect
.any(Number
),
1102 history
: expect
.any(CircularArray
)
1108 history
: expect
.any(CircularArray
)
1112 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
1113 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1116 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
1117 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
1120 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1121 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1122 ).defaultWorkerWeight
1123 ).toBeGreaterThan(0)
1125 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1126 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1127 ).workerVirtualTaskRunTime
1128 ).toBeGreaterThanOrEqual(0)
1129 // We need to clean up the resources after our test
1130 await pool
.destroy()
1133 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
1134 const pool
= new DynamicThreadPool(
1137 './tests/worker-files/thread/testWorker.js',
1139 workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
,
1140 workerChoiceStrategyOptions
: {
1141 runTime
: { median
: true }
1145 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1146 const promises
= new Set()
1147 const maxMultiplier
= 2
1148 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1149 promises
.add(pool
.execute())
1151 await Promise
.all(promises
)
1152 for (const workerNode
of pool
.workerNodes
) {
1153 expect(workerNode
.workerUsage
).toStrictEqual({
1155 executed
: expect
.any(Number
),
1161 aggregate
: expect
.any(Number
),
1163 median
: expect
.any(Number
),
1164 history
: expect
.any(CircularArray
)
1170 history
: expect
.any(CircularArray
)
1174 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
1175 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1178 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
1179 expect(workerNode
.workerUsage
.runTime
.median
).toBeGreaterThan(0)
1182 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1183 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1184 ).defaultWorkerWeight
1185 ).toBeGreaterThan(0)
1187 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1188 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1189 ).workerVirtualTaskRunTime
1190 ).toBeGreaterThanOrEqual(0)
1191 // We need to clean up the resources after our test
1192 await pool
.destroy()
1195 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1196 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1197 let pool
= new FixedThreadPool(
1199 './tests/worker-files/thread/testWorker.js'
1202 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1203 workerChoiceStrategy
1204 ).currentWorkerNodeId
1207 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1208 workerChoiceStrategy
1209 ).defaultWorkerWeight
1212 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1213 workerChoiceStrategy
1214 ).workerVirtualTaskRunTime
1216 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1218 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1219 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1220 ).currentWorkerNodeId
1223 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1224 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1225 ).defaultWorkerWeight
1226 ).toBeGreaterThan(0)
1228 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1229 workerChoiceStrategy
1230 ).workerVirtualTaskRunTime
1232 await pool
.destroy()
1233 pool
= new DynamicThreadPool(
1236 './tests/worker-files/thread/testWorker.js'
1239 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1240 workerChoiceStrategy
1241 ).currentWorkerNodeId
1244 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1245 workerChoiceStrategy
1246 ).defaultWorkerWeight
1249 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1250 workerChoiceStrategy
1251 ).workerVirtualTaskRunTime
1253 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1255 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1256 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1257 ).currentWorkerNodeId
1260 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1261 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1262 ).defaultWorkerWeight
1263 ).toBeGreaterThan(0)
1265 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1266 workerChoiceStrategy
1267 ).workerVirtualTaskRunTime
1269 // We need to clean up the resources after our test
1270 await pool
.destroy()
1273 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1274 const workerChoiceStrategy
=
1275 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1276 let pool
= new FixedThreadPool(
1278 './tests/worker-files/thread/testWorker.js',
1279 { workerChoiceStrategy
}
1282 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1296 await pool
.destroy()
1297 pool
= new DynamicThreadPool(
1300 './tests/worker-files/thread/testWorker.js',
1301 { workerChoiceStrategy
}
1304 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1318 // We need to clean up the resources after our test
1319 await pool
.destroy()
1322 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1323 const pool
= new FixedThreadPool(
1325 './tests/worker-files/thread/testWorker.js',
1327 workerChoiceStrategy
:
1328 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1331 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1332 const promises
= new Set()
1333 const maxMultiplier
= 2
1334 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1335 promises
.add(pool
.execute())
1337 await Promise
.all(promises
)
1338 for (const workerNode
of pool
.workerNodes
) {
1339 expect(workerNode
.workerUsage
).toStrictEqual({
1341 executed
: maxMultiplier
,
1350 history
: expect
.any(CircularArray
)
1356 history
: expect
.any(CircularArray
)
1362 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1363 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1364 ).defaultWorkerWeight
1365 ).toBeGreaterThan(0)
1367 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1368 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1372 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1373 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1374 ).currentWorkerNodeId
1377 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1378 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1381 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1382 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1383 ).defaultWorkerWeight
1385 // We need to clean up the resources after our test
1386 await pool
.destroy()
1389 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1390 const pool
= new DynamicThreadPool(
1393 './tests/worker-files/thread/testWorker.js',
1395 workerChoiceStrategy
:
1396 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1399 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1400 const promises
= new Set()
1401 const maxMultiplier
= 2
1402 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1403 promises
.add(pool
.execute())
1405 await Promise
.all(promises
)
1406 for (const workerNode
of pool
.workerNodes
) {
1407 expect(workerNode
.workerUsage
).toStrictEqual({
1409 executed
: maxMultiplier
,
1418 history
: expect
.any(CircularArray
)
1424 history
: expect
.any(CircularArray
)
1430 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1431 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1432 ).defaultWorkerWeight
1433 ).toBeGreaterThan(0)
1435 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1436 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1440 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1441 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1442 ).currentWorkerNodeId
1445 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1446 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1449 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1450 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1451 ).defaultWorkerWeight
1453 // We need to clean up the resources after our test
1454 await pool
.destroy()
1457 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1458 const workerChoiceStrategy
=
1459 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1460 let pool
= new FixedThreadPool(
1462 './tests/worker-files/thread/testWorker.js'
1465 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1466 workerChoiceStrategy
1470 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1471 workerChoiceStrategy
1472 ).currentWorkerNodeId
1475 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1476 workerChoiceStrategy
1477 ).defaultWorkerWeight
1480 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1481 workerChoiceStrategy
1484 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1486 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1487 workerChoiceStrategy
1491 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1492 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1493 ).currentWorkerNodeId
1496 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1497 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1498 ).defaultWorkerWeight
1499 ).toBeGreaterThan(0)
1501 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1502 workerChoiceStrategy
1505 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1506 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1507 ).defaultWorkerWeight
1509 await pool
.destroy()
1510 pool
= new DynamicThreadPool(
1513 './tests/worker-files/thread/testWorker.js'
1516 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1517 workerChoiceStrategy
1521 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1522 workerChoiceStrategy
1523 ).currentWorkerNodeId
1526 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1527 workerChoiceStrategy
1528 ).defaultWorkerWeight
1531 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1532 workerChoiceStrategy
1535 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1537 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1538 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1539 ).currentWorkerNodeId
1542 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1543 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1544 ).defaultWorkerWeight
1545 ).toBeGreaterThan(0)
1547 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1548 workerChoiceStrategy
1551 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1552 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1553 ).defaultWorkerWeight
1555 // We need to clean up the resources after our test
1556 await pool
.destroy()
1559 it('Verify unknown strategy throw error', () => {
1562 new DynamicThreadPool(
1565 './tests/worker-files/thread/testWorker.js',
1566 { workerChoiceStrategy
: 'UNKNOWN_STRATEGY' }
1568 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")