1 const { expect
} = require('expect')
3 WorkerChoiceStrategies
,
7 } = require('../../../lib')
8 const { CircularArray
} = require('../../../lib/circular-array')
10 describe('Selection strategies test suite', () => {
14 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
15 expect(WorkerChoiceStrategies
.ROUND_ROBIN
).toBe('ROUND_ROBIN')
16 expect(WorkerChoiceStrategies
.LEAST_USED
).toBe('LEAST_USED')
17 expect(WorkerChoiceStrategies
.LEAST_BUSY
).toBe('LEAST_BUSY')
18 expect(WorkerChoiceStrategies
.LEAST_ELU
).toBe('LEAST_ELU')
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
}
126 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
141 pool
= new DynamicThreadPool(
144 './tests/worker-files/thread/testWorker.js',
145 { workerChoiceStrategy
}
148 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
162 // We need to clean up the resources after our test
166 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
167 const pool
= new FixedThreadPool(
169 './tests/worker-files/thread/testWorker.js',
170 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
172 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
173 const promises
= new Set()
174 const maxMultiplier
= 2
175 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
176 promises
.add(pool
.execute())
178 await Promise
.all(promises
)
179 for (const workerNode
of pool
.workerNodes
) {
180 expect(workerNode
.workerUsage
).toStrictEqual({
182 executed
: maxMultiplier
,
191 history
: expect
.any(CircularArray
)
197 history
: expect
.any(CircularArray
)
203 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
204 WorkerChoiceStrategies
.ROUND_ROBIN
207 // We need to clean up the resources after our test
211 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
212 const pool
= new DynamicThreadPool(
215 './tests/worker-files/thread/testWorker.js',
216 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
218 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
219 const promises
= new Set()
220 const maxMultiplier
= 2
221 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
222 promises
.add(pool
.execute())
224 await Promise
.all(promises
)
225 for (const workerNode
of pool
.workerNodes
) {
226 expect(workerNode
.workerUsage
).toStrictEqual({
228 executed
: maxMultiplier
,
237 history
: expect
.any(CircularArray
)
243 history
: expect
.any(CircularArray
)
249 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
250 WorkerChoiceStrategies
.ROUND_ROBIN
253 // We need to clean up the resources after our test
257 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
258 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
259 let pool
= new FixedClusterPool(
261 './tests/worker-files/cluster/testWorker.js',
262 { workerChoiceStrategy
}
264 let results
= new Set()
265 for (let i
= 0; i
< max
; i
++) {
266 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.id
)
268 expect(results
.size
).toBe(max
)
270 pool
= new FixedThreadPool(
272 './tests/worker-files/thread/testWorker.js',
273 { workerChoiceStrategy
}
276 for (let i
= 0; i
< max
; i
++) {
277 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.threadId
)
279 expect(results
.size
).toBe(max
)
283 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
284 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
285 let pool
= new FixedThreadPool(
287 './tests/worker-files/thread/testWorker.js',
288 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
291 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
295 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
297 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
298 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
302 pool
= new DynamicThreadPool(
305 './tests/worker-files/thread/testWorker.js',
306 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
309 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
313 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
315 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
316 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
319 // We need to clean up the resources after our test
323 it('Verify LEAST_USED strategy default tasks usage statistics requirements', async () => {
324 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
325 let pool
= new FixedThreadPool(
327 './tests/worker-files/thread/testWorker.js',
328 { workerChoiceStrategy
}
331 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
346 pool
= new DynamicThreadPool(
349 './tests/worker-files/thread/testWorker.js',
350 { workerChoiceStrategy
}
353 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
367 // We need to clean up the resources after our test
371 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
372 const pool
= new FixedThreadPool(
374 './tests/worker-files/thread/testWorker.js',
375 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
377 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
378 const promises
= new Set()
379 const maxMultiplier
= 2
380 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
381 promises
.add(pool
.execute())
383 await Promise
.all(promises
)
384 for (const workerNode
of pool
.workerNodes
) {
385 expect(workerNode
.workerUsage
).toStrictEqual({
387 executed
: maxMultiplier
,
396 history
: expect
.any(CircularArray
)
402 history
: expect
.any(CircularArray
)
407 // We need to clean up the resources after our test
411 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
412 const pool
= new DynamicThreadPool(
415 './tests/worker-files/thread/testWorker.js',
416 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
418 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
419 const promises
= new Set()
420 const maxMultiplier
= 2
421 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
422 promises
.add(pool
.execute())
424 await Promise
.all(promises
)
425 for (const workerNode
of pool
.workerNodes
) {
426 expect(workerNode
.workerUsage
).toStrictEqual({
428 executed
: maxMultiplier
,
437 history
: expect
.any(CircularArray
)
443 history
: expect
.any(CircularArray
)
449 // We need to clean up the resources after our test
453 it('Verify LEAST_BUSY strategy default tasks usage statistics requirements', async () => {
454 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
455 let pool
= new FixedThreadPool(
457 './tests/worker-files/thread/testWorker.js',
458 { workerChoiceStrategy
}
461 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
476 pool
= new DynamicThreadPool(
479 './tests/worker-files/thread/testWorker.js',
480 { workerChoiceStrategy
}
483 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
497 // We need to clean up the resources after our test
501 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
502 const pool
= new FixedThreadPool(
504 './tests/worker-files/thread/testWorker.js',
505 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
507 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
508 const promises
= new Set()
509 const maxMultiplier
= 2
510 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
511 promises
.add(pool
.execute())
513 await Promise
.all(promises
)
514 for (const workerNode
of pool
.workerNodes
) {
515 expect(workerNode
.workerUsage
).toStrictEqual({
517 executed
: expect
.any(Number
),
523 aggregate
: expect
.any(Number
),
526 history
: expect
.any(CircularArray
)
529 aggregate
: expect
.any(Number
),
532 history
: expect
.any(CircularArray
)
536 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
537 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
540 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThanOrEqual(0)
541 expect(workerNode
.workerUsage
.waitTime
.aggregate
).toBeGreaterThanOrEqual(
545 // We need to clean up the resources after our test
549 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
550 const pool
= new DynamicThreadPool(
553 './tests/worker-files/thread/testWorker.js',
554 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
556 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
557 const promises
= new Set()
558 const maxMultiplier
= 2
559 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
560 promises
.add(pool
.execute())
562 await Promise
.all(promises
)
563 for (const workerNode
of pool
.workerNodes
) {
564 expect(workerNode
.workerUsage
).toStrictEqual({
566 executed
: expect
.any(Number
),
572 aggregate
: expect
.any(Number
),
575 history
: expect
.any(CircularArray
)
578 aggregate
: expect
.any(Number
),
581 history
: expect
.any(CircularArray
)
585 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
586 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
589 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
590 expect(workerNode
.workerUsage
.waitTime
.aggregate
).toBeGreaterThan(0)
592 // We need to clean up the resources after our test
596 it('Verify LEAST_ELU strategy default tasks usage statistics requirements', async () => {
597 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_ELU
598 let pool
= new FixedThreadPool(
600 './tests/worker-files/thread/testWorker.js',
601 { workerChoiceStrategy
}
604 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
619 pool
= new DynamicThreadPool(
622 './tests/worker-files/thread/testWorker.js',
623 { workerChoiceStrategy
}
626 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
640 // We need to clean up the resources after our test
644 it('Verify LEAST_ELU strategy can be run in a fixed pool', async () => {
645 const pool
= new FixedThreadPool(
647 './tests/worker-files/thread/testWorker.js',
648 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_ELU
}
650 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
651 const promises
= new Set()
652 const maxMultiplier
= 2
653 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
654 promises
.add(pool
.execute())
656 await Promise
.all(promises
)
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 promises
= new Set()
711 const maxMultiplier
= 2
712 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
713 promises
.add(pool
.execute())
715 await Promise
.all(promises
)
716 for (const workerNode
of pool
.workerNodes
) {
717 const expectedWorkerUsage
= {
719 executed
: expect
.any(Number
),
728 history
: expect
.any(CircularArray
)
734 history
: expect
.any(CircularArray
)
737 if (workerNode
.workerUsage
.elu
=== undefined) {
738 expect(workerNode
.workerUsage
).toStrictEqual({
739 ...expectedWorkerUsage
,
743 expect(workerNode
.workerUsage
).toStrictEqual({
744 ...expectedWorkerUsage
,
746 active
: expect
.any(Number
),
752 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
753 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
757 // We need to clean up the resources after our test
761 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
762 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
763 let pool
= new FixedThreadPool(
765 './tests/worker-files/thread/testWorker.js',
766 { workerChoiceStrategy
}
769 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
784 pool
= new DynamicThreadPool(
787 './tests/worker-files/thread/testWorker.js',
788 { workerChoiceStrategy
}
791 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
805 // We need to clean up the resources after our test
809 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
810 const pool
= new FixedThreadPool(
812 './tests/worker-files/thread/testWorker.js',
813 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
815 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
816 const promises
= new Set()
817 const maxMultiplier
= 2
818 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
819 promises
.add(pool
.execute())
821 await Promise
.all(promises
)
822 for (const workerNode
of pool
.workerNodes
) {
823 expect(workerNode
.workerUsage
).toStrictEqual({
825 executed
: maxMultiplier
,
831 aggregate
: expect
.any(Number
),
832 average
: expect
.any(Number
),
834 history
: expect
.any(CircularArray
)
840 history
: expect
.any(CircularArray
)
844 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
845 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
848 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
849 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
850 ).workersVirtualTaskEndTimestamp
.length
851 ).toBe(pool
.workerNodes
.length
)
852 // We need to clean up the resources after our test
856 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
857 const pool
= new DynamicThreadPool(
860 './tests/worker-files/thread/testWorker.js',
861 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
863 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
864 const promises
= new Set()
865 const maxMultiplier
= 2
866 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
867 promises
.add(pool
.execute())
869 await Promise
.all(promises
)
870 for (const workerNode
of pool
.workerNodes
) {
871 expect(workerNode
.workerUsage
).toStrictEqual({
873 executed
: maxMultiplier
,
879 aggregate
: expect
.any(Number
),
880 average
: expect
.any(Number
),
882 history
: expect
.any(CircularArray
)
888 history
: expect
.any(CircularArray
)
892 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
893 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
896 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
897 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
898 ).workersVirtualTaskEndTimestamp
.length
899 ).toBe(pool
.workerNodes
.length
)
900 // We need to clean up the resources after our test
904 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
905 const pool
= new DynamicThreadPool(
908 './tests/worker-files/thread/testWorker.js',
910 workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
,
911 workerChoiceStrategyOptions
: {
912 runTime
: { median
: true }
916 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
917 const promises
= new Set()
918 const maxMultiplier
= 2
919 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
920 promises
.add(pool
.execute())
922 await Promise
.all(promises
)
923 for (const workerNode
of pool
.workerNodes
) {
924 expect(workerNode
.workerUsage
).toStrictEqual({
926 executed
: maxMultiplier
,
932 aggregate
: expect
.any(Number
),
934 median
: expect
.any(Number
),
935 history
: expect
.any(CircularArray
)
941 history
: expect
.any(CircularArray
)
945 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
946 expect(workerNode
.workerUsage
.runTime
.median
).toBeGreaterThan(0)
949 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
950 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
951 ).workersVirtualTaskEndTimestamp
.length
952 ).toBe(pool
.workerNodes
.length
)
953 // We need to clean up the resources after our test
957 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
958 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
959 let pool
= new FixedThreadPool(
961 './tests/worker-files/thread/testWorker.js'
964 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
966 ).workersVirtualTaskEndTimestamp
967 ).toBeInstanceOf(Array
)
969 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
971 ).workersVirtualTaskEndTimestamp
.length
973 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
975 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
977 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
979 ).workersVirtualTaskEndTimestamp
.length
981 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
983 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
985 ).workersVirtualTaskEndTimestamp
986 ).toBeInstanceOf(Array
)
988 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
990 ).workersVirtualTaskEndTimestamp
.length
993 pool
= new DynamicThreadPool(
996 './tests/worker-files/thread/testWorker.js'
999 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1000 workerChoiceStrategy
1001 ).workersVirtualTaskEndTimestamp
1002 ).toBeInstanceOf(Array
)
1004 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1005 workerChoiceStrategy
1006 ).workersVirtualTaskEndTimestamp
.length
1008 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1009 workerChoiceStrategy
1010 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
1012 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1013 workerChoiceStrategy
1014 ).workersVirtualTaskEndTimestamp
.length
1016 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1018 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1019 workerChoiceStrategy
1020 ).workersVirtualTaskEndTimestamp
1021 ).toBeInstanceOf(Array
)
1023 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1024 workerChoiceStrategy
1025 ).workersVirtualTaskEndTimestamp
.length
1027 // We need to clean up the resources after our test
1028 await pool
.destroy()
1031 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1032 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1033 let pool
= new FixedThreadPool(
1035 './tests/worker-files/thread/testWorker.js',
1036 { workerChoiceStrategy
}
1039 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1053 await pool
.destroy()
1054 pool
= new DynamicThreadPool(
1057 './tests/worker-files/thread/testWorker.js',
1058 { workerChoiceStrategy
}
1061 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1075 // We need to clean up the resources after our test
1076 await pool
.destroy()
1079 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1080 const pool
= new FixedThreadPool(
1082 './tests/worker-files/thread/testWorker.js',
1083 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
1085 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1086 const promises
= new Set()
1087 const maxMultiplier
= 2
1088 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1089 promises
.add(pool
.execute())
1091 await Promise
.all(promises
)
1092 for (const workerNode
of pool
.workerNodes
) {
1093 expect(workerNode
.workerUsage
).toStrictEqual({
1095 executed
: expect
.any(Number
),
1101 aggregate
: expect
.any(Number
),
1102 average
: expect
.any(Number
),
1104 history
: expect
.any(CircularArray
)
1110 history
: expect
.any(CircularArray
)
1114 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1115 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1118 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThanOrEqual(0)
1119 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThanOrEqual(0)
1122 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1123 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1124 ).defaultWorkerWeight
1125 ).toBeGreaterThan(0)
1127 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1128 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1129 ).workerVirtualTaskRunTime
1130 ).toBeGreaterThanOrEqual(0)
1131 // We need to clean up the resources after our test
1132 await pool
.destroy()
1135 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1136 const pool
= new DynamicThreadPool(
1139 './tests/worker-files/thread/testWorker.js',
1140 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
1142 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1143 const promises
= new Set()
1144 const maxMultiplier
= 2
1145 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1146 promises
.add(pool
.execute())
1148 await Promise
.all(promises
)
1149 for (const workerNode
of pool
.workerNodes
) {
1150 expect(workerNode
.workerUsage
).toStrictEqual({
1152 executed
: expect
.any(Number
),
1158 aggregate
: expect
.any(Number
),
1159 average
: expect
.any(Number
),
1161 history
: expect
.any(CircularArray
)
1167 history
: expect
.any(CircularArray
)
1171 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
1172 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1175 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
1176 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
1179 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1180 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1181 ).defaultWorkerWeight
1182 ).toBeGreaterThan(0)
1184 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1185 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1186 ).workerVirtualTaskRunTime
1187 ).toBeGreaterThanOrEqual(0)
1188 // We need to clean up the resources after our test
1189 await pool
.destroy()
1192 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
1193 const pool
= new DynamicThreadPool(
1196 './tests/worker-files/thread/testWorker.js',
1198 workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
,
1199 workerChoiceStrategyOptions
: {
1200 runTime
: { median
: true }
1204 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1205 const promises
= new Set()
1206 const maxMultiplier
= 2
1207 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1208 promises
.add(pool
.execute())
1210 await Promise
.all(promises
)
1211 for (const workerNode
of pool
.workerNodes
) {
1212 expect(workerNode
.workerUsage
).toStrictEqual({
1214 executed
: expect
.any(Number
),
1220 aggregate
: expect
.any(Number
),
1222 median
: expect
.any(Number
),
1223 history
: expect
.any(CircularArray
)
1229 history
: expect
.any(CircularArray
)
1233 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
1234 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1237 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
1238 expect(workerNode
.workerUsage
.runTime
.median
).toBeGreaterThan(0)
1241 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1242 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1243 ).defaultWorkerWeight
1244 ).toBeGreaterThan(0)
1246 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1247 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1248 ).workerVirtualTaskRunTime
1249 ).toBeGreaterThanOrEqual(0)
1250 // We need to clean up the resources after our test
1251 await pool
.destroy()
1254 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1255 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1256 let pool
= new FixedThreadPool(
1258 './tests/worker-files/thread/testWorker.js'
1261 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1262 workerChoiceStrategy
1263 ).currentWorkerNodeId
1266 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1267 workerChoiceStrategy
1268 ).defaultWorkerWeight
1271 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1272 workerChoiceStrategy
1273 ).workerVirtualTaskRunTime
1275 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1277 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1278 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1279 ).currentWorkerNodeId
1282 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1283 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1284 ).defaultWorkerWeight
1285 ).toBeGreaterThan(0)
1287 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1288 workerChoiceStrategy
1289 ).workerVirtualTaskRunTime
1291 await pool
.destroy()
1292 pool
= new DynamicThreadPool(
1295 './tests/worker-files/thread/testWorker.js'
1298 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1299 workerChoiceStrategy
1300 ).currentWorkerNodeId
1303 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1304 workerChoiceStrategy
1305 ).defaultWorkerWeight
1308 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1309 workerChoiceStrategy
1310 ).workerVirtualTaskRunTime
1312 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1314 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1315 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1316 ).currentWorkerNodeId
1319 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1320 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1321 ).defaultWorkerWeight
1322 ).toBeGreaterThan(0)
1324 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1325 workerChoiceStrategy
1326 ).workerVirtualTaskRunTime
1328 // We need to clean up the resources after our test
1329 await pool
.destroy()
1332 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1333 const workerChoiceStrategy
=
1334 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1335 let pool
= new FixedThreadPool(
1337 './tests/worker-files/thread/testWorker.js',
1338 { workerChoiceStrategy
}
1341 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1355 await pool
.destroy()
1356 pool
= new DynamicThreadPool(
1359 './tests/worker-files/thread/testWorker.js',
1360 { workerChoiceStrategy
}
1363 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1377 // We need to clean up the resources after our test
1378 await pool
.destroy()
1381 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1382 const pool
= new FixedThreadPool(
1384 './tests/worker-files/thread/testWorker.js',
1386 workerChoiceStrategy
:
1387 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1390 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1391 const promises
= new Set()
1392 const maxMultiplier
= 2
1393 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1394 promises
.add(pool
.execute())
1396 await Promise
.all(promises
)
1397 for (const workerNode
of pool
.workerNodes
) {
1398 expect(workerNode
.workerUsage
).toStrictEqual({
1400 executed
: maxMultiplier
,
1409 history
: expect
.any(CircularArray
)
1415 history
: expect
.any(CircularArray
)
1421 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1422 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1423 ).defaultWorkerWeight
1424 ).toBeGreaterThan(0)
1426 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1427 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1431 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1432 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1433 ).currentWorkerNodeId
1436 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1437 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1440 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1441 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1442 ).defaultWorkerWeight
1444 // We need to clean up the resources after our test
1445 await pool
.destroy()
1448 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1449 const pool
= new DynamicThreadPool(
1452 './tests/worker-files/thread/testWorker.js',
1454 workerChoiceStrategy
:
1455 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1458 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1459 const promises
= new Set()
1460 const maxMultiplier
= 2
1461 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1462 promises
.add(pool
.execute())
1464 await Promise
.all(promises
)
1465 for (const workerNode
of pool
.workerNodes
) {
1466 expect(workerNode
.workerUsage
).toStrictEqual({
1468 executed
: maxMultiplier
,
1477 history
: expect
.any(CircularArray
)
1483 history
: expect
.any(CircularArray
)
1489 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1490 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1491 ).defaultWorkerWeight
1492 ).toBeGreaterThan(0)
1494 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1495 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1499 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1500 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1501 ).currentWorkerNodeId
1504 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1505 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1508 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1509 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1510 ).defaultWorkerWeight
1512 // We need to clean up the resources after our test
1513 await pool
.destroy()
1516 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1517 const workerChoiceStrategy
=
1518 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1519 let pool
= new FixedThreadPool(
1521 './tests/worker-files/thread/testWorker.js'
1524 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1525 workerChoiceStrategy
1529 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1530 workerChoiceStrategy
1531 ).currentWorkerNodeId
1534 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1535 workerChoiceStrategy
1536 ).defaultWorkerWeight
1539 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1540 workerChoiceStrategy
1543 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1545 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1546 workerChoiceStrategy
1550 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1551 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1552 ).currentWorkerNodeId
1555 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1556 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1557 ).defaultWorkerWeight
1558 ).toBeGreaterThan(0)
1560 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1561 workerChoiceStrategy
1564 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1565 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1566 ).defaultWorkerWeight
1568 await pool
.destroy()
1569 pool
= new DynamicThreadPool(
1572 './tests/worker-files/thread/testWorker.js'
1575 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1576 workerChoiceStrategy
1580 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1581 workerChoiceStrategy
1582 ).currentWorkerNodeId
1585 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1586 workerChoiceStrategy
1587 ).defaultWorkerWeight
1590 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1591 workerChoiceStrategy
1594 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1596 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1597 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1598 ).currentWorkerNodeId
1601 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1602 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1603 ).defaultWorkerWeight
1604 ).toBeGreaterThan(0)
1606 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1607 workerChoiceStrategy
1610 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1611 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1612 ).defaultWorkerWeight
1614 // We need to clean up the resources after our test
1615 await pool
.destroy()
1618 it('Verify unknown strategy throw error', () => {
1621 new DynamicThreadPool(
1624 './tests/worker-files/thread/testWorker.js',
1625 { workerChoiceStrategy
: 'UNKNOWN_STRATEGY' }
1627 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")