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()
145 pool
= new DynamicThreadPool(
148 './tests/worker-files/thread/testWorker.js',
149 { workerChoiceStrategy
}
152 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
170 // We need to clean up the resources after our test
174 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
175 const pool
= new FixedThreadPool(
177 './tests/worker-files/thread/testWorker.js',
178 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
180 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
181 const promises
= new Set()
182 const maxMultiplier
= 2
183 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
184 promises
.add(pool
.execute())
186 await Promise
.all(promises
)
187 for (const workerNode
of pool
.workerNodes
) {
188 expect(workerNode
.workerUsage
).toStrictEqual({
190 executed
: maxMultiplier
,
199 history
: expect
.any(CircularArray
)
205 history
: expect
.any(CircularArray
)
212 history
: expect
.any(CircularArray
)
218 history
: expect
.any(CircularArray
)
225 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
226 WorkerChoiceStrategies
.ROUND_ROBIN
229 // We need to clean up the resources after our test
233 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
234 const pool
= new DynamicThreadPool(
237 './tests/worker-files/thread/testWorker.js',
238 { workerChoiceStrategy
: WorkerChoiceStrategies
.ROUND_ROBIN
}
240 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
241 const promises
= new Set()
242 const maxMultiplier
= 2
243 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
244 promises
.add(pool
.execute())
246 await Promise
.all(promises
)
247 for (const workerNode
of pool
.workerNodes
) {
248 expect(workerNode
.workerUsage
).toStrictEqual({
250 executed
: maxMultiplier
,
259 history
: expect
.any(CircularArray
)
265 history
: expect
.any(CircularArray
)
272 history
: expect
.any(CircularArray
)
278 history
: expect
.any(CircularArray
)
285 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
286 WorkerChoiceStrategies
.ROUND_ROBIN
289 // We need to clean up the resources after our test
293 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
294 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
295 let pool
= new FixedClusterPool(
297 './tests/worker-files/cluster/testWorker.js',
298 { workerChoiceStrategy
}
300 let results
= new Set()
301 for (let i
= 0; i
< max
; i
++) {
302 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.id
)
304 expect(results
.size
).toBe(max
)
306 pool
= new FixedThreadPool(
308 './tests/worker-files/thread/testWorker.js',
309 { workerChoiceStrategy
}
312 for (let i
= 0; i
< max
; i
++) {
313 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.threadId
)
315 expect(results
.size
).toBe(max
)
319 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
320 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
321 let pool
= new FixedThreadPool(
323 './tests/worker-files/thread/testWorker.js',
324 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
327 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
331 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
333 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
334 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
338 pool
= new DynamicThreadPool(
341 './tests/worker-files/thread/testWorker.js',
342 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
345 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
349 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
351 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
352 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
355 // We need to clean up the resources after our test
359 it('Verify LEAST_USED strategy default tasks usage statistics requirements', async () => {
360 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
361 let pool
= new FixedThreadPool(
363 './tests/worker-files/thread/testWorker.js',
364 { workerChoiceStrategy
}
367 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
386 pool
= new DynamicThreadPool(
389 './tests/worker-files/thread/testWorker.js',
390 { workerChoiceStrategy
}
393 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
411 // We need to clean up the resources after our test
415 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
416 const pool
= new FixedThreadPool(
418 './tests/worker-files/thread/testWorker.js',
419 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
421 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
422 const promises
= new Set()
423 const maxMultiplier
= 2
424 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
425 promises
.add(pool
.execute())
427 await Promise
.all(promises
)
428 for (const workerNode
of pool
.workerNodes
) {
429 expect(workerNode
.workerUsage
).toStrictEqual({
431 executed
: maxMultiplier
,
440 history
: expect
.any(CircularArray
)
446 history
: expect
.any(CircularArray
)
453 history
: expect
.any(CircularArray
)
459 history
: expect
.any(CircularArray
)
465 // We need to clean up the resources after our test
469 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
470 const pool
= new DynamicThreadPool(
473 './tests/worker-files/thread/testWorker.js',
474 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
476 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
477 const promises
= new Set()
478 const maxMultiplier
= 2
479 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
480 promises
.add(pool
.execute())
482 await Promise
.all(promises
)
483 for (const workerNode
of pool
.workerNodes
) {
484 expect(workerNode
.workerUsage
).toStrictEqual({
486 executed
: maxMultiplier
,
495 history
: expect
.any(CircularArray
)
501 history
: expect
.any(CircularArray
)
508 history
: expect
.any(CircularArray
)
514 history
: expect
.any(CircularArray
)
520 // We need to clean up the resources after our test
524 it('Verify LEAST_BUSY strategy default tasks usage statistics requirements', async () => {
525 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
526 let pool
= new FixedThreadPool(
528 './tests/worker-files/thread/testWorker.js',
529 { workerChoiceStrategy
}
532 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
551 pool
= new DynamicThreadPool(
554 './tests/worker-files/thread/testWorker.js',
555 { workerChoiceStrategy
}
558 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
576 // We need to clean up the resources after our test
580 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
581 const pool
= new FixedThreadPool(
583 './tests/worker-files/thread/testWorker.js',
584 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
586 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
587 const promises
= new Set()
588 const maxMultiplier
= 2
589 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
590 promises
.add(pool
.execute())
592 await Promise
.all(promises
)
593 for (const workerNode
of pool
.workerNodes
) {
594 expect(workerNode
.workerUsage
).toStrictEqual({
596 executed
: expect
.any(Number
),
602 aggregate
: expect
.any(Number
),
605 history
: expect
.any(CircularArray
)
608 aggregate
: expect
.any(Number
),
611 history
: expect
.any(CircularArray
)
618 history
: expect
.any(CircularArray
)
624 history
: expect
.any(CircularArray
)
629 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
630 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
633 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThanOrEqual(0)
634 expect(workerNode
.workerUsage
.waitTime
.aggregate
).toBeGreaterThanOrEqual(
638 // We need to clean up the resources after our test
642 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
643 const pool
= new DynamicThreadPool(
646 './tests/worker-files/thread/testWorker.js',
647 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
649 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
650 const promises
= new Set()
651 const maxMultiplier
= 2
652 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
653 promises
.add(pool
.execute())
655 await Promise
.all(promises
)
656 for (const workerNode
of pool
.workerNodes
) {
657 expect(workerNode
.workerUsage
).toStrictEqual({
659 executed
: expect
.any(Number
),
665 aggregate
: expect
.any(Number
),
668 history
: expect
.any(CircularArray
)
671 aggregate
: expect
.any(Number
),
674 history
: expect
.any(CircularArray
)
681 history
: expect
.any(CircularArray
)
687 history
: expect
.any(CircularArray
)
692 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
693 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
696 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
697 expect(workerNode
.workerUsage
.waitTime
.aggregate
).toBeGreaterThan(0)
699 // We need to clean up the resources after our test
703 it('Verify LEAST_ELU strategy default tasks usage statistics requirements', async () => {
704 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_ELU
705 let pool
= new FixedThreadPool(
707 './tests/worker-files/thread/testWorker.js',
708 { workerChoiceStrategy
}
711 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
730 pool
= new DynamicThreadPool(
733 './tests/worker-files/thread/testWorker.js',
734 { workerChoiceStrategy
}
737 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
755 // We need to clean up the resources after our test
759 it('Verify LEAST_ELU strategy can be run in a fixed pool', async () => {
760 const pool
= new FixedThreadPool(
762 './tests/worker-files/thread/testWorker.js',
763 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_ELU
}
765 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
766 const promises
= new Set()
767 const maxMultiplier
= 2
768 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
769 promises
.add(pool
.execute())
771 await Promise
.all(promises
)
772 for (const workerNode
of pool
.workerNodes
) {
773 expect(workerNode
.workerUsage
).toStrictEqual({
775 executed
: expect
.any(Number
),
784 history
: expect
.any(CircularArray
)
790 history
: expect
.any(CircularArray
)
797 history
: expect
.any(CircularArray
)
800 aggregate
: expect
.any(Number
),
803 history
: expect
.any(CircularArray
)
805 utilization
: expect
.any(Number
)
808 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
809 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
812 expect(workerNode
.workerUsage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
813 expect(workerNode
.workerUsage
.elu
.utilization
).toBeLessThanOrEqual(1)
815 // We need to clean up the resources after our test
819 it('Verify LEAST_ELU strategy can be run in a dynamic pool', async () => {
820 const pool
= new DynamicThreadPool(
823 './tests/worker-files/thread/testWorker.js',
824 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_ELU
}
826 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
827 const promises
= new Set()
828 const maxMultiplier
= 2
829 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
830 promises
.add(pool
.execute())
832 await Promise
.all(promises
)
833 for (const workerNode
of pool
.workerNodes
) {
834 expect(workerNode
.workerUsage
).toStrictEqual({
836 executed
: expect
.any(Number
),
845 history
: expect
.any(CircularArray
)
851 history
: expect
.any(CircularArray
)
858 history
: expect
.any(CircularArray
)
861 aggregate
: expect
.any(Number
),
864 history
: expect
.any(CircularArray
)
866 utilization
: expect
.any(Number
)
869 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
870 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
873 expect(workerNode
.workerUsage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
874 expect(workerNode
.workerUsage
.elu
.utilization
).toBeLessThanOrEqual(1)
876 // We need to clean up the resources after our test
880 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
881 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
882 let pool
= new FixedThreadPool(
884 './tests/worker-files/thread/testWorker.js',
885 { workerChoiceStrategy
}
888 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
907 pool
= new DynamicThreadPool(
910 './tests/worker-files/thread/testWorker.js',
911 { workerChoiceStrategy
}
914 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
932 // We need to clean up the resources after our test
936 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
937 const pool
= new FixedThreadPool(
939 './tests/worker-files/thread/testWorker.js',
940 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
942 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
943 const promises
= new Set()
944 const maxMultiplier
= 2
945 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
946 promises
.add(pool
.execute())
948 await Promise
.all(promises
)
949 for (const workerNode
of pool
.workerNodes
) {
950 expect(workerNode
.workerUsage
).toStrictEqual({
952 executed
: maxMultiplier
,
958 aggregate
: expect
.any(Number
),
959 average
: expect
.any(Number
),
961 history
: expect
.any(CircularArray
)
967 history
: expect
.any(CircularArray
)
974 history
: expect
.any(CircularArray
)
980 history
: expect
.any(CircularArray
)
985 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
986 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
989 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
990 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
991 ).workersVirtualTaskEndTimestamp
.length
992 ).toBe(pool
.workerNodes
.length
)
993 // We need to clean up the resources after our test
997 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
998 const pool
= new DynamicThreadPool(
1001 './tests/worker-files/thread/testWorker.js',
1002 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
1004 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1005 const promises
= new Set()
1006 const maxMultiplier
= 2
1007 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1008 promises
.add(pool
.execute())
1010 await Promise
.all(promises
)
1011 for (const workerNode
of pool
.workerNodes
) {
1012 expect(workerNode
.workerUsage
).toStrictEqual({
1014 executed
: maxMultiplier
,
1020 aggregate
: expect
.any(Number
),
1021 average
: expect
.any(Number
),
1023 history
: expect
.any(CircularArray
)
1029 history
: expect
.any(CircularArray
)
1036 history
: expect
.any(CircularArray
)
1042 history
: expect
.any(CircularArray
)
1047 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
1048 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
1051 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1052 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1053 ).workersVirtualTaskEndTimestamp
.length
1054 ).toBe(pool
.workerNodes
.length
)
1055 // We need to clean up the resources after our test
1056 await pool
.destroy()
1059 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
1060 const pool
= new DynamicThreadPool(
1063 './tests/worker-files/thread/testWorker.js',
1065 workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
,
1066 workerChoiceStrategyOptions
: {
1067 runTime
: { median
: true }
1071 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1072 const promises
= new Set()
1073 const maxMultiplier
= 2
1074 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1075 promises
.add(pool
.execute())
1077 await Promise
.all(promises
)
1078 for (const workerNode
of pool
.workerNodes
) {
1079 expect(workerNode
.workerUsage
).toStrictEqual({
1081 executed
: maxMultiplier
,
1087 aggregate
: expect
.any(Number
),
1089 median
: expect
.any(Number
),
1090 history
: expect
.any(CircularArray
)
1096 history
: expect
.any(CircularArray
)
1103 history
: expect
.any(CircularArray
)
1109 history
: expect
.any(CircularArray
)
1114 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
1115 expect(workerNode
.workerUsage
.runTime
.median
).toBeGreaterThan(0)
1118 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1119 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1120 ).workersVirtualTaskEndTimestamp
.length
1121 ).toBe(pool
.workerNodes
.length
)
1122 // We need to clean up the resources after our test
1123 await pool
.destroy()
1126 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
1127 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
1128 let pool
= new FixedThreadPool(
1130 './tests/worker-files/thread/testWorker.js'
1133 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1134 workerChoiceStrategy
1135 ).workersVirtualTaskEndTimestamp
1136 ).toBeInstanceOf(Array
)
1138 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1139 workerChoiceStrategy
1140 ).workersVirtualTaskEndTimestamp
.length
1142 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1143 workerChoiceStrategy
1144 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
1146 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1147 workerChoiceStrategy
1148 ).workersVirtualTaskEndTimestamp
.length
1150 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1152 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1153 workerChoiceStrategy
1154 ).workersVirtualTaskEndTimestamp
1155 ).toBeInstanceOf(Array
)
1157 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1158 workerChoiceStrategy
1159 ).workersVirtualTaskEndTimestamp
.length
1161 await pool
.destroy()
1162 pool
= new DynamicThreadPool(
1165 './tests/worker-files/thread/testWorker.js'
1168 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1169 workerChoiceStrategy
1170 ).workersVirtualTaskEndTimestamp
1171 ).toBeInstanceOf(Array
)
1173 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1174 workerChoiceStrategy
1175 ).workersVirtualTaskEndTimestamp
.length
1177 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1178 workerChoiceStrategy
1179 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
1181 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1182 workerChoiceStrategy
1183 ).workersVirtualTaskEndTimestamp
.length
1185 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1187 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1188 workerChoiceStrategy
1189 ).workersVirtualTaskEndTimestamp
1190 ).toBeInstanceOf(Array
)
1192 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1193 workerChoiceStrategy
1194 ).workersVirtualTaskEndTimestamp
.length
1196 // We need to clean up the resources after our test
1197 await pool
.destroy()
1200 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1201 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1202 let pool
= new FixedThreadPool(
1204 './tests/worker-files/thread/testWorker.js',
1205 { workerChoiceStrategy
}
1208 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1226 await pool
.destroy()
1227 pool
= new DynamicThreadPool(
1230 './tests/worker-files/thread/testWorker.js',
1231 { workerChoiceStrategy
}
1234 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1252 // We need to clean up the resources after our test
1253 await pool
.destroy()
1256 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1257 const pool
= new FixedThreadPool(
1259 './tests/worker-files/thread/testWorker.js',
1260 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
1262 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1263 const promises
= new Set()
1264 const maxMultiplier
= 2
1265 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1266 promises
.add(pool
.execute())
1268 await Promise
.all(promises
)
1269 for (const workerNode
of pool
.workerNodes
) {
1270 expect(workerNode
.workerUsage
).toStrictEqual({
1272 executed
: expect
.any(Number
),
1278 aggregate
: expect
.any(Number
),
1279 average
: expect
.any(Number
),
1281 history
: expect
.any(CircularArray
)
1287 history
: expect
.any(CircularArray
)
1294 history
: expect
.any(CircularArray
)
1300 history
: expect
.any(CircularArray
)
1305 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1306 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1309 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThanOrEqual(0)
1310 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThanOrEqual(0)
1313 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1314 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1315 ).defaultWorkerWeight
1316 ).toBeGreaterThan(0)
1318 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1319 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1320 ).workerVirtualTaskRunTime
1321 ).toBeGreaterThanOrEqual(0)
1322 // We need to clean up the resources after our test
1323 await pool
.destroy()
1326 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1327 const pool
= new DynamicThreadPool(
1330 './tests/worker-files/thread/testWorker.js',
1331 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
1333 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1334 const promises
= new Set()
1335 const maxMultiplier
= 2
1336 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1337 promises
.add(pool
.execute())
1339 await Promise
.all(promises
)
1340 for (const workerNode
of pool
.workerNodes
) {
1341 expect(workerNode
.workerUsage
).toStrictEqual({
1343 executed
: expect
.any(Number
),
1349 aggregate
: expect
.any(Number
),
1350 average
: expect
.any(Number
),
1352 history
: expect
.any(CircularArray
)
1358 history
: expect
.any(CircularArray
)
1365 history
: expect
.any(CircularArray
)
1371 history
: expect
.any(CircularArray
)
1376 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
1377 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1380 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
1381 expect(workerNode
.workerUsage
.runTime
.average
).toBeGreaterThan(0)
1384 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1385 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1386 ).defaultWorkerWeight
1387 ).toBeGreaterThan(0)
1389 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1390 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1391 ).workerVirtualTaskRunTime
1392 ).toBeGreaterThanOrEqual(0)
1393 // We need to clean up the resources after our test
1394 await pool
.destroy()
1397 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
1398 const pool
= new DynamicThreadPool(
1401 './tests/worker-files/thread/testWorker.js',
1403 workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
,
1404 workerChoiceStrategyOptions
: {
1405 runTime
: { median
: true }
1409 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1410 const promises
= new Set()
1411 const maxMultiplier
= 2
1412 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1413 promises
.add(pool
.execute())
1415 await Promise
.all(promises
)
1416 for (const workerNode
of pool
.workerNodes
) {
1417 expect(workerNode
.workerUsage
).toStrictEqual({
1419 executed
: expect
.any(Number
),
1425 aggregate
: expect
.any(Number
),
1427 median
: expect
.any(Number
),
1428 history
: expect
.any(CircularArray
)
1434 history
: expect
.any(CircularArray
)
1441 history
: expect
.any(CircularArray
)
1447 history
: expect
.any(CircularArray
)
1452 expect(workerNode
.workerUsage
.tasks
.executed
).toBeGreaterThan(0)
1453 expect(workerNode
.workerUsage
.tasks
.executed
).toBeLessThanOrEqual(
1456 expect(workerNode
.workerUsage
.runTime
.aggregate
).toBeGreaterThan(0)
1457 expect(workerNode
.workerUsage
.runTime
.median
).toBeGreaterThan(0)
1460 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1461 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1462 ).defaultWorkerWeight
1463 ).toBeGreaterThan(0)
1465 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1466 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1467 ).workerVirtualTaskRunTime
1468 ).toBeGreaterThanOrEqual(0)
1469 // We need to clean up the resources after our test
1470 await pool
.destroy()
1473 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1474 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1475 let pool
= new FixedThreadPool(
1477 './tests/worker-files/thread/testWorker.js'
1480 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1481 workerChoiceStrategy
1482 ).currentWorkerNodeId
1485 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1486 workerChoiceStrategy
1487 ).defaultWorkerWeight
1490 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1491 workerChoiceStrategy
1492 ).workerVirtualTaskRunTime
1494 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1496 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1497 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1498 ).currentWorkerNodeId
1501 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1502 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1503 ).defaultWorkerWeight
1504 ).toBeGreaterThan(0)
1506 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1507 workerChoiceStrategy
1508 ).workerVirtualTaskRunTime
1510 await pool
.destroy()
1511 pool
= new DynamicThreadPool(
1514 './tests/worker-files/thread/testWorker.js'
1517 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1518 workerChoiceStrategy
1519 ).currentWorkerNodeId
1522 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1523 workerChoiceStrategy
1524 ).defaultWorkerWeight
1527 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1528 workerChoiceStrategy
1529 ).workerVirtualTaskRunTime
1531 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1533 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1534 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1535 ).currentWorkerNodeId
1538 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1539 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1540 ).defaultWorkerWeight
1541 ).toBeGreaterThan(0)
1543 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1544 workerChoiceStrategy
1545 ).workerVirtualTaskRunTime
1547 // We need to clean up the resources after our test
1548 await pool
.destroy()
1551 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1552 const workerChoiceStrategy
=
1553 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1554 let pool
= new FixedThreadPool(
1556 './tests/worker-files/thread/testWorker.js',
1557 { workerChoiceStrategy
}
1560 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1578 await pool
.destroy()
1579 pool
= new DynamicThreadPool(
1582 './tests/worker-files/thread/testWorker.js',
1583 { workerChoiceStrategy
}
1586 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1604 // We need to clean up the resources after our test
1605 await pool
.destroy()
1608 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1609 const pool
= new FixedThreadPool(
1611 './tests/worker-files/thread/testWorker.js',
1613 workerChoiceStrategy
:
1614 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1617 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1618 const promises
= new Set()
1619 const maxMultiplier
= 2
1620 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1621 promises
.add(pool
.execute())
1623 await Promise
.all(promises
)
1624 for (const workerNode
of pool
.workerNodes
) {
1625 expect(workerNode
.workerUsage
).toStrictEqual({
1627 executed
: maxMultiplier
,
1636 history
: expect
.any(CircularArray
)
1642 history
: expect
.any(CircularArray
)
1649 history
: expect
.any(CircularArray
)
1655 history
: expect
.any(CircularArray
)
1662 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1663 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1664 ).defaultWorkerWeight
1665 ).toBeGreaterThan(0)
1667 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1668 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1672 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1673 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1674 ).currentWorkerNodeId
1677 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1678 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1681 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1682 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1683 ).defaultWorkerWeight
1685 // We need to clean up the resources after our test
1686 await pool
.destroy()
1689 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1690 const pool
= new DynamicThreadPool(
1693 './tests/worker-files/thread/testWorker.js',
1695 workerChoiceStrategy
:
1696 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1699 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1700 const promises
= new Set()
1701 const maxMultiplier
= 2
1702 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1703 promises
.add(pool
.execute())
1705 await Promise
.all(promises
)
1706 for (const workerNode
of pool
.workerNodes
) {
1707 expect(workerNode
.workerUsage
).toStrictEqual({
1709 executed
: maxMultiplier
,
1718 history
: expect
.any(CircularArray
)
1724 history
: expect
.any(CircularArray
)
1731 history
: expect
.any(CircularArray
)
1737 history
: expect
.any(CircularArray
)
1744 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1745 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1746 ).defaultWorkerWeight
1747 ).toBeGreaterThan(0)
1749 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1750 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1754 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1755 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1756 ).currentWorkerNodeId
1759 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1760 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1763 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1764 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1765 ).defaultWorkerWeight
1767 // We need to clean up the resources after our test
1768 await pool
.destroy()
1771 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1772 const workerChoiceStrategy
=
1773 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1774 let pool
= new FixedThreadPool(
1776 './tests/worker-files/thread/testWorker.js'
1779 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1780 workerChoiceStrategy
1784 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1785 workerChoiceStrategy
1786 ).currentWorkerNodeId
1789 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1790 workerChoiceStrategy
1791 ).defaultWorkerWeight
1794 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1795 workerChoiceStrategy
1798 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1800 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1801 workerChoiceStrategy
1805 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1806 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1807 ).currentWorkerNodeId
1810 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1811 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1812 ).defaultWorkerWeight
1813 ).toBeGreaterThan(0)
1815 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1816 workerChoiceStrategy
1819 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1820 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1821 ).defaultWorkerWeight
1823 await pool
.destroy()
1824 pool
= new DynamicThreadPool(
1827 './tests/worker-files/thread/testWorker.js'
1830 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1831 workerChoiceStrategy
1835 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1836 workerChoiceStrategy
1837 ).currentWorkerNodeId
1840 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1841 workerChoiceStrategy
1842 ).defaultWorkerWeight
1845 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1846 workerChoiceStrategy
1849 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1851 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1852 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1853 ).currentWorkerNodeId
1856 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1857 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1858 ).defaultWorkerWeight
1859 ).toBeGreaterThan(0)
1861 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1862 workerChoiceStrategy
1865 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1866 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1867 ).defaultWorkerWeight
1869 // We need to clean up the resources after our test
1870 await pool
.destroy()
1873 it('Verify unknown strategy throw error', () => {
1876 new DynamicThreadPool(
1879 './tests/worker-files/thread/testWorker.js',
1880 { workerChoiceStrategy
: 'UNKNOWN_STRATEGY' }
1882 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")