1 const { expect
} = require('expect')
8 } = require('../../../lib')
9 const { CircularArray
} = require('../../../lib/circular-array')
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(
69 expect(pool
.opts
.workerChoiceStrategyOptions
).toStrictEqual({
71 runTime
: { median
: false },
72 waitTime
: { median
: false },
73 elu
: { median
: false }
75 expect(pool
.workerChoiceStrategyContext
.opts
).toStrictEqual({
77 runTime
: { median
: false },
78 waitTime
: { median
: false },
79 elu
: { median
: false }
83 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
84 const pool
= new DynamicClusterPool(
87 './tests/worker-files/cluster/testWorker.js'
89 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
, { retries
: 3 })
90 expect(pool
.opts
.workerChoiceStrategy
).toBe(workerChoiceStrategy
)
91 expect(pool
.workerChoiceStrategyContext
.workerChoiceStrategy
).toBe(
94 expect(pool
.opts
.workerChoiceStrategyOptions
).toStrictEqual({
96 runTime
: { median
: false },
97 waitTime
: { median
: false },
98 elu
: { median
: false }
100 expect(pool
.workerChoiceStrategyContext
.opts
).toStrictEqual({
102 runTime
: { median
: false },
103 waitTime
: { median
: false },
104 elu
: { median
: false }
110 it('Verify available strategies default internals at pool creation', async () => {
111 const pool
= new FixedThreadPool(
113 './tests/worker-files/thread/testWorker.js'
115 for (const workerChoiceStrategy
of Object
.values(WorkerChoiceStrategies
)) {
117 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
122 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
124 ).previousWorkerNodeKey
126 if (workerChoiceStrategy
=== WorkerChoiceStrategies
.FAIR_SHARE
) {
128 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
130 ).workersVirtualTaskEndTimestamp
131 ).toBeInstanceOf(Array
)
133 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
135 ).workersVirtualTaskEndTimestamp
.length
138 workerChoiceStrategy
=== WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
141 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
143 ).defaultWorkerWeight
146 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
148 ).workerVirtualTaskRunTime
151 workerChoiceStrategy
===
152 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
155 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
157 ).defaultWorkerWeight
160 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
162 ).workerVirtualTaskRunTime
165 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
170 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
175 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
179 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
181 ).defaultWorkerWeight
188 it('Verify ROUND_ROBIN strategy default policy', async () => {
189 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
190 let pool
= new FixedThreadPool(
192 './tests/worker-files/thread/testWorker.js',
193 { workerChoiceStrategy
}
195 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
196 dynamicWorkerUsage
: false,
197 dynamicWorkerReady
: true
200 pool
= new DynamicThreadPool(
203 './tests/worker-files/thread/testWorker.js',
204 { workerChoiceStrategy
}
206 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
207 dynamicWorkerUsage
: false,
208 dynamicWorkerReady
: true
210 // We need to clean up the resources after our test
214 it('Verify ROUND_ROBIN strategy default tasks statistics requirements', async () => {
215 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
216 let pool
= new FixedThreadPool(
218 './tests/worker-files/thread/testWorker.js',
219 { workerChoiceStrategy
}
222 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
241 pool
= new DynamicThreadPool(
244 './tests/worker-files/thread/testWorker.js',
245 { workerChoiceStrategy
}
248 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
266 // We need to clean up the resources after our test
270 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
271 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
272 const pool
= new FixedThreadPool(
274 './tests/worker-files/thread/testWorker.js',
275 { workerChoiceStrategy
}
277 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
278 const promises
= new Set()
279 const maxMultiplier
= 2
280 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
281 promises
.add(pool
.execute())
283 await Promise
.all(promises
)
284 for (const workerNode
of pool
.workerNodes
) {
285 expect(workerNode
.usage
).toStrictEqual({
287 executed
: maxMultiplier
,
295 history
: new CircularArray()
298 history
: new CircularArray()
302 history
: new CircularArray()
305 history
: new CircularArray()
311 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
312 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
316 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
317 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
318 ).previousWorkerNodeKey
319 ).toBe(pool
.workerNodes
.length
- 1)
320 // We need to clean up the resources after our test
324 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
325 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
326 const pool
= new DynamicThreadPool(
329 './tests/worker-files/thread/testWorker.js',
330 { workerChoiceStrategy
}
332 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
333 const promises
= new Set()
334 const maxMultiplier
= 2
335 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
336 promises
.add(pool
.execute())
338 await Promise
.all(promises
)
339 for (const workerNode
of pool
.workerNodes
) {
340 expect(workerNode
.usage
).toStrictEqual({
342 executed
: expect
.any(Number
),
350 history
: new CircularArray()
353 history
: new CircularArray()
357 history
: new CircularArray()
360 history
: new CircularArray()
364 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
365 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
370 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
371 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
375 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
376 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
377 ).previousWorkerNodeKey
378 ).toBe(pool
.workerNodes
.length
- 1)
379 // We need to clean up the resources after our test
383 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
384 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
385 let pool
= new FixedClusterPool(
387 './tests/worker-files/cluster/testWorker.js',
388 { workerChoiceStrategy
}
390 let results
= new Set()
391 for (let i
= 0; i
< max
; i
++) {
392 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.id
)
394 expect(results
.size
).toBe(max
)
396 pool
= new FixedThreadPool(
398 './tests/worker-files/thread/testWorker.js',
399 { workerChoiceStrategy
}
402 for (let i
= 0; i
< max
; i
++) {
403 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.threadId
)
405 expect(results
.size
).toBe(max
)
409 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
410 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
411 let pool
= new FixedThreadPool(
413 './tests/worker-files/thread/testWorker.js',
414 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
417 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
418 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
422 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
423 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
424 ).previousWorkerNodeKey
426 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
428 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
429 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
433 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
434 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
435 ).previousWorkerNodeKey
438 pool
= new DynamicThreadPool(
441 './tests/worker-files/thread/testWorker.js',
442 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
445 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
446 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
450 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
451 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
452 ).previousWorkerNodeKey
454 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
456 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
457 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
461 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
462 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
463 ).previousWorkerNodeKey
465 // We need to clean up the resources after our test
469 it('Verify LEAST_USED strategy default policy', async () => {
470 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
471 let pool
= new FixedThreadPool(
473 './tests/worker-files/thread/testWorker.js',
474 { workerChoiceStrategy
}
476 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
477 dynamicWorkerUsage
: false,
478 dynamicWorkerReady
: true
481 pool
= new DynamicThreadPool(
484 './tests/worker-files/thread/testWorker.js',
485 { workerChoiceStrategy
}
487 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
488 dynamicWorkerUsage
: false,
489 dynamicWorkerReady
: true
491 // We need to clean up the resources after our test
495 it('Verify LEAST_USED strategy default tasks statistics requirements', async () => {
496 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
497 let pool
= new FixedThreadPool(
499 './tests/worker-files/thread/testWorker.js',
500 { workerChoiceStrategy
}
503 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
522 pool
= new DynamicThreadPool(
525 './tests/worker-files/thread/testWorker.js',
526 { workerChoiceStrategy
}
529 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
547 // We need to clean up the resources after our test
551 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
552 const pool
= new FixedThreadPool(
554 './tests/worker-files/thread/testWorker.js',
555 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
557 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#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
.usage
).toStrictEqual({
567 executed
: expect
.any(Number
),
575 history
: new CircularArray()
578 history
: new CircularArray()
582 history
: new CircularArray()
585 history
: new CircularArray()
589 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
590 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
594 // We need to clean up the resources after our test
598 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
599 const pool
= new DynamicThreadPool(
602 './tests/worker-files/thread/testWorker.js',
603 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
605 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
606 const promises
= new Set()
607 const maxMultiplier
= 2
608 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
609 promises
.add(pool
.execute())
611 await Promise
.all(promises
)
612 for (const workerNode
of pool
.workerNodes
) {
613 expect(workerNode
.usage
).toStrictEqual({
615 executed
: expect
.any(Number
),
623 history
: new CircularArray()
626 history
: new CircularArray()
630 history
: new CircularArray()
633 history
: new CircularArray()
637 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
638 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
642 // We need to clean up the resources after our test
646 it('Verify LEAST_BUSY strategy default policy', async () => {
647 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
648 let pool
= new FixedThreadPool(
650 './tests/worker-files/thread/testWorker.js',
651 { workerChoiceStrategy
}
653 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
654 dynamicWorkerUsage
: false,
655 dynamicWorkerReady
: true
658 pool
= new DynamicThreadPool(
661 './tests/worker-files/thread/testWorker.js',
662 { workerChoiceStrategy
}
664 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
665 dynamicWorkerUsage
: false,
666 dynamicWorkerReady
: true
668 // We need to clean up the resources after our test
672 it('Verify LEAST_BUSY strategy default tasks statistics requirements', async () => {
673 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
674 let pool
= new FixedThreadPool(
676 './tests/worker-files/thread/testWorker.js',
677 { workerChoiceStrategy
}
680 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
699 pool
= new DynamicThreadPool(
702 './tests/worker-files/thread/testWorker.js',
703 { workerChoiceStrategy
}
706 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
724 // We need to clean up the resources after our test
728 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
729 const pool
= new FixedThreadPool(
731 './tests/worker-files/thread/testWorker.js',
732 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
734 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
735 const promises
= new Set()
736 const maxMultiplier
= 2
737 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
738 promises
.add(pool
.execute())
740 await Promise
.all(promises
)
741 for (const workerNode
of pool
.workerNodes
) {
742 expect(workerNode
.usage
).toStrictEqual({
744 executed
: expect
.any(Number
),
751 runTime
: expect
.objectContaining({
752 history
: expect
.any(CircularArray
)
754 waitTime
: expect
.objectContaining({
755 history
: expect
.any(CircularArray
)
759 history
: new CircularArray()
762 history
: new CircularArray()
766 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
767 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
770 if (workerNode
.usage
.runTime
.aggregate
== null) {
771 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
773 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
775 if (workerNode
.usage
.waitTime
.aggregate
== null) {
776 expect(workerNode
.usage
.waitTime
.aggregate
).toBeUndefined()
778 expect(workerNode
.usage
.waitTime
.aggregate
).toBeGreaterThan(0)
781 // We need to clean up the resources after our test
785 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
786 const pool
= new DynamicThreadPool(
789 './tests/worker-files/thread/testWorker.js',
790 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
792 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
793 const promises
= new Set()
794 const maxMultiplier
= 2
795 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
796 promises
.add(pool
.execute())
798 await Promise
.all(promises
)
799 for (const workerNode
of pool
.workerNodes
) {
800 expect(workerNode
.usage
).toStrictEqual({
802 executed
: expect
.any(Number
),
809 runTime
: expect
.objectContaining({
810 history
: expect
.any(CircularArray
)
812 waitTime
: expect
.objectContaining({
813 history
: expect
.any(CircularArray
)
817 history
: new CircularArray()
820 history
: new CircularArray()
824 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
825 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
828 if (workerNode
.usage
.runTime
.aggregate
== null) {
829 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
831 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
833 if (workerNode
.usage
.waitTime
.aggregate
== null) {
834 expect(workerNode
.usage
.waitTime
.aggregate
).toBeUndefined()
836 expect(workerNode
.usage
.waitTime
.aggregate
).toBeGreaterThan(0)
839 // We need to clean up the resources after our test
843 it('Verify LEAST_ELU strategy default policy', async () => {
844 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_ELU
845 let pool
= new FixedThreadPool(
847 './tests/worker-files/thread/testWorker.js',
848 { workerChoiceStrategy
}
850 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
851 dynamicWorkerUsage
: false,
852 dynamicWorkerReady
: true
855 pool
= new DynamicThreadPool(
858 './tests/worker-files/thread/testWorker.js',
859 { workerChoiceStrategy
}
861 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
862 dynamicWorkerUsage
: false,
863 dynamicWorkerReady
: true
865 // We need to clean up the resources after our test
869 it('Verify LEAST_ELU strategy default tasks statistics requirements', async () => {
870 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_ELU
871 let pool
= new FixedThreadPool(
873 './tests/worker-files/thread/testWorker.js',
874 { workerChoiceStrategy
}
877 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
896 pool
= new DynamicThreadPool(
899 './tests/worker-files/thread/testWorker.js',
900 { workerChoiceStrategy
}
903 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
921 // We need to clean up the resources after our test
925 it('Verify LEAST_ELU strategy can be run in a fixed pool', async () => {
926 const pool
= new FixedThreadPool(
928 './tests/worker-files/thread/testWorker.js',
929 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_ELU
}
931 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
932 const promises
= new Set()
933 const maxMultiplier
= 2
934 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
935 promises
.add(pool
.execute())
937 await Promise
.all(promises
)
938 for (const workerNode
of pool
.workerNodes
) {
939 expect(workerNode
.usage
).toStrictEqual({
941 executed
: expect
.any(Number
),
949 history
: new CircularArray()
952 history
: new CircularArray()
954 elu
: expect
.objectContaining({
955 idle
: expect
.objectContaining({
956 history
: expect
.any(CircularArray
)
958 active
: expect
.objectContaining({
959 history
: expect
.any(CircularArray
)
963 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
964 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
967 if (workerNode
.usage
.elu
.active
.aggregate
== null) {
968 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeUndefined()
970 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeGreaterThan(0)
972 if (workerNode
.usage
.elu
.idle
.aggregate
== null) {
973 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeUndefined()
975 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeGreaterThanOrEqual(0)
977 if (workerNode
.usage
.elu
.utilization
== null) {
978 expect(workerNode
.usage
.elu
.utilization
).toBeUndefined()
980 expect(workerNode
.usage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
981 expect(workerNode
.usage
.elu
.utilization
).toBeLessThanOrEqual(1)
984 // We need to clean up the resources after our test
988 it('Verify LEAST_ELU strategy can be run in a dynamic pool', async () => {
989 const pool
= new DynamicThreadPool(
992 './tests/worker-files/thread/testWorker.js',
993 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_ELU
}
995 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
996 const promises
= new Set()
997 const maxMultiplier
= 2
998 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
999 promises
.add(pool
.execute())
1001 await Promise
.all(promises
)
1002 for (const workerNode
of pool
.workerNodes
) {
1003 expect(workerNode
.usage
).toStrictEqual({
1005 executed
: expect
.any(Number
),
1013 history
: new CircularArray()
1016 history
: new CircularArray()
1018 elu
: expect
.objectContaining({
1019 idle
: expect
.objectContaining({
1020 history
: expect
.any(CircularArray
)
1022 active
: expect
.objectContaining({
1023 history
: expect
.any(CircularArray
)
1027 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1028 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1031 if (workerNode
.usage
.elu
.active
.aggregate
== null) {
1032 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeUndefined()
1034 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeGreaterThan(0)
1036 if (workerNode
.usage
.elu
.idle
.aggregate
== null) {
1037 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeUndefined()
1039 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeGreaterThanOrEqual(0)
1041 if (workerNode
.usage
.elu
.utilization
== null) {
1042 expect(workerNode
.usage
.elu
.utilization
).toBeUndefined()
1044 expect(workerNode
.usage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
1045 expect(workerNode
.usage
.elu
.utilization
).toBeLessThanOrEqual(1)
1048 // We need to clean up the resources after our test
1049 await pool
.destroy()
1052 it('Verify FAIR_SHARE strategy default policy', async () => {
1053 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
1054 let pool
= new FixedThreadPool(
1056 './tests/worker-files/thread/testWorker.js',
1057 { workerChoiceStrategy
}
1059 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1060 dynamicWorkerUsage
: false,
1061 dynamicWorkerReady
: true
1063 await pool
.destroy()
1064 pool
= new DynamicThreadPool(
1067 './tests/worker-files/thread/testWorker.js',
1068 { workerChoiceStrategy
}
1070 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1071 dynamicWorkerUsage
: false,
1072 dynamicWorkerReady
: true
1074 // We need to clean up the resources after our test
1075 await pool
.destroy()
1078 it('Verify FAIR_SHARE strategy default tasks statistics requirements', async () => {
1079 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
1080 let pool
= new FixedThreadPool(
1082 './tests/worker-files/thread/testWorker.js',
1083 { workerChoiceStrategy
}
1086 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1104 await pool
.destroy()
1105 pool
= new DynamicThreadPool(
1108 './tests/worker-files/thread/testWorker.js',
1109 { workerChoiceStrategy
}
1112 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1130 // We need to clean up the resources after our test
1131 await pool
.destroy()
1134 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
1135 const pool
= new FixedThreadPool(
1137 './tests/worker-files/thread/testWorker.js',
1138 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
1140 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1141 const promises
= new Set()
1142 const maxMultiplier
= 2
1143 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1144 promises
.add(pool
.execute())
1146 await Promise
.all(promises
)
1147 for (const workerNode
of pool
.workerNodes
) {
1148 expect(workerNode
.usage
).toStrictEqual({
1150 executed
: expect
.any(Number
),
1157 runTime
: expect
.objectContaining({
1158 history
: expect
.any(CircularArray
)
1161 history
: new CircularArray()
1163 elu
: expect
.objectContaining({
1164 idle
: expect
.objectContaining({
1165 history
: expect
.any(CircularArray
)
1167 active
: expect
.objectContaining({
1168 history
: expect
.any(CircularArray
)
1172 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1173 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1176 if (workerNode
.usage
.runTime
.aggregate
== null) {
1177 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1179 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1181 if (workerNode
.usage
.runTime
.average
== null) {
1182 expect(workerNode
.usage
.runTime
.average
).toBeUndefined()
1184 expect(workerNode
.usage
.runTime
.average
).toBeGreaterThan(0)
1186 if (workerNode
.usage
.elu
.active
.aggregate
== null) {
1187 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeUndefined()
1189 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeGreaterThan(0)
1191 if (workerNode
.usage
.elu
.idle
.aggregate
== null) {
1192 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeUndefined()
1194 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeGreaterThanOrEqual(0)
1196 if (workerNode
.usage
.elu
.utilization
== null) {
1197 expect(workerNode
.usage
.elu
.utilization
).toBeUndefined()
1199 expect(workerNode
.usage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
1200 expect(workerNode
.usage
.elu
.utilization
).toBeLessThanOrEqual(1)
1204 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1205 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1206 ).workersVirtualTaskEndTimestamp
.length
1207 ).toBe(pool
.workerNodes
.length
)
1208 // We need to clean up the resources after our test
1209 await pool
.destroy()
1212 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
1213 const pool
= new DynamicThreadPool(
1216 './tests/worker-files/thread/testWorker.js',
1217 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
1219 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1220 const promises
= new Set()
1221 const maxMultiplier
= 2
1222 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1223 promises
.add(pool
.execute())
1225 await Promise
.all(promises
)
1226 for (const workerNode
of pool
.workerNodes
) {
1227 expect(workerNode
.usage
).toStrictEqual({
1229 executed
: expect
.any(Number
),
1236 runTime
: expect
.objectContaining({
1237 history
: expect
.any(CircularArray
)
1240 history
: new CircularArray()
1242 elu
: expect
.objectContaining({
1243 idle
: expect
.objectContaining({
1244 history
: expect
.any(CircularArray
)
1246 active
: expect
.objectContaining({
1247 history
: expect
.any(CircularArray
)
1251 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1252 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1255 if (workerNode
.usage
.runTime
.aggregate
== null) {
1256 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1258 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1260 if (workerNode
.usage
.runTime
.average
== null) {
1261 expect(workerNode
.usage
.runTime
.average
).toBeUndefined()
1263 expect(workerNode
.usage
.runTime
.average
).toBeGreaterThan(0)
1265 if (workerNode
.usage
.elu
.active
.aggregate
== null) {
1266 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeUndefined()
1268 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeGreaterThan(0)
1270 if (workerNode
.usage
.elu
.idle
.aggregate
== null) {
1271 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeUndefined()
1273 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeGreaterThanOrEqual(0)
1275 if (workerNode
.usage
.elu
.utilization
== null) {
1276 expect(workerNode
.usage
.elu
.utilization
).toBeUndefined()
1278 expect(workerNode
.usage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
1279 expect(workerNode
.usage
.elu
.utilization
).toBeLessThanOrEqual(1)
1283 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1284 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1285 ).workersVirtualTaskEndTimestamp
.length
1286 ).toBe(pool
.workerNodes
.length
)
1287 // We need to clean up the resources after our test
1288 await pool
.destroy()
1291 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
1292 const pool
= new DynamicThreadPool(
1295 './tests/worker-files/thread/testWorker.js',
1297 workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
,
1298 workerChoiceStrategyOptions
: {
1299 runTime
: { median
: true }
1303 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1304 const promises
= new Set()
1305 const maxMultiplier
= 2
1306 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1307 promises
.add(pool
.execute())
1309 await Promise
.all(promises
)
1310 for (const workerNode
of pool
.workerNodes
) {
1311 expect(workerNode
.usage
).toStrictEqual({
1313 executed
: expect
.any(Number
),
1320 runTime
: expect
.objectContaining({
1321 history
: expect
.any(CircularArray
)
1324 history
: new CircularArray()
1326 elu
: expect
.objectContaining({
1327 idle
: expect
.objectContaining({
1328 history
: expect
.any(CircularArray
)
1330 active
: expect
.objectContaining({
1331 history
: expect
.any(CircularArray
)
1335 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1336 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1339 if (workerNode
.usage
.runTime
.aggregate
== null) {
1340 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1342 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1344 if (workerNode
.usage
.runTime
.median
== null) {
1345 expect(workerNode
.usage
.runTime
.median
).toBeUndefined()
1347 expect(workerNode
.usage
.runTime
.median
).toBeGreaterThan(0)
1349 if (workerNode
.usage
.elu
.active
.aggregate
== null) {
1350 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeUndefined()
1352 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeGreaterThan(0)
1354 if (workerNode
.usage
.elu
.idle
.aggregate
== null) {
1355 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeUndefined()
1357 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeGreaterThanOrEqual(0)
1359 if (workerNode
.usage
.elu
.utilization
== null) {
1360 expect(workerNode
.usage
.elu
.utilization
).toBeUndefined()
1362 expect(workerNode
.usage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
1363 expect(workerNode
.usage
.elu
.utilization
).toBeLessThanOrEqual(1)
1367 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1368 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1369 ).workersVirtualTaskEndTimestamp
.length
1370 ).toBe(pool
.workerNodes
.length
)
1371 // We need to clean up the resources after our test
1372 await pool
.destroy()
1375 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
1376 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
1377 let pool
= new FixedThreadPool(
1379 './tests/worker-files/thread/testWorker.js'
1382 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1383 workerChoiceStrategy
1384 ).workersVirtualTaskEndTimestamp
1385 ).toBeInstanceOf(Array
)
1387 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1388 workerChoiceStrategy
1389 ).workersVirtualTaskEndTimestamp
.length
1391 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1392 workerChoiceStrategy
1393 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
1395 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1396 workerChoiceStrategy
1397 ).workersVirtualTaskEndTimestamp
.length
1399 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1401 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1402 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1403 ).workersVirtualTaskEndTimestamp
1404 ).toBeInstanceOf(Array
)
1406 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1407 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1408 ).workersVirtualTaskEndTimestamp
.length
1410 await pool
.destroy()
1411 pool
= new DynamicThreadPool(
1414 './tests/worker-files/thread/testWorker.js'
1417 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1418 workerChoiceStrategy
1419 ).workersVirtualTaskEndTimestamp
1420 ).toBeInstanceOf(Array
)
1422 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1423 workerChoiceStrategy
1424 ).workersVirtualTaskEndTimestamp
.length
1426 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1427 workerChoiceStrategy
1428 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
1430 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1431 workerChoiceStrategy
1432 ).workersVirtualTaskEndTimestamp
.length
1434 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1436 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1437 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1438 ).workersVirtualTaskEndTimestamp
1439 ).toBeInstanceOf(Array
)
1441 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1442 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1443 ).workersVirtualTaskEndTimestamp
.length
1445 // We need to clean up the resources after our test
1446 await pool
.destroy()
1449 it('Verify WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1450 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1451 let pool
= new FixedThreadPool(
1453 './tests/worker-files/thread/testWorker.js',
1454 { workerChoiceStrategy
}
1456 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1457 dynamicWorkerUsage
: false,
1458 dynamicWorkerReady
: true
1460 await pool
.destroy()
1461 pool
= new DynamicThreadPool(
1464 './tests/worker-files/thread/testWorker.js',
1465 { workerChoiceStrategy
}
1467 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1468 dynamicWorkerUsage
: false,
1469 dynamicWorkerReady
: true
1471 // We need to clean up the resources after our test
1472 await pool
.destroy()
1475 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
1476 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1477 let pool
= new FixedThreadPool(
1479 './tests/worker-files/thread/testWorker.js',
1480 { workerChoiceStrategy
}
1483 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1501 await pool
.destroy()
1502 pool
= new DynamicThreadPool(
1505 './tests/worker-files/thread/testWorker.js',
1506 { workerChoiceStrategy
}
1509 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1527 // We need to clean up the resources after our test
1528 await pool
.destroy()
1531 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1532 const pool
= new FixedThreadPool(
1534 './tests/worker-files/thread/testWorker.js',
1535 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
1537 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1538 const promises
= new Set()
1539 const maxMultiplier
= 2
1540 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1541 promises
.add(pool
.execute())
1543 await Promise
.all(promises
)
1544 for (const workerNode
of pool
.workerNodes
) {
1545 expect(workerNode
.usage
).toStrictEqual({
1547 executed
: expect
.any(Number
),
1554 runTime
: expect
.objectContaining({
1555 history
: expect
.any(CircularArray
)
1558 history
: new CircularArray()
1562 history
: new CircularArray()
1565 history
: new CircularArray()
1569 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1570 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1573 if (workerNode
.usage
.runTime
.aggregate
== null) {
1574 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1576 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1578 if (workerNode
.usage
.runTime
.average
== null) {
1579 expect(workerNode
.usage
.runTime
.average
).toBeUndefined()
1581 expect(workerNode
.usage
.runTime
.average
).toBeGreaterThan(0)
1585 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1586 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1590 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1591 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1592 ).previousWorkerNodeKey
1595 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1596 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1597 ).defaultWorkerWeight
1598 ).toBeGreaterThan(0)
1600 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1601 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1602 ).workerVirtualTaskRunTime
1603 ).toBeGreaterThanOrEqual(0)
1604 // We need to clean up the resources after our test
1605 await pool
.destroy()
1608 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1609 const pool
= new DynamicThreadPool(
1612 './tests/worker-files/thread/testWorker.js',
1613 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
1615 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1616 const promises
= new Set()
1617 const maxMultiplier
= 2
1618 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1619 promises
.add(pool
.execute())
1621 await Promise
.all(promises
)
1622 for (const workerNode
of pool
.workerNodes
) {
1623 expect(workerNode
.usage
).toStrictEqual({
1625 executed
: expect
.any(Number
),
1632 runTime
: expect
.objectContaining({
1633 history
: expect
.any(CircularArray
)
1636 history
: new CircularArray()
1640 history
: new CircularArray()
1643 history
: new CircularArray()
1647 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1648 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1651 if (workerNode
.usage
.runTime
.aggregate
== null) {
1652 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1654 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1656 if (workerNode
.usage
.runTime
.average
== null) {
1657 expect(workerNode
.usage
.runTime
.average
).toBeUndefined()
1659 expect(workerNode
.usage
.runTime
.average
).toBeGreaterThan(0)
1663 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1664 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1668 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1669 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1670 ).previousWorkerNodeKey
1673 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1674 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1675 ).defaultWorkerWeight
1676 ).toBeGreaterThan(0)
1678 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1679 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1680 ).workerVirtualTaskRunTime
1681 ).toBeGreaterThanOrEqual(0)
1682 // We need to clean up the resources after our test
1683 await pool
.destroy()
1686 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
1687 const pool
= new DynamicThreadPool(
1690 './tests/worker-files/thread/testWorker.js',
1692 workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
,
1693 workerChoiceStrategyOptions
: {
1694 runTime
: { median
: true }
1698 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1699 const promises
= new Set()
1700 const maxMultiplier
= 2
1701 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1702 promises
.add(pool
.execute())
1704 await Promise
.all(promises
)
1705 for (const workerNode
of pool
.workerNodes
) {
1706 expect(workerNode
.usage
).toStrictEqual({
1708 executed
: expect
.any(Number
),
1715 runTime
: expect
.objectContaining({
1716 history
: expect
.any(CircularArray
)
1719 history
: new CircularArray()
1723 history
: new CircularArray()
1726 history
: new CircularArray()
1730 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1731 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1734 if (workerNode
.usage
.runTime
.aggregate
== null) {
1735 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1737 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1739 if (workerNode
.usage
.runTime
.median
== null) {
1740 expect(workerNode
.usage
.runTime
.median
).toBeUndefined()
1742 expect(workerNode
.usage
.runTime
.median
).toBeGreaterThan(0)
1746 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1747 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1751 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1752 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1753 ).previousWorkerNodeKey
1756 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1757 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1758 ).defaultWorkerWeight
1759 ).toBeGreaterThan(0)
1761 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1762 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1763 ).workerVirtualTaskRunTime
1764 ).toBeGreaterThanOrEqual(0)
1765 // We need to clean up the resources after our test
1766 await pool
.destroy()
1769 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1770 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1771 let pool
= new FixedThreadPool(
1773 './tests/worker-files/thread/testWorker.js'
1776 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1777 workerChoiceStrategy
1781 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1782 workerChoiceStrategy
1783 ).previousWorkerNodeKey
1786 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1787 workerChoiceStrategy
1788 ).defaultWorkerWeight
1791 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1792 workerChoiceStrategy
1793 ).workerVirtualTaskRunTime
1795 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1797 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1798 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1802 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1803 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1804 ).previousWorkerNodeKey
1807 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1808 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1809 ).defaultWorkerWeight
1810 ).toBeGreaterThan(0)
1812 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1813 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1814 ).workerVirtualTaskRunTime
1816 await pool
.destroy()
1817 pool
= new DynamicThreadPool(
1820 './tests/worker-files/thread/testWorker.js'
1823 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1824 workerChoiceStrategy
1828 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1829 workerChoiceStrategy
1830 ).previousWorkerNodeKey
1833 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1834 workerChoiceStrategy
1835 ).defaultWorkerWeight
1838 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1839 workerChoiceStrategy
1840 ).workerVirtualTaskRunTime
1842 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1844 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1845 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1849 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1850 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1851 ).previousWorkerNodeKey
1854 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1855 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1856 ).defaultWorkerWeight
1857 ).toBeGreaterThan(0)
1859 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1860 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1861 ).workerVirtualTaskRunTime
1863 // We need to clean up the resources after our test
1864 await pool
.destroy()
1867 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1868 const workerChoiceStrategy
=
1869 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1870 let pool
= new FixedThreadPool(
1872 './tests/worker-files/thread/testWorker.js',
1873 { workerChoiceStrategy
}
1875 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1876 dynamicWorkerUsage
: false,
1877 dynamicWorkerReady
: true
1879 await pool
.destroy()
1880 pool
= new DynamicThreadPool(
1883 './tests/worker-files/thread/testWorker.js',
1884 { workerChoiceStrategy
}
1886 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1887 dynamicWorkerUsage
: false,
1888 dynamicWorkerReady
: true
1890 // We need to clean up the resources after our test
1891 await pool
.destroy()
1894 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
1895 const workerChoiceStrategy
=
1896 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1897 let pool
= new FixedThreadPool(
1899 './tests/worker-files/thread/testWorker.js',
1900 { workerChoiceStrategy
}
1903 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1921 await pool
.destroy()
1922 pool
= new DynamicThreadPool(
1925 './tests/worker-files/thread/testWorker.js',
1926 { workerChoiceStrategy
}
1929 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1947 // We need to clean up the resources after our test
1948 await pool
.destroy()
1951 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1952 const pool
= new FixedThreadPool(
1954 './tests/worker-files/thread/testWorker.js',
1956 workerChoiceStrategy
:
1957 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1960 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1961 const promises
= new Set()
1962 const maxMultiplier
= 2
1963 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1964 promises
.add(pool
.execute())
1966 await Promise
.all(promises
)
1967 for (const workerNode
of pool
.workerNodes
) {
1968 expect(workerNode
.usage
).toStrictEqual({
1970 executed
: expect
.any(Number
),
1977 runTime
: expect
.objectContaining({
1978 history
: expect
.any(CircularArray
)
1981 history
: new CircularArray()
1985 history
: new CircularArray()
1988 history
: new CircularArray()
1992 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1993 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1998 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1999 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2000 ).defaultWorkerWeight
2001 ).toBeGreaterThan(0)
2003 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2004 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2008 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2009 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2013 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2014 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2018 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2019 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2020 ).previousWorkerNodeKey
2021 ).toEqual(expect
.any(Number
))
2023 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2024 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2027 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2028 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2029 ).defaultWorkerWeight
2031 // We need to clean up the resources after our test
2032 await pool
.destroy()
2035 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
2036 const pool
= new DynamicThreadPool(
2039 './tests/worker-files/thread/testWorker.js',
2041 workerChoiceStrategy
:
2042 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2045 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
2046 const promises
= new Set()
2047 const maxMultiplier
= 2
2048 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
2049 promises
.add(pool
.execute())
2051 await Promise
.all(promises
)
2052 for (const workerNode
of pool
.workerNodes
) {
2053 expect(workerNode
.usage
).toStrictEqual({
2055 executed
: expect
.any(Number
),
2062 runTime
: expect
.objectContaining({
2063 history
: expect
.any(CircularArray
)
2066 history
: new CircularArray()
2070 history
: new CircularArray()
2073 history
: new CircularArray()
2077 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
2078 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
2083 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2084 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2085 ).defaultWorkerWeight
2086 ).toBeGreaterThan(0)
2088 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2089 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2093 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2094 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2098 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2099 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2103 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2104 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2105 ).previousWorkerNodeKey
2106 ).toEqual(expect
.any(Number
))
2108 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2109 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2112 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2113 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2114 ).defaultWorkerWeight
2116 // We need to clean up the resources after our test
2117 await pool
.destroy()
2120 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
2121 const workerChoiceStrategy
=
2122 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2123 let pool
= new FixedThreadPool(
2125 './tests/worker-files/thread/testWorker.js'
2128 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2129 workerChoiceStrategy
2133 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2134 workerChoiceStrategy
2138 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2139 workerChoiceStrategy
2143 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2144 workerChoiceStrategy
2145 ).previousWorkerNodeKey
2148 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2149 workerChoiceStrategy
2150 ).defaultWorkerWeight
2153 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2154 workerChoiceStrategy
2157 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
2159 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2160 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2164 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2165 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2169 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2170 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2174 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2175 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2176 ).previousWorkerNodeKey
2179 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2180 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2181 ).defaultWorkerWeight
2182 ).toBeGreaterThan(0)
2184 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2185 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2188 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2189 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2190 ).defaultWorkerWeight
2192 await pool
.destroy()
2193 pool
= new DynamicThreadPool(
2196 './tests/worker-files/thread/testWorker.js'
2199 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2200 workerChoiceStrategy
2204 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2205 workerChoiceStrategy
2209 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2210 workerChoiceStrategy
2214 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2215 workerChoiceStrategy
2216 ).previousWorkerNodeKey
2219 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2220 workerChoiceStrategy
2221 ).defaultWorkerWeight
2224 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2225 workerChoiceStrategy
2228 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
2230 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2231 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2235 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2236 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2240 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2241 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2245 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2246 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2247 ).previousWorkerNodeKey
2250 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2251 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2252 ).defaultWorkerWeight
2253 ).toBeGreaterThan(0)
2255 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2256 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2259 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2260 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2261 ).defaultWorkerWeight
2263 // We need to clean up the resources after our test
2264 await pool
.destroy()
2267 it('Verify unknown strategy throw error', () => {
2270 new DynamicThreadPool(
2273 './tests/worker-files/thread/testWorker.js',
2274 { workerChoiceStrategy
: 'UNKNOWN_STRATEGY' }
2276 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")