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
127 workerChoiceStrategy
=== WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
130 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
132 ).defaultWorkerWeight
135 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
137 ).workerNodeVirtualTaskRunTime
140 workerChoiceStrategy
===
141 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
144 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
146 ).defaultWorkerWeight
149 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
151 ).workerNodeVirtualTaskRunTime
154 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
159 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
164 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
168 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
170 ).defaultWorkerWeight
177 it('Verify ROUND_ROBIN strategy default policy', async () => {
178 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
179 let pool
= new FixedThreadPool(
181 './tests/worker-files/thread/testWorker.js',
182 { workerChoiceStrategy
}
184 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
185 dynamicWorkerUsage
: false,
186 dynamicWorkerReady
: true
189 pool
= new DynamicThreadPool(
192 './tests/worker-files/thread/testWorker.js',
193 { workerChoiceStrategy
}
195 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
196 dynamicWorkerUsage
: false,
197 dynamicWorkerReady
: true
199 // We need to clean up the resources after our test
203 it('Verify ROUND_ROBIN strategy default tasks statistics requirements', async () => {
204 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
205 let pool
= new FixedThreadPool(
207 './tests/worker-files/thread/testWorker.js',
208 { workerChoiceStrategy
}
211 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
230 pool
= new DynamicThreadPool(
233 './tests/worker-files/thread/testWorker.js',
234 { workerChoiceStrategy
}
237 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
255 // We need to clean up the resources after our test
259 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
260 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
261 const pool
= new FixedThreadPool(
263 './tests/worker-files/thread/testWorker.js',
264 { workerChoiceStrategy
}
266 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
267 const promises
= new Set()
268 const maxMultiplier
= 2
269 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
270 promises
.add(pool
.execute())
272 await Promise
.all(promises
)
273 for (const workerNode
of pool
.workerNodes
) {
274 expect(workerNode
.usage
).toStrictEqual({
276 executed
: maxMultiplier
,
284 history
: new CircularArray()
287 history
: new CircularArray()
291 history
: new CircularArray()
294 history
: new CircularArray()
300 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
301 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
305 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
306 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
307 ).previousWorkerNodeKey
308 ).toBe(pool
.workerNodes
.length
- 1)
309 // We need to clean up the resources after our test
313 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
314 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
315 const pool
= new DynamicThreadPool(
318 './tests/worker-files/thread/testWorker.js',
319 { workerChoiceStrategy
}
321 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
322 const promises
= new Set()
323 const maxMultiplier
= 2
324 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
325 promises
.add(pool
.execute())
327 await Promise
.all(promises
)
328 for (const workerNode
of pool
.workerNodes
) {
329 expect(workerNode
.usage
).toStrictEqual({
331 executed
: expect
.any(Number
),
339 history
: new CircularArray()
342 history
: new CircularArray()
346 history
: new CircularArray()
349 history
: new CircularArray()
353 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
354 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
359 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
360 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
364 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
365 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
366 ).previousWorkerNodeKey
367 ).toBe(pool
.workerNodes
.length
- 1)
368 // We need to clean up the resources after our test
372 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
373 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
374 let pool
= new FixedClusterPool(
376 './tests/worker-files/cluster/testWorker.js',
377 { workerChoiceStrategy
}
379 let results
= new Set()
380 for (let i
= 0; i
< max
; i
++) {
381 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.id
)
383 expect(results
.size
).toBe(max
)
385 pool
= new FixedThreadPool(
387 './tests/worker-files/thread/testWorker.js',
388 { workerChoiceStrategy
}
391 for (let i
= 0; i
< max
; i
++) {
392 results
.add(pool
.workerNodes
[pool
.chooseWorkerNode()].worker
.threadId
)
394 expect(results
.size
).toBe(max
)
398 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
399 const workerChoiceStrategy
= WorkerChoiceStrategies
.ROUND_ROBIN
400 let pool
= new FixedThreadPool(
402 './tests/worker-files/thread/testWorker.js',
403 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
406 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
407 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
411 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
412 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
413 ).previousWorkerNodeKey
415 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
417 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
418 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
422 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
423 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
424 ).previousWorkerNodeKey
427 pool
= new DynamicThreadPool(
430 './tests/worker-files/thread/testWorker.js',
431 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
434 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
435 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
439 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
440 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
441 ).previousWorkerNodeKey
443 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
445 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
446 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
450 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
451 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
452 ).previousWorkerNodeKey
454 // We need to clean up the resources after our test
458 it('Verify LEAST_USED strategy default policy', async () => {
459 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
460 let pool
= new FixedThreadPool(
462 './tests/worker-files/thread/testWorker.js',
463 { workerChoiceStrategy
}
465 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
466 dynamicWorkerUsage
: false,
467 dynamicWorkerReady
: true
470 pool
= new DynamicThreadPool(
473 './tests/worker-files/thread/testWorker.js',
474 { workerChoiceStrategy
}
476 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
477 dynamicWorkerUsage
: false,
478 dynamicWorkerReady
: true
480 // We need to clean up the resources after our test
484 it('Verify LEAST_USED strategy default tasks statistics requirements', async () => {
485 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_USED
486 let pool
= new FixedThreadPool(
488 './tests/worker-files/thread/testWorker.js',
489 { workerChoiceStrategy
}
492 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
511 pool
= new DynamicThreadPool(
514 './tests/worker-files/thread/testWorker.js',
515 { workerChoiceStrategy
}
518 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
536 // We need to clean up the resources after our test
540 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
541 const pool
= new FixedThreadPool(
543 './tests/worker-files/thread/testWorker.js',
544 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
546 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
547 const promises
= new Set()
548 const maxMultiplier
= 2
549 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
550 promises
.add(pool
.execute())
552 await Promise
.all(promises
)
553 for (const workerNode
of pool
.workerNodes
) {
554 expect(workerNode
.usage
).toStrictEqual({
556 executed
: expect
.any(Number
),
564 history
: new CircularArray()
567 history
: new CircularArray()
571 history
: new CircularArray()
574 history
: new CircularArray()
578 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
579 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
584 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
585 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
587 ).toEqual(expect
.any(Number
))
589 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
590 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
591 ).previousWorkerNodeKey
592 ).toEqual(expect
.any(Number
))
593 // We need to clean up the resources after our test
597 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
598 const pool
= new DynamicThreadPool(
601 './tests/worker-files/thread/testWorker.js',
602 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
}
604 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
605 const promises
= new Set()
606 const maxMultiplier
= 2
607 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
608 promises
.add(pool
.execute())
610 await Promise
.all(promises
)
611 for (const workerNode
of pool
.workerNodes
) {
612 expect(workerNode
.usage
).toStrictEqual({
614 executed
: expect
.any(Number
),
622 history
: new CircularArray()
625 history
: new CircularArray()
629 history
: new CircularArray()
632 history
: new CircularArray()
636 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
637 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
642 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
643 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
645 ).toEqual(expect
.any(Number
))
647 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
648 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
649 ).previousWorkerNodeKey
650 ).toEqual(expect
.any(Number
))
651 // We need to clean up the resources after our test
655 it('Verify LEAST_BUSY strategy default policy', async () => {
656 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
657 let pool
= new FixedThreadPool(
659 './tests/worker-files/thread/testWorker.js',
660 { workerChoiceStrategy
}
662 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
663 dynamicWorkerUsage
: false,
664 dynamicWorkerReady
: true
667 pool
= new DynamicThreadPool(
670 './tests/worker-files/thread/testWorker.js',
671 { workerChoiceStrategy
}
673 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
674 dynamicWorkerUsage
: false,
675 dynamicWorkerReady
: true
677 // We need to clean up the resources after our test
681 it('Verify LEAST_BUSY strategy default tasks statistics requirements', async () => {
682 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_BUSY
683 let pool
= new FixedThreadPool(
685 './tests/worker-files/thread/testWorker.js',
686 { workerChoiceStrategy
}
689 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
708 pool
= new DynamicThreadPool(
711 './tests/worker-files/thread/testWorker.js',
712 { workerChoiceStrategy
}
715 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
733 // We need to clean up the resources after our test
737 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
738 const pool
= new FixedThreadPool(
740 './tests/worker-files/thread/testWorker.js',
741 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
743 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
744 const promises
= new Set()
745 const maxMultiplier
= 2
746 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
747 promises
.add(pool
.execute())
749 await Promise
.all(promises
)
750 for (const workerNode
of pool
.workerNodes
) {
751 expect(workerNode
.usage
).toStrictEqual({
753 executed
: expect
.any(Number
),
760 runTime
: expect
.objectContaining({
761 history
: expect
.any(CircularArray
)
763 waitTime
: expect
.objectContaining({
764 history
: expect
.any(CircularArray
)
768 history
: new CircularArray()
771 history
: new CircularArray()
775 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
776 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
779 if (workerNode
.usage
.runTime
.aggregate
== null) {
780 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
782 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
784 if (workerNode
.usage
.waitTime
.aggregate
== null) {
785 expect(workerNode
.usage
.waitTime
.aggregate
).toBeUndefined()
787 expect(workerNode
.usage
.waitTime
.aggregate
).toBeGreaterThan(0)
791 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
792 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
794 ).toEqual(expect
.any(Number
))
796 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
797 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
798 ).previousWorkerNodeKey
799 ).toEqual(expect
.any(Number
))
800 // We need to clean up the resources after our test
804 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
805 const pool
= new DynamicThreadPool(
808 './tests/worker-files/thread/testWorker.js',
809 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_BUSY
}
811 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
812 const promises
= new Set()
813 const maxMultiplier
= 2
814 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
815 promises
.add(pool
.execute())
817 await Promise
.all(promises
)
818 for (const workerNode
of pool
.workerNodes
) {
819 expect(workerNode
.usage
).toStrictEqual({
821 executed
: expect
.any(Number
),
828 runTime
: expect
.objectContaining({
829 history
: expect
.any(CircularArray
)
831 waitTime
: expect
.objectContaining({
832 history
: expect
.any(CircularArray
)
836 history
: new CircularArray()
839 history
: new CircularArray()
843 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
844 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
847 if (workerNode
.usage
.runTime
.aggregate
== null) {
848 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
850 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
852 if (workerNode
.usage
.waitTime
.aggregate
== null) {
853 expect(workerNode
.usage
.waitTime
.aggregate
).toBeUndefined()
855 expect(workerNode
.usage
.waitTime
.aggregate
).toBeGreaterThan(0)
859 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
860 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
862 ).toEqual(expect
.any(Number
))
864 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
865 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
866 ).previousWorkerNodeKey
867 ).toEqual(expect
.any(Number
))
868 // We need to clean up the resources after our test
872 it('Verify LEAST_ELU strategy default policy', async () => {
873 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_ELU
874 let pool
= new FixedThreadPool(
876 './tests/worker-files/thread/testWorker.js',
877 { workerChoiceStrategy
}
879 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
880 dynamicWorkerUsage
: false,
881 dynamicWorkerReady
: true
884 pool
= new DynamicThreadPool(
887 './tests/worker-files/thread/testWorker.js',
888 { workerChoiceStrategy
}
890 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
891 dynamicWorkerUsage
: false,
892 dynamicWorkerReady
: true
894 // We need to clean up the resources after our test
898 it('Verify LEAST_ELU strategy default tasks statistics requirements', async () => {
899 const workerChoiceStrategy
= WorkerChoiceStrategies
.LEAST_ELU
900 let pool
= new FixedThreadPool(
902 './tests/worker-files/thread/testWorker.js',
903 { workerChoiceStrategy
}
906 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
925 pool
= new DynamicThreadPool(
928 './tests/worker-files/thread/testWorker.js',
929 { workerChoiceStrategy
}
932 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
950 // We need to clean up the resources after our test
954 it('Verify LEAST_ELU strategy can be run in a fixed pool', async () => {
955 const pool
= new FixedThreadPool(
957 './tests/worker-files/thread/testWorker.js',
958 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_ELU
}
960 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
961 const promises
= new Set()
962 const maxMultiplier
= 2
963 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
964 promises
.add(pool
.execute())
966 await Promise
.all(promises
)
967 for (const workerNode
of pool
.workerNodes
) {
968 expect(workerNode
.usage
).toStrictEqual({
970 executed
: expect
.any(Number
),
978 history
: new CircularArray()
981 history
: new CircularArray()
983 elu
: expect
.objectContaining({
984 idle
: expect
.objectContaining({
985 history
: expect
.any(CircularArray
)
987 active
: expect
.objectContaining({
988 history
: expect
.any(CircularArray
)
992 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
993 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
996 if (workerNode
.usage
.elu
.active
.aggregate
== null) {
997 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeUndefined()
999 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeGreaterThan(0)
1001 if (workerNode
.usage
.elu
.idle
.aggregate
== null) {
1002 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeUndefined()
1004 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeGreaterThanOrEqual(0)
1006 if (workerNode
.usage
.elu
.utilization
== null) {
1007 expect(workerNode
.usage
.elu
.utilization
).toBeUndefined()
1009 expect(workerNode
.usage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
1010 expect(workerNode
.usage
.elu
.utilization
).toBeLessThanOrEqual(1)
1014 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1015 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1017 ).toEqual(expect
.any(Number
))
1019 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1020 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1021 ).previousWorkerNodeKey
1022 ).toEqual(expect
.any(Number
))
1023 // We need to clean up the resources after our test
1024 await pool
.destroy()
1027 it('Verify LEAST_ELU strategy can be run in a dynamic pool', async () => {
1028 const pool
= new DynamicThreadPool(
1031 './tests/worker-files/thread/testWorker.js',
1032 { workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_ELU
}
1034 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
1035 const promises
= new Set()
1036 const maxMultiplier
= 2
1037 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1038 promises
.add(pool
.execute())
1040 await Promise
.all(promises
)
1041 for (const workerNode
of pool
.workerNodes
) {
1042 expect(workerNode
.usage
).toStrictEqual({
1044 executed
: expect
.any(Number
),
1052 history
: new CircularArray()
1055 history
: new CircularArray()
1057 elu
: expect
.objectContaining({
1058 idle
: expect
.objectContaining({
1059 history
: expect
.any(CircularArray
)
1061 active
: expect
.objectContaining({
1062 history
: expect
.any(CircularArray
)
1066 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1067 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1070 if (workerNode
.usage
.elu
.active
.aggregate
== null) {
1071 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeUndefined()
1073 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeGreaterThan(0)
1075 if (workerNode
.usage
.elu
.idle
.aggregate
== null) {
1076 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeUndefined()
1078 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeGreaterThanOrEqual(0)
1080 if (workerNode
.usage
.elu
.utilization
== null) {
1081 expect(workerNode
.usage
.elu
.utilization
).toBeUndefined()
1083 expect(workerNode
.usage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
1084 expect(workerNode
.usage
.elu
.utilization
).toBeLessThanOrEqual(1)
1088 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1089 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1091 ).toEqual(expect
.any(Number
))
1093 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1094 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1095 ).previousWorkerNodeKey
1096 ).toEqual(expect
.any(Number
))
1097 // We need to clean up the resources after our test
1098 await pool
.destroy()
1101 it('Verify FAIR_SHARE strategy default policy', async () => {
1102 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
1103 let pool
= new FixedThreadPool(
1105 './tests/worker-files/thread/testWorker.js',
1106 { workerChoiceStrategy
}
1108 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1109 dynamicWorkerUsage
: false,
1110 dynamicWorkerReady
: true
1112 await pool
.destroy()
1113 pool
= new DynamicThreadPool(
1116 './tests/worker-files/thread/testWorker.js',
1117 { workerChoiceStrategy
}
1119 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1120 dynamicWorkerUsage
: false,
1121 dynamicWorkerReady
: true
1123 // We need to clean up the resources after our test
1124 await pool
.destroy()
1127 it('Verify FAIR_SHARE strategy default tasks statistics requirements', async () => {
1128 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
1129 let pool
= new FixedThreadPool(
1131 './tests/worker-files/thread/testWorker.js',
1132 { workerChoiceStrategy
}
1135 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1153 await pool
.destroy()
1154 pool
= new DynamicThreadPool(
1157 './tests/worker-files/thread/testWorker.js',
1158 { workerChoiceStrategy
}
1161 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1179 // We need to clean up the resources after our test
1180 await pool
.destroy()
1183 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
1184 const pool
= new FixedThreadPool(
1186 './tests/worker-files/thread/testWorker.js',
1187 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
1189 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1190 const promises
= new Set()
1191 const maxMultiplier
= 2
1192 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1193 promises
.add(pool
.execute())
1195 await Promise
.all(promises
)
1196 for (const workerNode
of pool
.workerNodes
) {
1197 expect(workerNode
.usage
).toStrictEqual({
1199 executed
: expect
.any(Number
),
1206 runTime
: expect
.objectContaining({
1207 history
: expect
.any(CircularArray
)
1210 history
: new CircularArray()
1212 elu
: expect
.objectContaining({
1213 idle
: expect
.objectContaining({
1214 history
: expect
.any(CircularArray
)
1216 active
: expect
.objectContaining({
1217 history
: expect
.any(CircularArray
)
1221 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1222 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1225 if (workerNode
.usage
.runTime
.aggregate
== null) {
1226 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1228 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1230 if (workerNode
.usage
.runTime
.average
== null) {
1231 expect(workerNode
.usage
.runTime
.average
).toBeUndefined()
1233 expect(workerNode
.usage
.runTime
.average
).toBeGreaterThan(0)
1235 if (workerNode
.usage
.elu
.active
.aggregate
== null) {
1236 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeUndefined()
1238 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeGreaterThan(0)
1240 if (workerNode
.usage
.elu
.idle
.aggregate
== null) {
1241 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeUndefined()
1243 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeGreaterThanOrEqual(0)
1245 if (workerNode
.usage
.elu
.utilization
== null) {
1246 expect(workerNode
.usage
.elu
.utilization
).toBeUndefined()
1248 expect(workerNode
.usage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
1249 expect(workerNode
.usage
.elu
.utilization
).toBeLessThanOrEqual(1)
1251 expect(workerNode
.strategyData
.virtualTaskEndTimestamp
).toBeGreaterThan(0)
1254 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1255 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1257 ).toEqual(expect
.any(Number
))
1259 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1260 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1261 ).previousWorkerNodeKey
1262 ).toEqual(expect
.any(Number
))
1263 // We need to clean up the resources after our test
1264 await pool
.destroy()
1267 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
1268 const pool
= new DynamicThreadPool(
1271 './tests/worker-files/thread/testWorker.js',
1272 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
1274 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1275 const promises
= new Set()
1276 const maxMultiplier
= 2
1277 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1278 promises
.add(pool
.execute())
1280 await Promise
.all(promises
)
1281 for (const workerNode
of pool
.workerNodes
) {
1282 expect(workerNode
.usage
).toStrictEqual({
1284 executed
: expect
.any(Number
),
1291 runTime
: expect
.objectContaining({
1292 history
: expect
.any(CircularArray
)
1295 history
: new CircularArray()
1297 elu
: expect
.objectContaining({
1298 idle
: expect
.objectContaining({
1299 history
: expect
.any(CircularArray
)
1301 active
: expect
.objectContaining({
1302 history
: expect
.any(CircularArray
)
1306 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1307 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1310 if (workerNode
.usage
.runTime
.aggregate
== null) {
1311 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1313 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1315 if (workerNode
.usage
.runTime
.average
== null) {
1316 expect(workerNode
.usage
.runTime
.average
).toBeUndefined()
1318 expect(workerNode
.usage
.runTime
.average
).toBeGreaterThan(0)
1320 if (workerNode
.usage
.elu
.active
.aggregate
== null) {
1321 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeUndefined()
1323 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeGreaterThan(0)
1325 if (workerNode
.usage
.elu
.idle
.aggregate
== null) {
1326 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeUndefined()
1328 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeGreaterThanOrEqual(0)
1330 if (workerNode
.usage
.elu
.utilization
== null) {
1331 expect(workerNode
.usage
.elu
.utilization
).toBeUndefined()
1333 expect(workerNode
.usage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
1334 expect(workerNode
.usage
.elu
.utilization
).toBeLessThanOrEqual(1)
1336 expect(workerNode
.strategyData
.virtualTaskEndTimestamp
).toBeGreaterThan(0)
1339 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1340 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1342 ).toEqual(expect
.any(Number
))
1344 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1345 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1346 ).previousWorkerNodeKey
1347 ).toEqual(expect
.any(Number
))
1348 // We need to clean up the resources after our test
1349 await pool
.destroy()
1352 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
1353 const pool
= new DynamicThreadPool(
1356 './tests/worker-files/thread/testWorker.js',
1358 workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
,
1359 workerChoiceStrategyOptions
: {
1360 runTime
: { median
: true }
1364 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1365 const promises
= new Set()
1366 const maxMultiplier
= 2
1367 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1368 promises
.add(pool
.execute())
1370 await Promise
.all(promises
)
1371 for (const workerNode
of pool
.workerNodes
) {
1372 expect(workerNode
.usage
).toStrictEqual({
1374 executed
: expect
.any(Number
),
1381 runTime
: expect
.objectContaining({
1382 history
: expect
.any(CircularArray
)
1385 history
: new CircularArray()
1387 elu
: expect
.objectContaining({
1388 idle
: expect
.objectContaining({
1389 history
: expect
.any(CircularArray
)
1391 active
: expect
.objectContaining({
1392 history
: expect
.any(CircularArray
)
1396 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1397 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1400 if (workerNode
.usage
.runTime
.aggregate
== null) {
1401 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1403 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1405 if (workerNode
.usage
.runTime
.median
== null) {
1406 expect(workerNode
.usage
.runTime
.median
).toBeUndefined()
1408 expect(workerNode
.usage
.runTime
.median
).toBeGreaterThan(0)
1410 if (workerNode
.usage
.elu
.active
.aggregate
== null) {
1411 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeUndefined()
1413 expect(workerNode
.usage
.elu
.active
.aggregate
).toBeGreaterThan(0)
1415 if (workerNode
.usage
.elu
.idle
.aggregate
== null) {
1416 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeUndefined()
1418 expect(workerNode
.usage
.elu
.idle
.aggregate
).toBeGreaterThanOrEqual(0)
1420 if (workerNode
.usage
.elu
.utilization
== null) {
1421 expect(workerNode
.usage
.elu
.utilization
).toBeUndefined()
1423 expect(workerNode
.usage
.elu
.utilization
).toBeGreaterThanOrEqual(0)
1424 expect(workerNode
.usage
.elu
.utilization
).toBeLessThanOrEqual(1)
1426 expect(workerNode
.strategyData
.virtualTaskEndTimestamp
).toBeGreaterThan(0)
1429 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1430 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1432 ).toEqual(expect
.any(Number
))
1434 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1435 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1436 ).previousWorkerNodeKey
1437 ).toEqual(expect
.any(Number
))
1438 // We need to clean up the resources after our test
1439 await pool
.destroy()
1442 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
1443 const workerChoiceStrategy
= WorkerChoiceStrategies
.FAIR_SHARE
1444 let pool
= new FixedThreadPool(
1446 './tests/worker-files/thread/testWorker.js'
1448 for (const workerNode
of pool
.workerNodes
) {
1449 workerNode
.strategyData
= {
1450 virtualTaskEndTimestamp
: performance
.now()
1453 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1454 for (const workerNode
of pool
.workerNodes
) {
1455 expect(workerNode
.strategyData
.virtualTaskEndTimestamp
).toBeUndefined()
1457 await pool
.destroy()
1458 pool
= new DynamicThreadPool(
1461 './tests/worker-files/thread/testWorker.js'
1463 for (const workerNode
of pool
.workerNodes
) {
1464 workerNode
.strategyData
= {
1465 virtualTaskEndTimestamp
: performance
.now()
1468 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1469 for (const workerNode
of pool
.workerNodes
) {
1470 expect(workerNode
.strategyData
.virtualTaskEndTimestamp
).toBeUndefined()
1472 // We need to clean up the resources after our test
1473 await pool
.destroy()
1476 it('Verify WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1477 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1478 let pool
= new FixedThreadPool(
1480 './tests/worker-files/thread/testWorker.js',
1481 { workerChoiceStrategy
}
1483 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1484 dynamicWorkerUsage
: false,
1485 dynamicWorkerReady
: true
1487 await pool
.destroy()
1488 pool
= new DynamicThreadPool(
1491 './tests/worker-files/thread/testWorker.js',
1492 { workerChoiceStrategy
}
1494 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1495 dynamicWorkerUsage
: false,
1496 dynamicWorkerReady
: true
1498 // We need to clean up the resources after our test
1499 await pool
.destroy()
1502 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
1503 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1504 let pool
= new FixedThreadPool(
1506 './tests/worker-files/thread/testWorker.js',
1507 { workerChoiceStrategy
}
1510 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1528 await pool
.destroy()
1529 pool
= new DynamicThreadPool(
1532 './tests/worker-files/thread/testWorker.js',
1533 { workerChoiceStrategy
}
1536 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1554 // We need to clean up the resources after our test
1555 await pool
.destroy()
1558 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1559 const pool
= new FixedThreadPool(
1561 './tests/worker-files/thread/testWorker.js',
1562 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
1564 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1565 const promises
= new Set()
1566 const maxMultiplier
= 2
1567 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1568 promises
.add(pool
.execute())
1570 await Promise
.all(promises
)
1571 for (const workerNode
of pool
.workerNodes
) {
1572 expect(workerNode
.usage
).toStrictEqual({
1574 executed
: expect
.any(Number
),
1581 runTime
: expect
.objectContaining({
1582 history
: expect
.any(CircularArray
)
1585 history
: new CircularArray()
1589 history
: new CircularArray()
1592 history
: new CircularArray()
1596 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1597 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1600 if (workerNode
.usage
.runTime
.aggregate
== null) {
1601 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1603 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1605 if (workerNode
.usage
.runTime
.average
== null) {
1606 expect(workerNode
.usage
.runTime
.average
).toBeUndefined()
1608 expect(workerNode
.usage
.runTime
.average
).toBeGreaterThan(0)
1612 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1613 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1617 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1618 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1619 ).previousWorkerNodeKey
1622 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1623 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1624 ).defaultWorkerWeight
1625 ).toBeGreaterThan(0)
1627 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1628 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1629 ).workerNodeVirtualTaskRunTime
1630 ).toBeGreaterThanOrEqual(0)
1631 // We need to clean up the resources after our test
1632 await pool
.destroy()
1635 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1636 const pool
= new DynamicThreadPool(
1639 './tests/worker-files/thread/testWorker.js',
1640 { workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
}
1642 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1643 const promises
= new Set()
1644 const maxMultiplier
= 2
1645 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1646 promises
.add(pool
.execute())
1648 await Promise
.all(promises
)
1649 for (const workerNode
of pool
.workerNodes
) {
1650 expect(workerNode
.usage
).toStrictEqual({
1652 executed
: expect
.any(Number
),
1659 runTime
: expect
.objectContaining({
1660 history
: expect
.any(CircularArray
)
1663 history
: new CircularArray()
1667 history
: new CircularArray()
1670 history
: new CircularArray()
1674 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1675 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1678 if (workerNode
.usage
.runTime
.aggregate
== null) {
1679 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1681 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1683 if (workerNode
.usage
.runTime
.average
== null) {
1684 expect(workerNode
.usage
.runTime
.average
).toBeUndefined()
1686 expect(workerNode
.usage
.runTime
.average
).toBeGreaterThan(0)
1690 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1691 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1695 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1696 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1697 ).previousWorkerNodeKey
1700 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1701 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1702 ).defaultWorkerWeight
1703 ).toBeGreaterThan(0)
1705 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1706 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1707 ).workerNodeVirtualTaskRunTime
1708 ).toBeGreaterThanOrEqual(0)
1709 // We need to clean up the resources after our test
1710 await pool
.destroy()
1713 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
1714 const pool
= new DynamicThreadPool(
1717 './tests/worker-files/thread/testWorker.js',
1719 workerChoiceStrategy
: WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
,
1720 workerChoiceStrategyOptions
: {
1721 runTime
: { median
: true }
1725 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1726 const promises
= new Set()
1727 const maxMultiplier
= 2
1728 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1729 promises
.add(pool
.execute())
1731 await Promise
.all(promises
)
1732 for (const workerNode
of pool
.workerNodes
) {
1733 expect(workerNode
.usage
).toStrictEqual({
1735 executed
: expect
.any(Number
),
1742 runTime
: expect
.objectContaining({
1743 history
: expect
.any(CircularArray
)
1746 history
: new CircularArray()
1750 history
: new CircularArray()
1753 history
: new CircularArray()
1757 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
1758 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
1761 if (workerNode
.usage
.runTime
.aggregate
== null) {
1762 expect(workerNode
.usage
.runTime
.aggregate
).toBeUndefined()
1764 expect(workerNode
.usage
.runTime
.aggregate
).toBeGreaterThan(0)
1766 if (workerNode
.usage
.runTime
.median
== null) {
1767 expect(workerNode
.usage
.runTime
.median
).toBeUndefined()
1769 expect(workerNode
.usage
.runTime
.median
).toBeGreaterThan(0)
1773 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1774 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1778 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1779 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1780 ).previousWorkerNodeKey
1783 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1784 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1785 ).defaultWorkerWeight
1786 ).toBeGreaterThan(0)
1788 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1789 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1790 ).workerNodeVirtualTaskRunTime
1791 ).toBeGreaterThanOrEqual(0)
1792 // We need to clean up the resources after our test
1793 await pool
.destroy()
1796 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1797 const workerChoiceStrategy
= WorkerChoiceStrategies
.WEIGHTED_ROUND_ROBIN
1798 let pool
= new FixedThreadPool(
1800 './tests/worker-files/thread/testWorker.js'
1803 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1804 workerChoiceStrategy
1808 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1809 workerChoiceStrategy
1810 ).previousWorkerNodeKey
1813 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1814 workerChoiceStrategy
1815 ).defaultWorkerWeight
1818 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1819 workerChoiceStrategy
1820 ).workerNodeVirtualTaskRunTime
1822 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1824 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1825 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1829 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1830 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1831 ).previousWorkerNodeKey
1834 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1835 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1836 ).defaultWorkerWeight
1837 ).toBeGreaterThan(0)
1839 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1840 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1841 ).workerNodeVirtualTaskRunTime
1843 await pool
.destroy()
1844 pool
= new DynamicThreadPool(
1847 './tests/worker-files/thread/testWorker.js'
1850 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1851 workerChoiceStrategy
1855 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1856 workerChoiceStrategy
1857 ).previousWorkerNodeKey
1860 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1861 workerChoiceStrategy
1862 ).defaultWorkerWeight
1865 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1866 workerChoiceStrategy
1867 ).workerNodeVirtualTaskRunTime
1869 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
1871 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1872 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1876 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1877 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1878 ).previousWorkerNodeKey
1881 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1882 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1883 ).defaultWorkerWeight
1884 ).toBeGreaterThan(0)
1886 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
1887 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
1888 ).workerNodeVirtualTaskRunTime
1890 // We need to clean up the resources after our test
1891 await pool
.destroy()
1894 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1895 const workerChoiceStrategy
=
1896 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1897 let pool
= new FixedThreadPool(
1899 './tests/worker-files/thread/testWorker.js',
1900 { workerChoiceStrategy
}
1902 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1903 dynamicWorkerUsage
: false,
1904 dynamicWorkerReady
: true
1906 await pool
.destroy()
1907 pool
= new DynamicThreadPool(
1910 './tests/worker-files/thread/testWorker.js',
1911 { workerChoiceStrategy
}
1913 expect(pool
.workerChoiceStrategyContext
.getStrategyPolicy()).toStrictEqual({
1914 dynamicWorkerUsage
: false,
1915 dynamicWorkerReady
: true
1917 // We need to clean up the resources after our test
1918 await pool
.destroy()
1921 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
1922 const workerChoiceStrategy
=
1923 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1924 let pool
= new FixedThreadPool(
1926 './tests/worker-files/thread/testWorker.js',
1927 { workerChoiceStrategy
}
1930 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1948 await pool
.destroy()
1949 pool
= new DynamicThreadPool(
1952 './tests/worker-files/thread/testWorker.js',
1953 { workerChoiceStrategy
}
1956 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
1974 // We need to clean up the resources after our test
1975 await pool
.destroy()
1978 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1979 const pool
= new FixedThreadPool(
1981 './tests/worker-files/thread/testWorker.js',
1983 workerChoiceStrategy
:
1984 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1987 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1988 const promises
= new Set()
1989 const maxMultiplier
= 2
1990 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
1991 promises
.add(pool
.execute())
1993 await Promise
.all(promises
)
1994 for (const workerNode
of pool
.workerNodes
) {
1995 expect(workerNode
.usage
).toStrictEqual({
1997 executed
: expect
.any(Number
),
2004 runTime
: expect
.objectContaining({
2005 history
: expect
.any(CircularArray
)
2008 history
: new CircularArray()
2012 history
: new CircularArray()
2015 history
: new CircularArray()
2019 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
2020 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
2025 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2026 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2027 ).defaultWorkerWeight
2028 ).toBeGreaterThan(0)
2030 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2031 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2035 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2036 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2040 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2041 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2045 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2046 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2047 ).previousWorkerNodeKey
2048 ).toEqual(expect
.any(Number
))
2050 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2051 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2054 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2055 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2056 ).defaultWorkerWeight
2058 // We need to clean up the resources after our test
2059 await pool
.destroy()
2062 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
2063 const pool
= new DynamicThreadPool(
2066 './tests/worker-files/thread/testWorker.js',
2068 workerChoiceStrategy
:
2069 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2072 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
2073 const promises
= new Set()
2074 const maxMultiplier
= 2
2075 for (let i
= 0; i
< max
* maxMultiplier
; i
++) {
2076 promises
.add(pool
.execute())
2078 await Promise
.all(promises
)
2079 for (const workerNode
of pool
.workerNodes
) {
2080 expect(workerNode
.usage
).toStrictEqual({
2082 executed
: expect
.any(Number
),
2089 runTime
: expect
.objectContaining({
2090 history
: expect
.any(CircularArray
)
2093 history
: new CircularArray()
2097 history
: new CircularArray()
2100 history
: new CircularArray()
2104 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThanOrEqual(0)
2105 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(
2110 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2111 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2112 ).defaultWorkerWeight
2113 ).toBeGreaterThan(0)
2115 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2116 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2120 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2121 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2125 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2126 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2130 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2131 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2132 ).previousWorkerNodeKey
2133 ).toEqual(expect
.any(Number
))
2135 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2136 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2139 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2140 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2141 ).defaultWorkerWeight
2143 // We need to clean up the resources after our test
2144 await pool
.destroy()
2147 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
2148 const workerChoiceStrategy
=
2149 WorkerChoiceStrategies
.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2150 let pool
= new FixedThreadPool(
2152 './tests/worker-files/thread/testWorker.js'
2155 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2156 workerChoiceStrategy
2160 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2161 workerChoiceStrategy
2165 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2166 workerChoiceStrategy
2170 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2171 workerChoiceStrategy
2172 ).previousWorkerNodeKey
2175 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2176 workerChoiceStrategy
2177 ).defaultWorkerWeight
2180 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2181 workerChoiceStrategy
2184 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
2186 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2187 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2191 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2192 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2196 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2197 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2201 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2202 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2203 ).previousWorkerNodeKey
2206 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2207 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2208 ).defaultWorkerWeight
2209 ).toBeGreaterThan(0)
2211 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2212 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2215 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2216 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2217 ).defaultWorkerWeight
2219 await pool
.destroy()
2220 pool
= new DynamicThreadPool(
2223 './tests/worker-files/thread/testWorker.js'
2226 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2227 workerChoiceStrategy
2231 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2232 workerChoiceStrategy
2236 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2237 workerChoiceStrategy
2241 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2242 workerChoiceStrategy
2243 ).previousWorkerNodeKey
2246 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2247 workerChoiceStrategy
2248 ).defaultWorkerWeight
2251 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2252 workerChoiceStrategy
2255 pool
.setWorkerChoiceStrategy(workerChoiceStrategy
)
2257 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2258 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2262 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2263 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2267 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2268 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2272 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2273 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2274 ).previousWorkerNodeKey
2277 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2278 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2279 ).defaultWorkerWeight
2280 ).toBeGreaterThan(0)
2282 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2283 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2286 pool
.workerChoiceStrategyContext
.workerChoiceStrategies
.get(
2287 pool
.workerChoiceStrategyContext
.workerChoiceStrategy
2288 ).defaultWorkerWeight
2290 // We need to clean up the resources after our test
2291 await pool
.destroy()
2294 it('Verify unknown strategy throw error', () => {
2297 new DynamicThreadPool(
2300 './tests/worker-files/thread/testWorker.js',
2301 { workerChoiceStrategy
: 'UNKNOWN_STRATEGY' }
2303 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")