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
133 workerChoiceStrategy
=== WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
136 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
138 ).defaultWorkerWeight
141 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
143 ).workerVirtualTaskRunTime
146 workerChoiceStrategy
===
147 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
150 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
152 ).defaultWorkerWeight
155 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
157 ).workerVirtualTaskRunTime
160 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
165 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
170 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
174 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
176 ).defaultWorkerWeight
183 it('Verify ROUND_ROBIN strategy default policy', async () => {
184 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
185 let pool
= new FixedThreadPool(
187 './tests/worker-files/thread/testWorker.js',
188 { workerChoiceStrategy
}
190 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
191 dynamicWorkerUsage
: false,
192 dynamicWorkerReady
: true
195 pool
= new DynamicThreadPool(
198 './tests/worker-files/thread/testWorker.js',
199 { workerChoiceStrategy
}
201 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
202 dynamicWorkerUsage
: false,
203 dynamicWorkerReady
: true
205 // We need to clean up the resources after our test
209 it('Verify ROUND_ROBIN strategy default tasks statistics requirements', async () => {
210 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
211 let pool
= new FixedThreadPool(
213 './tests/worker-files/thread/testWorker.js',
214 { workerChoiceStrategy
}
217 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
236 pool
= new DynamicThreadPool(
239 './tests/worker-files/thread/testWorker.js',
240 { workerChoiceStrategy
}
243 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
261 // We need to clean up the resources after our test
265 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
266 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
267 const pool
= new FixedThreadPool(
269 './tests/worker-files/thread/testWorker.js',
270 { workerChoiceStrategy
}
272 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
273 const promises
= new Set()
274 const maxMultiplier
= 2
275 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
276 promises
.add(pool
.execute())
278 await Promise
.all(promises
)
279 for (const workerNode
of pool
.workerNodes
) {
280 expect(workerNode
.usage
).toStrictEqual({
282 executed
: maxMultiplier
,
290 history
: new CircularArray()
293 history
: new CircularArray()
297 history
: new CircularArray()
300 history
: new CircularArray()
306 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
307 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
311 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
312 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
313 ).previousWorkerNodeKey
314 ).toBe(pool
.workerNodes
.length
- 1)
315 // We need to clean up the resources after our test
319 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
320 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
321 const pool
= new DynamicThreadPool(
324 './tests/worker-files/thread/testWorker.js',
325 { workerChoiceStrategy
}
327 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
328 const promises
= new Set()
329 const maxMultiplier
= 2
330 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
331 promises
.add(pool
.execute())
333 await Promise
.all(promises
)
334 for (const workerNode
of pool
.workerNodes
) {
335 expect(workerNode
.usage
).toStrictEqual({
337 executed
: expect
.any(Number
),
345 history
: new CircularArray()
348 history
: new CircularArray()
352 history
: new CircularArray()
355 history
: new CircularArray()
359 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
360 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
365 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
366 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
370 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
371 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
372 ).previousWorkerNodeKey
373 ).toBe(pool
.workerNodes
.length
- 1)
374 // We need to clean up the resources after our test
378 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
379 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
380 let pool
= new FixedClusterPool(
382 './tests/worker-files/cluster/testWorker.js',
383 { workerChoiceStrategy
}
385 let results
= new Set()
386 for (let i
= 0; i
< max
; i
++) {
387 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.id
)
389 expect(results
.size
).toBe(max
)
391 pool
= new FixedThreadPool(
393 './tests/worker-files/thread/testWorker.js',
394 { workerChoiceStrategy
}
397 for (let i
= 0; i
< max
; i
++) {
398 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.threadId
)
400 expect(results
.size
).toBe(max
)
404 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
405 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
406 let pool
= new FixedThreadPool(
408 './tests/worker-files/thread/testWorker.js',
409 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
412 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
413 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
417 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
418 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
419 ).previousWorkerNodeKey
421 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
423 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
424 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
428 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
429 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
430 ).previousWorkerNodeKey
433 pool
= new DynamicThreadPool(
436 './tests/worker-files/thread/testWorker.js',
437 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
440 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
441 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
445 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
446 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
447 ).previousWorkerNodeKey
449 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
451 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
452 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
456 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
457 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
458 ).previousWorkerNodeKey
460 // We need to clean up the resources after our test
464 it('Verify LEAST_USED strategy default policy', async () => {
465 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
466 let pool
= new FixedThreadPool(
468 './tests/worker-files/thread/testWorker.js',
469 { workerChoiceStrategy
}
471 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
472 dynamicWorkerUsage
: false,
473 dynamicWorkerReady
: true
476 pool
= new DynamicThreadPool(
479 './tests/worker-files/thread/testWorker.js',
480 { workerChoiceStrategy
}
482 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
483 dynamicWorkerUsage
: false,
484 dynamicWorkerReady
: true
486 // We need to clean up the resources after our test
490 it('Verify LEAST_USED strategy default tasks statistics requirements', async () => {
491 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
492 let pool
= new FixedThreadPool(
494 './tests/worker-files/thread/testWorker.js',
495 { workerChoiceStrategy
}
498 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
517 pool
= new DynamicThreadPool(
520 './tests/worker-files/thread/testWorker.js',
521 { workerChoiceStrategy
}
524 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
542 // We need to clean up the resources after our test
546 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
547 const pool
= new FixedThreadPool(
549 './tests/worker-files/thread/testWorker.js',
550 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
552 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
553 const promises
= new Set()
554 const maxMultiplier
= 2
555 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
556 promises
.add(pool
.execute())
558 await Promise
.all(promises
)
559 for (const workerNode
of pool
.workerNodes
) {
560 expect(workerNode
.usage
).toStrictEqual({
562 executed
: expect
.any(Number
),
570 history
: new CircularArray()
573 history
: new CircularArray()
577 history
: new CircularArray()
580 history
: new CircularArray()
584 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
585 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
590 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
591 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
593 ).toEqual(expect
.any(Number
))
595 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
596 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
597 ).previousWorkerNodeKey
598 ).toEqual(expect
.any(Number
))
599 // We need to clean up the resources after our test
603 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
604 const pool
= new DynamicThreadPool(
607 './tests/worker-files/thread/testWorker.js',
608 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
610 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
611 const promises
= new Set()
612 const maxMultiplier
= 2
613 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
614 promises
.add(pool
.execute())
616 await Promise
.all(promises
)
617 for (const workerNode
of pool
.workerNodes
) {
618 expect(workerNode
.usage
).toStrictEqual({
620 executed
: expect
.any(Number
),
628 history
: new CircularArray()
631 history
: new CircularArray()
635 history
: new CircularArray()
638 history
: new CircularArray()
642 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
643 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
648 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
649 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
651 ).toEqual(expect
.any(Number
))
653 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
654 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
655 ).previousWorkerNodeKey
656 ).toEqual(expect
.any(Number
))
657 // We need to clean up the resources after our test
661 it('Verify LEAST_BUSY strategy default policy', async () => {
662 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
663 let pool
= new FixedThreadPool(
665 './tests/worker-files/thread/testWorker.js',
666 { workerChoiceStrategy
}
668 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
669 dynamicWorkerUsage
: false,
670 dynamicWorkerReady
: true
673 pool
= new DynamicThreadPool(
676 './tests/worker-files/thread/testWorker.js',
677 { workerChoiceStrategy
}
679 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
680 dynamicWorkerUsage
: false,
681 dynamicWorkerReady
: true
683 // We need to clean up the resources after our test
687 it('Verify LEAST_BUSY strategy default tasks statistics requirements', async () => {
688 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
689 let pool
= new FixedThreadPool(
691 './tests/worker-files/thread/testWorker.js',
692 { workerChoiceStrategy
}
695 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
714 pool
= new DynamicThreadPool(
717 './tests/worker-files/thread/testWorker.js',
718 { workerChoiceStrategy
}
721 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
739 // We need to clean up the resources after our test
743 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
744 const pool
= new FixedThreadPool(
746 './tests/worker-files/thread/testWorker.js',
747 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
749 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
750 const promises
= new Set()
751 const maxMultiplier
= 2
752 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
753 promises
.add(pool
.execute())
755 await Promise
.all(promises
)
756 for (const workerNode
of pool
.workerNodes
) {
757 expect(workerNode
.usage
).toStrictEqual({
759 executed
: expect
.any(Number
),
766 runTime
: expect
.objectContaining({
767 history
: expect
.any(CircularArray
)
769 waitTime
: expect
.objectContaining({
770 history
: expect
.any(CircularArray
)
774 history
: new CircularArray()
777 history
: new CircularArray()
781 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
782 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
785 if (workerNode
.usage
.runTime
.aggregate
== null) {
786 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
788 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
790 if (workerNode
.usage
.waitTime
.aggregate
== null) {
791 expect(workerNode
.usage
.waitTime
.aggregate
).toBeUndefined()
793 expect(workerNode
.usage
.waitTime
.aggregate
).toBeGreaterThan(0)
797 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
798 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
800 ).toEqual(expect
.any(Number
))
802 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
803 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
804 ).previousWorkerNodeKey
805 ).toEqual(expect
.any(Number
))
806 // We need to clean up the resources after our test
810 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
811 const pool
= new DynamicThreadPool(
814 './tests/worker-files/thread/testWorker.js',
815 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
817 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
818 const promises
= new Set()
819 const maxMultiplier
= 2
820 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
821 promises
.add(pool
.execute())
823 await Promise
.all(promises
)
824 for (const workerNode
of pool
.workerNodes
) {
825 expect(workerNode
.usage
).toStrictEqual({
827 executed
: expect
.any(Number
),
834 runTime
: expect
.objectContaining({
835 history
: expect
.any(CircularArray
)
837 waitTime
: expect
.objectContaining({
838 history
: expect
.any(CircularArray
)
842 history
: new CircularArray()
845 history
: new CircularArray()
849 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
850 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
853 if (workerNode
.usage
.runTime
.aggregate
== null) {
854 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
856 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
858 if (workerNode
.usage
.waitTime
.aggregate
== null) {
859 expect(workerNode
.usage
.waitTime
.aggregate
).toBeUndefined()
861 expect(workerNode
.usage
.waitTime
.aggregate
).toBeGreaterThan(0)
865 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
866 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
868 ).toEqual(expect
.any(Number
))
870 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
871 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
872 ).previousWorkerNodeKey
873 ).toEqual(expect
.any(Number
))
874 // We need to clean up the resources after our test
878 it('Verify LEAST_ELU strategy default policy', async () => {
879 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_ELU
880 let pool
= new FixedThreadPool(
882 './tests/worker-files/thread/testWorker.js',
883 { workerChoiceStrategy
}
885 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
886 dynamicWorkerUsage
: false,
887 dynamicWorkerReady
: true
890 pool
= new DynamicThreadPool(
893 './tests/worker-files/thread/testWorker.js',
894 { workerChoiceStrategy
}
896 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
897 dynamicWorkerUsage
: false,
898 dynamicWorkerReady
: true
900 // We need to clean up the resources after our test
904 it('Verify LEAST_ELU strategy default tasks statistics requirements', async () => {
905 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_ELU
906 let pool
= new FixedThreadPool(
908 './tests/worker-files/thread/testWorker.js',
909 { workerChoiceStrategy
}
912 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
931 pool
= new DynamicThreadPool(
934 './tests/worker-files/thread/testWorker.js',
935 { workerChoiceStrategy
}
938 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
956 // We need to clean up the resources after our test
960 it('Verify LEAST_ELU strategy can be run in a fixed pool', async () => {
961 const pool
= new FixedThreadPool(
963 './tests/worker-files/thread/testWorker.js',
964 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_ELU
}
966 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
967 const promises
= new Set()
968 const maxMultiplier
= 2
969 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
970 promises
.add(pool
.execute())
972 await Promise
.all(promises
)
973 for (const workerNode
of pool
.workerNodes
) {
974 expect(workerNode
.usage
).toStrictEqual({
976 executed
: expect
.any(Number
),
984 history
: new CircularArray()
987 history
: new CircularArray()
989 elu
: expect
.objectContaining({
990 idle
: expect
.objectContaining({
991 history
: expect
.any(CircularArray
)
993 active
: expect
.objectContaining({
994 history
: expect
.any(CircularArray
)
998 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
999 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1002 if (workerNode
.usage
.elu
.active
.aggregate
== null) {
1003 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeUndefined()
1005 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeGreaterThan(0)
1007 if (workerNode
.usage
.elu
.idle
.aggregate
== null) {
1008 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeUndefined()
1010 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeGreaterThanOrEqual(0)
1012 if (workerNode
.usage
.elu
.utilization
== null) {
1013 expect(workerNode
.usage
.elu
.utilization
).toBeUndefined()
1015 expect(workerNode
.usage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
1016 expect(workerNode
.usage
.elu
.utilization
).toBeLessThanOrEqual(1)
1020 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1021 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1023 ).toEqual(expect
.any(Number
))
1025 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1026 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1027 ).previousWorkerNodeKey
1028 ).toEqual(expect
.any(Number
))
1029 // We need to clean up the resources after our test
1030 await pool
.destroy()
1033 it('Verify LEAST_ELU strategy can be run in a dynamic pool', async () => {
1034 const pool
= new DynamicThreadPool(
1037 './tests/worker-files/thread/testWorker.js',
1038 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_ELU
}
1040 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
1041 const promises
= new Set()
1042 const maxMultiplier
= 2
1043 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1044 promises
.add(pool
.execute())
1046 await Promise
.all(promises
)
1047 for (const workerNode
of pool
.workerNodes
) {
1048 expect(workerNode
.usage
).toStrictEqual({
1050 executed
: expect
.any(Number
),
1058 history
: new CircularArray()
1061 history
: new CircularArray()
1063 elu
: expect
.objectContaining({
1064 idle
: expect
.objectContaining({
1065 history
: expect
.any(CircularArray
)
1067 active
: expect
.objectContaining({
1068 history
: expect
.any(CircularArray
)
1072 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1073 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1076 if (workerNode
.usage
.elu
.active
.aggregate
== null) {
1077 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeUndefined()
1079 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeGreaterThan(0)
1081 if (workerNode
.usage
.elu
.idle
.aggregate
== null) {
1082 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeUndefined()
1084 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeGreaterThanOrEqual(0)
1086 if (workerNode
.usage
.elu
.utilization
== null) {
1087 expect(workerNode
.usage
.elu
.utilization
).toBeUndefined()
1089 expect(workerNode
.usage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
1090 expect(workerNode
.usage
.elu
.utilization
).toBeLessThanOrEqual(1)
1094 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1095 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1097 ).toEqual(expect
.any(Number
))
1099 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1100 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1101 ).previousWorkerNodeKey
1102 ).toEqual(expect
.any(Number
))
1103 // We need to clean up the resources after our test
1104 await pool
.destroy()
1107 it('Verify FAIR_SHARE strategy default policy', async () => {
1108 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
1109 let pool
= new FixedThreadPool(
1111 './tests/worker-files/thread/testWorker.js',
1112 { workerChoiceStrategy
}
1114 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1115 dynamicWorkerUsage
: false,
1116 dynamicWorkerReady
: true
1118 await pool
.destroy()
1119 pool
= new DynamicThreadPool(
1122 './tests/worker-files/thread/testWorker.js',
1123 { workerChoiceStrategy
}
1125 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1126 dynamicWorkerUsage
: false,
1127 dynamicWorkerReady
: true
1129 // We need to clean up the resources after our test
1130 await pool
.destroy()
1133 it('Verify FAIR_SHARE strategy default tasks statistics requirements', async () => {
1134 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
1135 let pool
= new FixedThreadPool(
1137 './tests/worker-files/thread/testWorker.js',
1138 { workerChoiceStrategy
}
1141 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1159 await pool
.destroy()
1160 pool
= new DynamicThreadPool(
1163 './tests/worker-files/thread/testWorker.js',
1164 { workerChoiceStrategy
}
1167 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1185 // We need to clean up the resources after our test
1186 await pool
.destroy()
1189 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
1190 const pool
= new FixedThreadPool(
1192 './tests/worker-files/thread/testWorker.js',
1193 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
1195 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1196 const promises
= new Set()
1197 const maxMultiplier
= 2
1198 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1199 promises
.add(pool
.execute())
1201 await Promise
.all(promises
)
1202 for (const workerNode
of pool
.workerNodes
) {
1203 expect(workerNode
.usage
).toStrictEqual({
1205 executed
: expect
.any(Number
),
1212 runTime
: expect
.objectContaining({
1213 history
: expect
.any(CircularArray
)
1216 history
: new CircularArray()
1218 elu
: expect
.objectContaining({
1219 idle
: expect
.objectContaining({
1220 history
: expect
.any(CircularArray
)
1222 active
: expect
.objectContaining({
1223 history
: expect
.any(CircularArray
)
1227 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1228 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1231 if (workerNode
.usage
.runTime
.aggregate
== null) {
1232 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1234 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1236 if (workerNode
.usage
.runTime
.average
== null) {
1237 expect(workerNode
.usage
.runTime
.average
).toBeUndefined()
1239 expect(workerNode
.usage
.runTime
.average
).toBeGreaterThan(0)
1241 if (workerNode
.usage
.elu
.active
.aggregate
== null) {
1242 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeUndefined()
1244 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeGreaterThan(0)
1246 if (workerNode
.usage
.elu
.idle
.aggregate
== null) {
1247 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeUndefined()
1249 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeGreaterThanOrEqual(0)
1251 if (workerNode
.usage
.elu
.utilization
== null) {
1252 expect(workerNode
.usage
.elu
.utilization
).toBeUndefined()
1254 expect(workerNode
.usage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
1255 expect(workerNode
.usage
.elu
.utilization
).toBeLessThanOrEqual(1)
1259 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1260 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1262 ).toEqual(expect
.any(Number
))
1264 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1265 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1266 ).previousWorkerNodeKey
1267 ).toEqual(expect
.any(Number
))
1269 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1270 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1271 ).workersVirtualTaskEndTimestamp
.length
1272 ).toBe(pool
.workerNodes
.length
)
1273 // We need to clean up the resources after our test
1274 await pool
.destroy()
1277 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
1278 const pool
= new DynamicThreadPool(
1281 './tests/worker-files/thread/testWorker.js',
1282 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
1284 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1285 const promises
= new Set()
1286 const maxMultiplier
= 2
1287 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1288 promises
.add(pool
.execute())
1290 await Promise
.all(promises
)
1291 for (const workerNode
of pool
.workerNodes
) {
1292 expect(workerNode
.usage
).toStrictEqual({
1294 executed
: expect
.any(Number
),
1301 runTime
: expect
.objectContaining({
1302 history
: expect
.any(CircularArray
)
1305 history
: new CircularArray()
1307 elu
: expect
.objectContaining({
1308 idle
: expect
.objectContaining({
1309 history
: expect
.any(CircularArray
)
1311 active
: expect
.objectContaining({
1312 history
: expect
.any(CircularArray
)
1316 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1317 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1320 if (workerNode
.usage
.runTime
.aggregate
== null) {
1321 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1323 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1325 if (workerNode
.usage
.runTime
.average
== null) {
1326 expect(workerNode
.usage
.runTime
.average
).toBeUndefined()
1328 expect(workerNode
.usage
.runTime
.average
).toBeGreaterThan(0)
1330 if (workerNode
.usage
.elu
.active
.aggregate
== null) {
1331 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeUndefined()
1333 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeGreaterThan(0)
1335 if (workerNode
.usage
.elu
.idle
.aggregate
== null) {
1336 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeUndefined()
1338 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeGreaterThanOrEqual(0)
1340 if (workerNode
.usage
.elu
.utilization
== null) {
1341 expect(workerNode
.usage
.elu
.utilization
).toBeUndefined()
1343 expect(workerNode
.usage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
1344 expect(workerNode
.usage
.elu
.utilization
).toBeLessThanOrEqual(1)
1348 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1349 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1351 ).toEqual(expect
.any(Number
))
1353 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1354 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1355 ).previousWorkerNodeKey
1356 ).toEqual(expect
.any(Number
))
1358 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1359 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1360 ).workersVirtualTaskEndTimestamp
.length
1361 ).toBe(pool
.workerNodes
.length
)
1362 // We need to clean up the resources after our test
1363 await pool
.destroy()
1366 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
1367 const pool
= new DynamicThreadPool(
1370 './tests/worker-files/thread/testWorker.js',
1372 workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
,
1373 workerChoiceStrategyOptions
: {
1374 runTime
: { median
: true }
1378 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1379 const promises
= new Set()
1380 const maxMultiplier
= 2
1381 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1382 promises
.add(pool
.execute())
1384 await Promise
.all(promises
)
1385 for (const workerNode
of pool
.workerNodes
) {
1386 expect(workerNode
.usage
).toStrictEqual({
1388 executed
: expect
.any(Number
),
1395 runTime
: expect
.objectContaining({
1396 history
: expect
.any(CircularArray
)
1399 history
: new CircularArray()
1401 elu
: expect
.objectContaining({
1402 idle
: expect
.objectContaining({
1403 history
: expect
.any(CircularArray
)
1405 active
: expect
.objectContaining({
1406 history
: expect
.any(CircularArray
)
1410 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1411 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1414 if (workerNode
.usage
.runTime
.aggregate
== null) {
1415 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1417 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1419 if (workerNode
.usage
.runTime
.median
== null) {
1420 expect(workerNode
.usage
.runTime
.median
).toBeUndefined()
1422 expect(workerNode
.usage
.runTime
.median
).toBeGreaterThan(0)
1424 if (workerNode
.usage
.elu
.active
.aggregate
== null) {
1425 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeUndefined()
1427 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeGreaterThan(0)
1429 if (workerNode
.usage
.elu
.idle
.aggregate
== null) {
1430 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeUndefined()
1432 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeGreaterThanOrEqual(0)
1434 if (workerNode
.usage
.elu
.utilization
== null) {
1435 expect(workerNode
.usage
.elu
.utilization
).toBeUndefined()
1437 expect(workerNode
.usage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
1438 expect(workerNode
.usage
.elu
.utilization
).toBeLessThanOrEqual(1)
1442 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1443 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1445 ).toEqual(expect
.any(Number
))
1447 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1448 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1449 ).previousWorkerNodeKey
1450 ).toEqual(expect
.any(Number
))
1452 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1453 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1454 ).workersVirtualTaskEndTimestamp
.length
1455 ).toBe(pool
.workerNodes
.length
)
1456 // We need to clean up the resources after our test
1457 await pool
.destroy()
1460 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
1461 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
1462 let pool
= new FixedThreadPool(
1464 './tests/worker-files/thread/testWorker.js'
1467 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1468 workerChoiceStrategy
1469 ).workersVirtualTaskEndTimestamp
1470 ).toBeInstanceOf(Array
)
1472 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1473 workerChoiceStrategy
1474 ).workersVirtualTaskEndTimestamp
.length
1476 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1477 workerChoiceStrategy
1478 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
1480 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1481 workerChoiceStrategy
1482 ).workersVirtualTaskEndTimestamp
.length
1484 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1486 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1487 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1488 ).workersVirtualTaskEndTimestamp
1489 ).toBeInstanceOf(Array
)
1491 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1492 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1493 ).workersVirtualTaskEndTimestamp
.length
1495 await pool
.destroy()
1496 pool
= new DynamicThreadPool(
1499 './tests/worker-files/thread/testWorker.js'
1502 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1503 workerChoiceStrategy
1504 ).workersVirtualTaskEndTimestamp
1505 ).toBeInstanceOf(Array
)
1507 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1508 workerChoiceStrategy
1509 ).workersVirtualTaskEndTimestamp
.length
1511 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1512 workerChoiceStrategy
1513 ).workersVirtualTaskEndTimestamp
[0] = performance
.now()
1515 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1516 workerChoiceStrategy
1517 ).workersVirtualTaskEndTimestamp
.length
1519 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1521 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1522 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1523 ).workersVirtualTaskEndTimestamp
1524 ).toBeInstanceOf(Array
)
1526 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1527 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1528 ).workersVirtualTaskEndTimestamp
.length
1530 // We need to clean up the resources after our test
1531 await pool
.destroy()
1534 it('Verify WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1535 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1536 let pool
= new FixedThreadPool(
1538 './tests/worker-files/thread/testWorker.js',
1539 { workerChoiceStrategy
}
1541 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1542 dynamicWorkerUsage
: false,
1543 dynamicWorkerReady
: true
1545 await pool
.destroy()
1546 pool
= new DynamicThreadPool(
1549 './tests/worker-files/thread/testWorker.js',
1550 { workerChoiceStrategy
}
1552 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1553 dynamicWorkerUsage
: false,
1554 dynamicWorkerReady
: true
1556 // We need to clean up the resources after our test
1557 await pool
.destroy()
1560 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
1561 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1562 let pool
= new FixedThreadPool(
1564 './tests/worker-files/thread/testWorker.js',
1565 { workerChoiceStrategy
}
1568 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1586 await pool
.destroy()
1587 pool
= new DynamicThreadPool(
1590 './tests/worker-files/thread/testWorker.js',
1591 { workerChoiceStrategy
}
1594 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1612 // We need to clean up the resources after our test
1613 await pool
.destroy()
1616 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1617 const pool
= new FixedThreadPool(
1619 './tests/worker-files/thread/testWorker.js',
1620 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
1622 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1623 const promises
= new Set()
1624 const maxMultiplier
= 2
1625 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1626 promises
.add(pool
.execute())
1628 await Promise
.all(promises
)
1629 for (const workerNode
of pool
.workerNodes
) {
1630 expect(workerNode
.usage
).toStrictEqual({
1632 executed
: expect
.any(Number
),
1639 runTime
: expect
.objectContaining({
1640 history
: expect
.any(CircularArray
)
1643 history
: new CircularArray()
1647 history
: new CircularArray()
1650 history
: new CircularArray()
1654 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1655 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1658 if (workerNode
.usage
.runTime
.aggregate
== null) {
1659 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1661 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1663 if (workerNode
.usage
.runTime
.average
== null) {
1664 expect(workerNode
.usage
.runTime
.average
).toBeUndefined()
1666 expect(workerNode
.usage
.runTime
.average
).toBeGreaterThan(0)
1670 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1671 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1675 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1676 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1677 ).previousWorkerNodeKey
1680 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1681 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1682 ).defaultWorkerWeight
1683 ).toBeGreaterThan(0)
1685 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1686 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1687 ).workerVirtualTaskRunTime
1688 ).toBeGreaterThanOrEqual(0)
1689 // We need to clean up the resources after our test
1690 await pool
.destroy()
1693 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1694 const pool
= new DynamicThreadPool(
1697 './tests/worker-files/thread/testWorker.js',
1698 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
1700 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1701 const promises
= new Set()
1702 const maxMultiplier
= 2
1703 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1704 promises
.add(pool
.execute())
1706 await Promise
.all(promises
)
1707 for (const workerNode
of pool
.workerNodes
) {
1708 expect(workerNode
.usage
).toStrictEqual({
1710 executed
: expect
.any(Number
),
1717 runTime
: expect
.objectContaining({
1718 history
: expect
.any(CircularArray
)
1721 history
: new CircularArray()
1725 history
: new CircularArray()
1728 history
: new CircularArray()
1732 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1733 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1736 if (workerNode
.usage
.runTime
.aggregate
== null) {
1737 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1739 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1741 if (workerNode
.usage
.runTime
.average
== null) {
1742 expect(workerNode
.usage
.runTime
.average
).toBeUndefined()
1744 expect(workerNode
.usage
.runTime
.average
).toBeGreaterThan(0)
1748 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1749 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1753 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1754 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1755 ).previousWorkerNodeKey
1758 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1759 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1760 ).defaultWorkerWeight
1761 ).toBeGreaterThan(0)
1763 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1764 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1765 ).workerVirtualTaskRunTime
1766 ).toBeGreaterThanOrEqual(0)
1767 // We need to clean up the resources after our test
1768 await pool
.destroy()
1771 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
1772 const pool
= new DynamicThreadPool(
1775 './tests/worker-files/thread/testWorker.js',
1777 workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
,
1778 workerChoiceStrategyOptions
: {
1779 runTime
: { median
: true }
1783 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1784 const promises
= new Set()
1785 const maxMultiplier
= 2
1786 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1787 promises
.add(pool
.execute())
1789 await Promise
.all(promises
)
1790 for (const workerNode
of pool
.workerNodes
) {
1791 expect(workerNode
.usage
).toStrictEqual({
1793 executed
: expect
.any(Number
),
1800 runTime
: expect
.objectContaining({
1801 history
: expect
.any(CircularArray
)
1804 history
: new CircularArray()
1808 history
: new CircularArray()
1811 history
: new CircularArray()
1815 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1816 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1819 if (workerNode
.usage
.runTime
.aggregate
== null) {
1820 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1822 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1824 if (workerNode
.usage
.runTime
.median
== null) {
1825 expect(workerNode
.usage
.runTime
.median
).toBeUndefined()
1827 expect(workerNode
.usage
.runTime
.median
).toBeGreaterThan(0)
1831 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1832 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1836 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1837 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1838 ).previousWorkerNodeKey
1841 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1842 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1843 ).defaultWorkerWeight
1844 ).toBeGreaterThan(0)
1846 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1847 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1848 ).workerVirtualTaskRunTime
1849 ).toBeGreaterThanOrEqual(0)
1850 // We need to clean up the resources after our test
1851 await pool
.destroy()
1854 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1855 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1856 let pool
= new FixedThreadPool(
1858 './tests/worker-files/thread/testWorker.js'
1861 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1862 workerChoiceStrategy
1866 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1867 workerChoiceStrategy
1868 ).previousWorkerNodeKey
1871 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1872 workerChoiceStrategy
1873 ).defaultWorkerWeight
1876 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1877 workerChoiceStrategy
1878 ).workerVirtualTaskRunTime
1880 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1882 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1883 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1887 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1888 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1889 ).previousWorkerNodeKey
1892 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1893 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1894 ).defaultWorkerWeight
1895 ).toBeGreaterThan(0)
1897 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1898 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1899 ).workerVirtualTaskRunTime
1901 await pool
.destroy()
1902 pool
= new DynamicThreadPool(
1905 './tests/worker-files/thread/testWorker.js'
1908 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1909 workerChoiceStrategy
1913 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1914 workerChoiceStrategy
1915 ).previousWorkerNodeKey
1918 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1919 workerChoiceStrategy
1920 ).defaultWorkerWeight
1923 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1924 workerChoiceStrategy
1925 ).workerVirtualTaskRunTime
1927 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1929 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1930 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1934 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1935 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1936 ).previousWorkerNodeKey
1939 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1940 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1941 ).defaultWorkerWeight
1942 ).toBeGreaterThan(0)
1944 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1945 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1946 ).workerVirtualTaskRunTime
1948 // We need to clean up the resources after our test
1949 await pool
.destroy()
1952 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1953 const workerChoiceStrategy
=
1954 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1955 let pool
= new FixedThreadPool(
1957 './tests/worker-files/thread/testWorker.js',
1958 { workerChoiceStrategy
}
1960 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1961 dynamicWorkerUsage
: false,
1962 dynamicWorkerReady
: true
1964 await pool
.destroy()
1965 pool
= new DynamicThreadPool(
1968 './tests/worker-files/thread/testWorker.js',
1969 { workerChoiceStrategy
}
1971 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1972 dynamicWorkerUsage
: false,
1973 dynamicWorkerReady
: true
1975 // We need to clean up the resources after our test
1976 await pool
.destroy()
1979 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
1980 const workerChoiceStrategy
=
1981 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1982 let pool
= new FixedThreadPool(
1984 './tests/worker-files/thread/testWorker.js',
1985 { workerChoiceStrategy
}
1988 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
2006 await pool
.destroy()
2007 pool
= new DynamicThreadPool(
2010 './tests/worker-files/thread/testWorker.js',
2011 { workerChoiceStrategy
}
2014 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
2032 // We need to clean up the resources after our test
2033 await pool
.destroy()
2036 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
2037 const pool
= new FixedThreadPool(
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 can be run in a dynamic pool', async () => {
2121 const pool
= new DynamicThreadPool(
2124 './tests/worker-files/thread/testWorker.js',
2126 workerChoiceStrategy
:
2127 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2130 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
2131 const promises
= new Set()
2132 const maxMultiplier
= 2
2133 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
2134 promises
.add(pool
.execute())
2136 await Promise
.all(promises
)
2137 for (const workerNode
of pool
.workerNodes
) {
2138 expect(workerNode
.usage
).toStrictEqual({
2140 executed
: expect
.any(Number
),
2147 runTime
: expect
.objectContaining({
2148 history
: expect
.any(CircularArray
)
2151 history
: new CircularArray()
2155 history
: new CircularArray()
2158 history
: new CircularArray()
2162 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
2163 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
2168 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2169 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2170 ).defaultWorkerWeight
2171 ).toBeGreaterThan(0)
2173 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2174 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2178 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2179 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2183 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2184 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2188 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2189 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2190 ).previousWorkerNodeKey
2191 ).toEqual(expect
.any(Number
))
2193 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2194 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2197 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2198 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2199 ).defaultWorkerWeight
2201 // We need to clean up the resources after our test
2202 await pool
.destroy()
2205 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
2206 const workerChoiceStrategy
=
2207 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2208 let pool
= new FixedThreadPool(
2210 './tests/worker-files/thread/testWorker.js'
2213 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2214 workerChoiceStrategy
2218 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2219 workerChoiceStrategy
2223 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2224 workerChoiceStrategy
2228 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2229 workerChoiceStrategy
2230 ).previousWorkerNodeKey
2233 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2234 workerChoiceStrategy
2235 ).defaultWorkerWeight
2238 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2239 workerChoiceStrategy
2242 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
2244 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2245 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2249 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2250 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2254 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2255 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2259 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2260 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2261 ).previousWorkerNodeKey
2264 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2265 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2266 ).defaultWorkerWeight
2267 ).toBeGreaterThan(0)
2269 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2270 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2273 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2274 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2275 ).defaultWorkerWeight
2277 await pool
.destroy()
2278 pool
= new DynamicThreadPool(
2281 './tests/worker-files/thread/testWorker.js'
2284 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2285 workerChoiceStrategy
2289 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2290 workerChoiceStrategy
2294 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2295 workerChoiceStrategy
2299 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2300 workerChoiceStrategy
2301 ).previousWorkerNodeKey
2304 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2305 workerChoiceStrategy
2306 ).defaultWorkerWeight
2309 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2310 workerChoiceStrategy
2313 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
2315 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2316 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2320 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2321 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2325 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2326 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2330 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2331 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2332 ).previousWorkerNodeKey
2335 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2336 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2337 ).defaultWorkerWeight
2338 ).toBeGreaterThan(0)
2340 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2341 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2344 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2345 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2346 ).defaultWorkerWeight
2348 // We need to clean up the resources after our test
2349 await pool
.destroy()
2352 it('Verify unknown strategy throw error', () => {
2355 new DynamicThreadPool(
2358 './tests/worker-files/thread/testWorker.js',
2359 { workerChoiceStrategy
: 'UNKNOWN_STRATEGY' }
2361 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")