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 LEAST_ELU strategy can be run in a dynamic pool', async () => {
703 const pool
= new DynamicThreadPool(
706 './tests/worker-files/thread/testWorker.js',
707 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_ELU
}
709 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
710 const maxMultiplier
= 2
711 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
713 if (i
!== max
* maxMultiplier
- 1) await TestUtils
.sleep(500)
715 for (const workerNode
of pool
.workerNodes
) {
716 const expectedWorkerUsage
= {
718 executed
: expect
.any(Number
),
727 history
: expect
.any(CircularArray
)
733 history
: expect
.any(CircularArray
)
736 if (workerNode
.workerUsage
.elu
=== undefined) {
737 expect(workerNode
.workerUsage
).toStrictEqual({
738 ...expectedWorkerUsage
,
742 expect(workerNode
.workerUsage
).toStrictEqual({
743 ...expectedWorkerUsage
,
745 active
: expect
.any(Number
),
751 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
752 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
756 // We need to clean up the resources after our test
760 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
761 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
762 let pool
= new FixedThreadPool(
764 './tests/worker-files/thread/testWorker.js',
765 { workerChoiceStrategy
}
768 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
783 pool
= new DynamicThreadPool(
786 './tests/worker-files/thread/testWorker.js',
787 { workerChoiceStrategy
}
790 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
804 // We need to clean up the resources after our test
808 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
809 const pool
= new FixedThreadPool(
811 './tests/worker-files/thread/testWorker.js',
812 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
814 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
815 const promises
= new Set()
816 const maxMultiplier
= 2
817 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
818 promises
.add(pool
.execute())
820 await Promise
.all(promises
)
821 for (const workerNode
of pool
.workerNodes
) {
822 expect(workerNode
.workerUsage
).toStrictEqual({
824 executed
: maxMultiplier
,
830 aggregate
: expect
.any(Number
),
831 average
: expect
.any(Number
),
833 history
: expect
.any(CircularArray
)
839 history
: expect
.any(CircularArray
)
843 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
844 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
847 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
848 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
849 ).workersVirtualTaskEndTimestamp
.length
850 ).toBe(pool
.workerNodes
.length
)
851 // We need to clean up the resources after our test
855 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
856 const pool
= new DynamicThreadPool(
859 './tests/worker-files/thread/testWorker.js',
860 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
862 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
863 const promises
= new Set()
864 const maxMultiplier
= 2
865 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
866 promises
.add(pool
.execute())
868 await Promise
.all(promises
)
869 for (const workerNode
of pool
.workerNodes
) {
870 expect(workerNode
.workerUsage
).toStrictEqual({
872 executed
: maxMultiplier
,
878 aggregate
: expect
.any(Number
),
879 average
: expect
.any(Number
),
881 history
: expect
.any(CircularArray
)
887 history
: expect
.any(CircularArray
)
891 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
892 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
895 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
896 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
897 ).workersVirtualTaskEndTimestamp
.length
898 ).toBe(pool
.workerNodes
.length
)
899 // We need to clean up the resources after our test
903 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
904 const pool
= new DynamicThreadPool(
907 './tests/worker-files/thread/testWorker.js',
909 workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
,
910 workerChoiceStrategyOptions
: {
911 runTime
: { median
: true }
915 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
916 const promises
= new Set()
917 const maxMultiplier
= 2
918 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
919 promises
.add(pool
.execute())
921 await Promise
.all(promises
)
922 for (const workerNode
of pool
.workerNodes
) {
923 expect(workerNode
.workerUsage
).toStrictEqual({
925 executed
: maxMultiplier
,
931 aggregate
: expect
.any(Number
),
933 median
: expect
.any(Number
),
934 history
: expect
.any(CircularArray
)
940 history
: expect
.any(CircularArray
)
944 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
945 expect(workerNode
.workerUsage
.runTime
.median
).toBeGreaterThan(0)
948 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
949 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
950 ).workersVirtualTaskEndTimestamp
.length
951 ).toBe(pool
.workerNodes
.length
)
952 // We need to clean up the resources after our test
956 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
957 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
958 let pool
= new FixedThreadPool(
960 './tests/worker-files/thread/testWorker.js'
963 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
965 ).workersVirtualTaskEndTimestamp
966 ).toBeInstanceOf(Array
)
968 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
970 ).workersVirtualTaskEndTimestamp
.length
972 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
974 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
976 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
978 ).workersVirtualTaskEndTimestamp
.length
980 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
982 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
984 ).workersVirtualTaskEndTimestamp
985 ).toBeInstanceOf(Array
)
987 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
989 ).workersVirtualTaskEndTimestamp
.length
992 pool
= new DynamicThreadPool(
995 './tests/worker-files/thread/testWorker.js'
998 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1000 ).workersVirtualTaskEndTimestamp
1001 ).toBeInstanceOf(Array
)
1003 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1004 workerChoiceStrategy
1005 ).workersVirtualTaskEndTimestamp
.length
1007 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1008 workerChoiceStrategy
1009 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
1011 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1012 workerChoiceStrategy
1013 ).workersVirtualTaskEndTimestamp
.length
1015 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1017 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1018 workerChoiceStrategy
1019 ).workersVirtualTaskEndTimestamp
1020 ).toBeInstanceOf(Array
)
1022 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1023 workerChoiceStrategy
1024 ).workersVirtualTaskEndTimestamp
.length
1026 // We need to clean up the resources after our test
1027 await pool
.destroy()
1030 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1031 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1032 let pool
= new FixedThreadPool(
1034 './tests/worker-files/thread/testWorker.js',
1035 { workerChoiceStrategy
}
1038 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1052 await pool
.destroy()
1053 pool
= new DynamicThreadPool(
1056 './tests/worker-files/thread/testWorker.js',
1057 { workerChoiceStrategy
}
1060 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1074 // We need to clean up the resources after our test
1075 await pool
.destroy()
1078 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1079 const pool
= new FixedThreadPool(
1081 './tests/worker-files/thread/testWorker.js',
1082 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
1084 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1085 const promises
= new Set()
1086 const maxMultiplier
= 2
1087 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1088 promises
.add(pool
.execute())
1090 await Promise
.all(promises
)
1091 for (const workerNode
of pool
.workerNodes
) {
1092 expect(workerNode
.workerUsage
).toStrictEqual({
1094 executed
: expect
.any(Number
),
1100 aggregate
: expect
.any(Number
),
1101 average
: expect
.any(Number
),
1103 history
: expect
.any(CircularArray
)
1109 history
: expect
.any(CircularArray
)
1113 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1114 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1117 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThanOrEqual(0)
1118 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThanOrEqual(0)
1121 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1122 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1123 ).defaultWorkerWeight
1124 ).toBeGreaterThan(0)
1126 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1127 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1128 ).workerVirtualTaskRunTime
1129 ).toBeGreaterThanOrEqual(0)
1130 // We need to clean up the resources after our test
1131 await pool
.destroy()
1134 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1135 const pool
= new DynamicThreadPool(
1138 './tests/worker-files/thread/testWorker.js',
1139 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
1141 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1142 const promises
= new Set()
1143 const maxMultiplier
= 2
1144 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1145 promises
.add(pool
.execute())
1147 await Promise
.all(promises
)
1148 for (const workerNode
of pool
.workerNodes
) {
1149 expect(workerNode
.workerUsage
).toStrictEqual({
1151 executed
: expect
.any(Number
),
1157 aggregate
: expect
.any(Number
),
1158 average
: expect
.any(Number
),
1160 history
: expect
.any(CircularArray
)
1166 history
: expect
.any(CircularArray
)
1170 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
1171 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1174 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
1175 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
1178 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1179 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1180 ).defaultWorkerWeight
1181 ).toBeGreaterThan(0)
1183 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1184 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1185 ).workerVirtualTaskRunTime
1186 ).toBeGreaterThanOrEqual(0)
1187 // We need to clean up the resources after our test
1188 await pool
.destroy()
1191 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
1192 const pool
= new DynamicThreadPool(
1195 './tests/worker-files/thread/testWorker.js',
1197 workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
,
1198 workerChoiceStrategyOptions
: {
1199 runTime
: { median
: true }
1203 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1204 const promises
= new Set()
1205 const maxMultiplier
= 2
1206 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1207 promises
.add(pool
.execute())
1209 await Promise
.all(promises
)
1210 for (const workerNode
of pool
.workerNodes
) {
1211 expect(workerNode
.workerUsage
).toStrictEqual({
1213 executed
: expect
.any(Number
),
1219 aggregate
: expect
.any(Number
),
1221 median
: expect
.any(Number
),
1222 history
: expect
.any(CircularArray
)
1228 history
: expect
.any(CircularArray
)
1232 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
1233 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1236 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
1237 expect(workerNode
.workerUsage
.runTime
.median
).toBeGreaterThan(0)
1240 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1241 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1242 ).defaultWorkerWeight
1243 ).toBeGreaterThan(0)
1245 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1246 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1247 ).workerVirtualTaskRunTime
1248 ).toBeGreaterThanOrEqual(0)
1249 // We need to clean up the resources after our test
1250 await pool
.destroy()
1253 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1254 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1255 let pool
= new FixedThreadPool(
1257 './tests/worker-files/thread/testWorker.js'
1260 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1261 workerChoiceStrategy
1262 ).currentWorkerNodeId
1265 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1266 workerChoiceStrategy
1267 ).defaultWorkerWeight
1270 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1271 workerChoiceStrategy
1272 ).workerVirtualTaskRunTime
1274 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1276 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1277 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1278 ).currentWorkerNodeId
1281 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1282 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1283 ).defaultWorkerWeight
1284 ).toBeGreaterThan(0)
1286 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1287 workerChoiceStrategy
1288 ).workerVirtualTaskRunTime
1290 await pool
.destroy()
1291 pool
= new DynamicThreadPool(
1294 './tests/worker-files/thread/testWorker.js'
1297 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1298 workerChoiceStrategy
1299 ).currentWorkerNodeId
1302 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1303 workerChoiceStrategy
1304 ).defaultWorkerWeight
1307 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1308 workerChoiceStrategy
1309 ).workerVirtualTaskRunTime
1311 pool
.setWorkerChoiceStrategy(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
1325 ).workerVirtualTaskRunTime
1327 // We need to clean up the resources after our test
1328 await pool
.destroy()
1331 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1332 const workerChoiceStrategy
=
1333 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1334 let pool
= new FixedThreadPool(
1336 './tests/worker-files/thread/testWorker.js',
1337 { workerChoiceStrategy
}
1340 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1354 await pool
.destroy()
1355 pool
= new DynamicThreadPool(
1358 './tests/worker-files/thread/testWorker.js',
1359 { workerChoiceStrategy
}
1362 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1376 // We need to clean up the resources after our test
1377 await pool
.destroy()
1380 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1381 const pool
= new FixedThreadPool(
1383 './tests/worker-files/thread/testWorker.js',
1385 workerChoiceStrategy
:
1386 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1389 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1390 const promises
= new Set()
1391 const maxMultiplier
= 2
1392 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1393 promises
.add(pool
.execute())
1395 await Promise
.all(promises
)
1396 for (const workerNode
of pool
.workerNodes
) {
1397 expect(workerNode
.workerUsage
).toStrictEqual({
1399 executed
: maxMultiplier
,
1408 history
: expect
.any(CircularArray
)
1414 history
: expect
.any(CircularArray
)
1420 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1421 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1422 ).defaultWorkerWeight
1423 ).toBeGreaterThan(0)
1425 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1426 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1430 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1431 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1432 ).currentWorkerNodeId
1435 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1436 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1439 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1440 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1441 ).defaultWorkerWeight
1443 // We need to clean up the resources after our test
1444 await pool
.destroy()
1447 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1448 const pool
= new DynamicThreadPool(
1451 './tests/worker-files/thread/testWorker.js',
1453 workerChoiceStrategy
:
1454 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1457 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1458 const promises
= new Set()
1459 const maxMultiplier
= 2
1460 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1461 promises
.add(pool
.execute())
1463 await Promise
.all(promises
)
1464 for (const workerNode
of pool
.workerNodes
) {
1465 expect(workerNode
.workerUsage
).toStrictEqual({
1467 executed
: maxMultiplier
,
1476 history
: expect
.any(CircularArray
)
1482 history
: expect
.any(CircularArray
)
1488 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1489 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1490 ).defaultWorkerWeight
1491 ).toBeGreaterThan(0)
1493 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1494 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1498 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1499 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1500 ).currentWorkerNodeId
1503 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1504 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1507 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1508 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1509 ).defaultWorkerWeight
1511 // We need to clean up the resources after our test
1512 await pool
.destroy()
1515 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1516 const workerChoiceStrategy
=
1517 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1518 let pool
= new FixedThreadPool(
1520 './tests/worker-files/thread/testWorker.js'
1523 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1524 workerChoiceStrategy
1528 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1529 workerChoiceStrategy
1530 ).currentWorkerNodeId
1533 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1534 workerChoiceStrategy
1535 ).defaultWorkerWeight
1538 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1539 workerChoiceStrategy
1542 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1544 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1545 workerChoiceStrategy
1549 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1550 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1551 ).currentWorkerNodeId
1554 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1555 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1556 ).defaultWorkerWeight
1557 ).toBeGreaterThan(0)
1559 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1560 workerChoiceStrategy
1563 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1564 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1565 ).defaultWorkerWeight
1567 await pool
.destroy()
1568 pool
= new DynamicThreadPool(
1571 './tests/worker-files/thread/testWorker.js'
1574 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1575 workerChoiceStrategy
1579 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1580 workerChoiceStrategy
1581 ).currentWorkerNodeId
1584 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1585 workerChoiceStrategy
1586 ).defaultWorkerWeight
1589 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1590 workerChoiceStrategy
1593 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1595 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1596 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1597 ).currentWorkerNodeId
1600 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1601 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1602 ).defaultWorkerWeight
1603 ).toBeGreaterThan(0)
1605 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1606 workerChoiceStrategy
1609 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1610 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1611 ).defaultWorkerWeight
1613 // We need to clean up the resources after our test
1614 await pool
.destroy()
1617 it('Verify unknown strategy throw error', () => {
1620 new DynamicThreadPool(
1623 './tests/worker-files/thread/testWorker.js',
1624 { workerChoiceStrategy
: 'UNKNOWN_STRATEGY' }
1626 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")