1 import { expect } from 'expect'
8 } from '../../../lib/index.cjs'
9 import { CircularArray } from '../../../lib/circular-array.cjs'
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.mjs'
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.mjs',
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.mjs'
64 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
65 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
66 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
71 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
72 const pool = new DynamicClusterPool(
75 './tests/worker-files/cluster/testWorker.cjs'
77 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
78 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
79 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
86 it('Verify available strategies default internals at pool creation', async () => {
87 const pool = new FixedThreadPool(
89 './tests/worker-files/thread/testWorker.mjs'
91 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
93 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
98 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
100 ).previousWorkerNodeKey
103 workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
106 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
108 ).workerNodeVirtualTaskRunTime
111 workerChoiceStrategy ===
112 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
115 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
117 ).workerNodeVirtualTaskRunTime
120 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
125 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
130 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
132 ).roundWeights.length
135 Number.isSafeInteger(
136 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
146 it('Verify strategies wait for worker node readiness in dynamic pool', async () => {
147 const pool = new DynamicThreadPool(
150 './tests/worker-files/thread/testWorker.mjs'
152 expect(pool.starting).toBe(false)
153 expect(pool.workerNodes.length).toBe(min)
154 const maxMultiplier = 10000
155 const promises = new Set()
156 for (let i = 0; i < max * maxMultiplier; i++) {
157 promises.add(pool.execute())
159 await Promise.all(promises)
160 expect(pool.workerNodes.length).toBe(max)
161 // We need to clean up the resources after our test
165 it('Verify ROUND_ROBIN strategy default policy', async () => {
166 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
167 let pool = new FixedThreadPool(
169 './tests/worker-files/thread/testWorker.mjs',
170 { workerChoiceStrategy }
172 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
173 dynamicWorkerUsage: false,
174 dynamicWorkerReady: true
177 pool = new DynamicThreadPool(
180 './tests/worker-files/thread/testWorker.mjs',
181 { workerChoiceStrategy }
183 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
184 dynamicWorkerUsage: false,
185 dynamicWorkerReady: true
187 // We need to clean up the resources after our test
191 it('Verify ROUND_ROBIN strategy default tasks statistics requirements', async () => {
192 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
193 let pool = new FixedThreadPool(
195 './tests/worker-files/thread/testWorker.mjs',
196 { workerChoiceStrategy }
199 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
218 pool = new DynamicThreadPool(
221 './tests/worker-files/thread/testWorker.mjs',
222 { workerChoiceStrategy }
225 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
243 // We need to clean up the resources after our test
247 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
248 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
249 const pool = new FixedThreadPool(
251 './tests/worker-files/thread/testWorker.mjs',
252 { workerChoiceStrategy }
254 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
255 const promises = new Set()
256 const maxMultiplier = 2
257 for (let i = 0; i < max * maxMultiplier; i++) {
258 promises.add(pool.execute())
260 await Promise.all(promises)
261 for (const workerNode of pool.workerNodes) {
262 expect(workerNode.usage).toStrictEqual({
264 executed: maxMultiplier,
268 sequentiallyStolen: 0,
273 history: new CircularArray()
276 history: new CircularArray()
280 history: new CircularArray()
283 history: new CircularArray()
289 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
290 pool.workerChoiceStrategyContext.workerChoiceStrategy
294 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
295 pool.workerChoiceStrategyContext.workerChoiceStrategy
296 ).previousWorkerNodeKey
297 ).toBe(pool.workerNodes.length - 1)
298 // We need to clean up the resources after our test
302 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
303 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
304 const pool = new DynamicThreadPool(
307 './tests/worker-files/thread/testWorker.mjs',
308 { workerChoiceStrategy }
310 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
311 const promises = new Set()
312 const maxMultiplier = 2
313 for (let i = 0; i < max * maxMultiplier; i++) {
314 promises.add(pool.execute())
316 await Promise.all(promises)
317 for (const workerNode of pool.workerNodes) {
318 expect(workerNode.usage).toStrictEqual({
320 executed: expect.any(Number),
324 sequentiallyStolen: 0,
329 history: new CircularArray()
332 history: new CircularArray()
336 history: new CircularArray()
339 history: new CircularArray()
343 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
344 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
349 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
350 pool.workerChoiceStrategyContext.workerChoiceStrategy
354 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
355 pool.workerChoiceStrategyContext.workerChoiceStrategy
356 ).previousWorkerNodeKey
357 ).toBe(pool.workerNodes.length - 1)
358 // We need to clean up the resources after our test
362 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
363 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
364 let pool = new FixedClusterPool(
366 './tests/worker-files/cluster/testWorker.cjs',
367 { workerChoiceStrategy }
369 let results = new Set()
370 for (let i = 0; i < max; i++) {
371 results.add(pool.workerNodes[pool.chooseWorkerNode()].info.id)
373 expect(results.size).toBe(max)
375 pool = new FixedThreadPool(
377 './tests/worker-files/thread/testWorker.mjs',
378 { workerChoiceStrategy }
381 for (let i = 0; i < max; i++) {
382 results.add(pool.workerNodes[pool.chooseWorkerNode()].info.id)
384 expect(results.size).toBe(max)
388 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
389 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
390 let pool = new FixedThreadPool(
392 './tests/worker-files/thread/testWorker.mjs',
393 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
396 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
397 pool.workerChoiceStrategyContext.workerChoiceStrategy
401 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
402 pool.workerChoiceStrategyContext.workerChoiceStrategy
403 ).previousWorkerNodeKey
405 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
407 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
408 pool.workerChoiceStrategyContext.workerChoiceStrategy
412 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
413 pool.workerChoiceStrategyContext.workerChoiceStrategy
414 ).previousWorkerNodeKey
417 pool = new DynamicThreadPool(
420 './tests/worker-files/thread/testWorker.mjs',
421 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
424 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
425 pool.workerChoiceStrategyContext.workerChoiceStrategy
429 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
430 pool.workerChoiceStrategyContext.workerChoiceStrategy
431 ).previousWorkerNodeKey
433 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
435 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
436 pool.workerChoiceStrategyContext.workerChoiceStrategy
440 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
441 pool.workerChoiceStrategyContext.workerChoiceStrategy
442 ).previousWorkerNodeKey
444 // We need to clean up the resources after our test
448 it('Verify LEAST_USED strategy default policy', async () => {
449 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
450 let pool = new FixedThreadPool(
452 './tests/worker-files/thread/testWorker.mjs',
453 { workerChoiceStrategy }
455 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
456 dynamicWorkerUsage: false,
457 dynamicWorkerReady: true
460 pool = new DynamicThreadPool(
463 './tests/worker-files/thread/testWorker.mjs',
464 { workerChoiceStrategy }
466 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
467 dynamicWorkerUsage: false,
468 dynamicWorkerReady: true
470 // We need to clean up the resources after our test
474 it('Verify LEAST_USED strategy default tasks statistics requirements', async () => {
475 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
476 let pool = new FixedThreadPool(
478 './tests/worker-files/thread/testWorker.mjs',
479 { workerChoiceStrategy }
482 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
501 pool = new DynamicThreadPool(
504 './tests/worker-files/thread/testWorker.mjs',
505 { workerChoiceStrategy }
508 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
526 // We need to clean up the resources after our test
530 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
531 const pool = new FixedThreadPool(
533 './tests/worker-files/thread/testWorker.mjs',
534 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
536 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
537 const promises = new Set()
538 const maxMultiplier = 2
539 for (let i = 0; i < max * maxMultiplier; i++) {
540 promises.add(pool.execute())
542 await Promise.all(promises)
543 for (const workerNode of pool.workerNodes) {
544 expect(workerNode.usage).toStrictEqual({
546 executed: expect.any(Number),
550 sequentiallyStolen: 0,
555 history: new CircularArray()
558 history: new CircularArray()
562 history: new CircularArray()
565 history: new CircularArray()
569 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
570 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
575 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
576 pool.workerChoiceStrategyContext.workerChoiceStrategy
578 ).toEqual(expect.any(Number))
580 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
581 pool.workerChoiceStrategyContext.workerChoiceStrategy
582 ).previousWorkerNodeKey
583 ).toEqual(expect.any(Number))
584 // We need to clean up the resources after our test
588 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
589 const pool = new DynamicThreadPool(
592 './tests/worker-files/thread/testWorker.mjs',
593 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
595 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
596 const promises = new Set()
597 const maxMultiplier = 2
598 for (let i = 0; i < max * maxMultiplier; i++) {
599 promises.add(pool.execute())
601 await Promise.all(promises)
602 for (const workerNode of pool.workerNodes) {
603 expect(workerNode.usage).toStrictEqual({
605 executed: expect.any(Number),
609 sequentiallyStolen: 0,
614 history: new CircularArray()
617 history: new CircularArray()
621 history: new CircularArray()
624 history: new CircularArray()
628 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
629 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
634 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
635 pool.workerChoiceStrategyContext.workerChoiceStrategy
637 ).toEqual(expect.any(Number))
639 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
640 pool.workerChoiceStrategyContext.workerChoiceStrategy
641 ).previousWorkerNodeKey
642 ).toEqual(expect.any(Number))
643 // We need to clean up the resources after our test
647 it('Verify LEAST_BUSY strategy default policy', async () => {
648 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
649 let pool = new FixedThreadPool(
651 './tests/worker-files/thread/testWorker.mjs',
652 { workerChoiceStrategy }
654 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
655 dynamicWorkerUsage: false,
656 dynamicWorkerReady: true
659 pool = new DynamicThreadPool(
662 './tests/worker-files/thread/testWorker.mjs',
663 { workerChoiceStrategy }
665 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
666 dynamicWorkerUsage: false,
667 dynamicWorkerReady: true
669 // We need to clean up the resources after our test
673 it('Verify LEAST_BUSY strategy default tasks statistics requirements', async () => {
674 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
675 let pool = new FixedThreadPool(
677 './tests/worker-files/thread/testWorker.mjs',
678 { workerChoiceStrategy }
681 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
700 pool = new DynamicThreadPool(
703 './tests/worker-files/thread/testWorker.mjs',
704 { workerChoiceStrategy }
707 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
725 // We need to clean up the resources after our test
729 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
730 const pool = new FixedThreadPool(
732 './tests/worker-files/thread/testWorker.mjs',
733 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
735 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
736 const promises = new Set()
737 const maxMultiplier = 2
738 for (let i = 0; i < max * maxMultiplier; i++) {
739 promises.add(pool.execute())
741 await Promise.all(promises)
742 for (const workerNode of pool.workerNodes) {
743 expect(workerNode.usage).toStrictEqual({
745 executed: expect.any(Number),
749 sequentiallyStolen: 0,
753 runTime: expect.objectContaining({
754 history: expect.any(CircularArray)
756 waitTime: expect.objectContaining({
757 history: expect.any(CircularArray)
761 history: new CircularArray()
764 history: new CircularArray()
768 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
769 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
772 if (workerNode.usage.runTime.aggregate == null) {
773 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
775 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
777 if (workerNode.usage.waitTime.aggregate == null) {
778 expect(workerNode.usage.waitTime.aggregate).toBeUndefined()
780 expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
784 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
785 pool.workerChoiceStrategyContext.workerChoiceStrategy
787 ).toEqual(expect.any(Number))
789 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
790 pool.workerChoiceStrategyContext.workerChoiceStrategy
791 ).previousWorkerNodeKey
792 ).toEqual(expect.any(Number))
793 // We need to clean up the resources after our test
797 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
798 const pool = new DynamicThreadPool(
801 './tests/worker-files/thread/testWorker.mjs',
802 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
804 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
805 const promises = new Set()
806 const maxMultiplier = 2
807 for (let i = 0; i < max * maxMultiplier; i++) {
808 promises.add(pool.execute())
810 await Promise.all(promises)
811 for (const workerNode of pool.workerNodes) {
812 expect(workerNode.usage).toStrictEqual({
814 executed: expect.any(Number),
818 sequentiallyStolen: 0,
822 runTime: expect.objectContaining({
823 history: expect.any(CircularArray)
825 waitTime: expect.objectContaining({
826 history: expect.any(CircularArray)
830 history: new CircularArray()
833 history: new CircularArray()
837 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
838 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
841 if (workerNode.usage.runTime.aggregate == null) {
842 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
844 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
846 if (workerNode.usage.waitTime.aggregate == null) {
847 expect(workerNode.usage.waitTime.aggregate).toBeUndefined()
849 expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
853 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
854 pool.workerChoiceStrategyContext.workerChoiceStrategy
856 ).toEqual(expect.any(Number))
858 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
859 pool.workerChoiceStrategyContext.workerChoiceStrategy
860 ).previousWorkerNodeKey
861 ).toEqual(expect.any(Number))
862 // We need to clean up the resources after our test
866 it('Verify LEAST_ELU strategy default policy', async () => {
867 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
868 let pool = new FixedThreadPool(
870 './tests/worker-files/thread/testWorker.mjs',
871 { workerChoiceStrategy }
873 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
874 dynamicWorkerUsage: false,
875 dynamicWorkerReady: true
878 pool = new DynamicThreadPool(
881 './tests/worker-files/thread/testWorker.mjs',
882 { workerChoiceStrategy }
884 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
885 dynamicWorkerUsage: false,
886 dynamicWorkerReady: true
888 // We need to clean up the resources after our test
892 it('Verify LEAST_ELU strategy default tasks statistics requirements', async () => {
893 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
894 let pool = new FixedThreadPool(
896 './tests/worker-files/thread/testWorker.mjs',
897 { workerChoiceStrategy }
900 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
919 pool = new DynamicThreadPool(
922 './tests/worker-files/thread/testWorker.mjs',
923 { workerChoiceStrategy }
926 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
944 // We need to clean up the resources after our test
948 it('Verify LEAST_ELU strategy can be run in a fixed pool', async () => {
949 const pool = new FixedThreadPool(
951 './tests/worker-files/thread/testWorker.mjs',
952 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_ELU }
954 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
955 const promises = new Set()
956 const maxMultiplier = 2
957 for (let i = 0; i < max * maxMultiplier; i++) {
958 promises.add(pool.execute())
960 await Promise.all(promises)
961 for (const workerNode of pool.workerNodes) {
962 expect(workerNode.usage).toStrictEqual({
964 executed: expect.any(Number),
968 sequentiallyStolen: 0,
973 history: new CircularArray()
976 history: new CircularArray()
978 elu: expect.objectContaining({
979 idle: expect.objectContaining({
980 history: expect.any(CircularArray)
982 active: expect.objectContaining({
983 history: expect.any(CircularArray)
987 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
988 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
991 if (workerNode.usage.elu.active.aggregate == null) {
992 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
994 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
996 if (workerNode.usage.elu.idle.aggregate == null) {
997 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
999 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1001 if (workerNode.usage.elu.utilization == null) {
1002 expect(workerNode.usage.elu.utilization).toBeUndefined()
1004 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1005 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1009 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1010 pool.workerChoiceStrategyContext.workerChoiceStrategy
1012 ).toEqual(expect.any(Number))
1014 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1015 pool.workerChoiceStrategyContext.workerChoiceStrategy
1016 ).previousWorkerNodeKey
1017 ).toEqual(expect.any(Number))
1018 // We need to clean up the resources after our test
1019 await pool.destroy()
1022 it('Verify LEAST_ELU strategy can be run in a dynamic pool', async () => {
1023 const pool = new DynamicThreadPool(
1026 './tests/worker-files/thread/testWorker.mjs',
1027 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_ELU }
1029 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
1030 const promises = new Set()
1031 const maxMultiplier = 2
1032 for (let i = 0; i < max * maxMultiplier; i++) {
1033 promises.add(pool.execute())
1035 await Promise.all(promises)
1036 for (const workerNode of pool.workerNodes) {
1037 expect(workerNode.usage).toStrictEqual({
1039 executed: expect.any(Number),
1043 sequentiallyStolen: 0,
1048 history: new CircularArray()
1051 history: new CircularArray()
1053 elu: expect.objectContaining({
1054 idle: expect.objectContaining({
1055 history: expect.any(CircularArray)
1057 active: expect.objectContaining({
1058 history: expect.any(CircularArray)
1062 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1063 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1066 if (workerNode.usage.elu.active.aggregate == null) {
1067 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1069 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1071 if (workerNode.usage.elu.idle.aggregate == null) {
1072 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1074 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1076 if (workerNode.usage.elu.utilization == null) {
1077 expect(workerNode.usage.elu.utilization).toBeUndefined()
1079 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1080 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1084 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1085 pool.workerChoiceStrategyContext.workerChoiceStrategy
1087 ).toEqual(expect.any(Number))
1089 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1090 pool.workerChoiceStrategyContext.workerChoiceStrategy
1091 ).previousWorkerNodeKey
1092 ).toEqual(expect.any(Number))
1093 // We need to clean up the resources after our test
1094 await pool.destroy()
1097 it('Verify FAIR_SHARE strategy default policy', async () => {
1098 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
1099 let pool = new FixedThreadPool(
1101 './tests/worker-files/thread/testWorker.mjs',
1102 { workerChoiceStrategy }
1104 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1105 dynamicWorkerUsage: false,
1106 dynamicWorkerReady: true
1108 await pool.destroy()
1109 pool = new DynamicThreadPool(
1112 './tests/worker-files/thread/testWorker.mjs',
1113 { workerChoiceStrategy }
1115 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1116 dynamicWorkerUsage: false,
1117 dynamicWorkerReady: true
1119 // We need to clean up the resources after our test
1120 await pool.destroy()
1123 it('Verify FAIR_SHARE strategy default tasks statistics requirements', async () => {
1124 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
1125 let pool = new FixedThreadPool(
1127 './tests/worker-files/thread/testWorker.mjs',
1128 { workerChoiceStrategy }
1131 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1149 await pool.destroy()
1150 pool = new DynamicThreadPool(
1153 './tests/worker-files/thread/testWorker.mjs',
1154 { workerChoiceStrategy }
1157 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1175 // We need to clean up the resources after our test
1176 await pool.destroy()
1179 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
1180 const pool = new FixedThreadPool(
1182 './tests/worker-files/thread/testWorker.mjs',
1183 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
1185 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1186 const promises = new Set()
1187 const maxMultiplier = 2
1188 for (let i = 0; i < max * maxMultiplier; i++) {
1189 promises.add(pool.execute())
1191 await Promise.all(promises)
1192 for (const workerNode of pool.workerNodes) {
1193 expect(workerNode.usage).toStrictEqual({
1195 executed: expect.any(Number),
1199 sequentiallyStolen: 0,
1203 runTime: expect.objectContaining({
1204 history: expect.any(CircularArray)
1207 history: new CircularArray()
1209 elu: expect.objectContaining({
1210 idle: expect.objectContaining({
1211 history: expect.any(CircularArray)
1213 active: expect.objectContaining({
1214 history: expect.any(CircularArray)
1218 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1219 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1222 if (workerNode.usage.runTime.aggregate == null) {
1223 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1225 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1227 if (workerNode.usage.runTime.average == null) {
1228 expect(workerNode.usage.runTime.average).toBeUndefined()
1230 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1232 if (workerNode.usage.elu.active.aggregate == null) {
1233 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1235 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1237 if (workerNode.usage.elu.idle.aggregate == null) {
1238 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1240 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1242 if (workerNode.usage.elu.utilization == null) {
1243 expect(workerNode.usage.elu.utilization).toBeUndefined()
1245 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1246 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1248 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
1251 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1252 pool.workerChoiceStrategyContext.workerChoiceStrategy
1254 ).toEqual(expect.any(Number))
1256 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1257 pool.workerChoiceStrategyContext.workerChoiceStrategy
1258 ).previousWorkerNodeKey
1259 ).toEqual(expect.any(Number))
1260 // We need to clean up the resources after our test
1261 await pool.destroy()
1264 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
1265 const pool = new DynamicThreadPool(
1268 './tests/worker-files/thread/testWorker.mjs',
1269 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
1271 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1272 const promises = new Set()
1273 const maxMultiplier = 2
1274 for (let i = 0; i < max * maxMultiplier; i++) {
1275 promises.add(pool.execute())
1277 await Promise.all(promises)
1278 for (const workerNode of pool.workerNodes) {
1279 expect(workerNode.usage).toStrictEqual({
1281 executed: expect.any(Number),
1285 sequentiallyStolen: 0,
1289 runTime: expect.objectContaining({
1290 history: expect.any(CircularArray)
1293 history: new CircularArray()
1295 elu: expect.objectContaining({
1296 idle: expect.objectContaining({
1297 history: expect.any(CircularArray)
1299 active: expect.objectContaining({
1300 history: expect.any(CircularArray)
1304 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1305 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1308 if (workerNode.usage.runTime.aggregate == null) {
1309 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1311 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1313 if (workerNode.usage.runTime.average == null) {
1314 expect(workerNode.usage.runTime.average).toBeUndefined()
1316 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1318 if (workerNode.usage.elu.active.aggregate == null) {
1319 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1321 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1323 if (workerNode.usage.elu.idle.aggregate == null) {
1324 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1326 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1328 if (workerNode.usage.elu.utilization == null) {
1329 expect(workerNode.usage.elu.utilization).toBeUndefined()
1331 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1332 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1334 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
1337 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1338 pool.workerChoiceStrategyContext.workerChoiceStrategy
1340 ).toEqual(expect.any(Number))
1342 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1343 pool.workerChoiceStrategyContext.workerChoiceStrategy
1344 ).previousWorkerNodeKey
1345 ).toEqual(expect.any(Number))
1346 // We need to clean up the resources after our test
1347 await pool.destroy()
1350 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
1351 const pool = new DynamicThreadPool(
1354 './tests/worker-files/thread/testWorker.mjs',
1356 workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE,
1357 workerChoiceStrategyOptions: {
1358 runTime: { median: true }
1362 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1363 const promises = new Set()
1364 const maxMultiplier = 2
1365 for (let i = 0; i < max * maxMultiplier; i++) {
1366 promises.add(pool.execute())
1368 await Promise.all(promises)
1369 for (const workerNode of pool.workerNodes) {
1370 expect(workerNode.usage).toStrictEqual({
1372 executed: expect.any(Number),
1376 sequentiallyStolen: 0,
1380 runTime: expect.objectContaining({
1381 history: expect.any(CircularArray)
1384 history: new CircularArray()
1386 elu: expect.objectContaining({
1387 idle: expect.objectContaining({
1388 history: expect.any(CircularArray)
1390 active: expect.objectContaining({
1391 history: expect.any(CircularArray)
1395 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1396 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1399 if (workerNode.usage.runTime.aggregate == null) {
1400 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1402 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1404 if (workerNode.usage.runTime.median == null) {
1405 expect(workerNode.usage.runTime.median).toBeUndefined()
1407 expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
1409 if (workerNode.usage.elu.active.aggregate == null) {
1410 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1412 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1414 if (workerNode.usage.elu.idle.aggregate == null) {
1415 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1417 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1419 if (workerNode.usage.elu.utilization == null) {
1420 expect(workerNode.usage.elu.utilization).toBeUndefined()
1422 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1423 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1425 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
1428 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1429 pool.workerChoiceStrategyContext.workerChoiceStrategy
1431 ).toEqual(expect.any(Number))
1433 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1434 pool.workerChoiceStrategyContext.workerChoiceStrategy
1435 ).previousWorkerNodeKey
1436 ).toEqual(expect.any(Number))
1437 // We need to clean up the resources after our test
1438 await pool.destroy()
1441 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
1442 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
1443 let pool = new FixedThreadPool(
1445 './tests/worker-files/thread/testWorker.mjs'
1447 for (const workerNode of pool.workerNodes) {
1448 workerNode.strategyData = {
1449 virtualTaskEndTimestamp: performance.now()
1452 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1453 for (const workerNode of pool.workerNodes) {
1454 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeUndefined()
1456 await pool.destroy()
1457 pool = new DynamicThreadPool(
1460 './tests/worker-files/thread/testWorker.mjs'
1462 for (const workerNode of pool.workerNodes) {
1463 workerNode.strategyData = {
1464 virtualTaskEndTimestamp: performance.now()
1467 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1468 for (const workerNode of pool.workerNodes) {
1469 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeUndefined()
1471 // We need to clean up the resources after our test
1472 await pool.destroy()
1475 it('Verify WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1476 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1477 let pool = new FixedThreadPool(
1479 './tests/worker-files/thread/testWorker.mjs',
1480 { workerChoiceStrategy }
1482 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1483 dynamicWorkerUsage: false,
1484 dynamicWorkerReady: true
1486 await pool.destroy()
1487 pool = new DynamicThreadPool(
1490 './tests/worker-files/thread/testWorker.mjs',
1491 { workerChoiceStrategy }
1493 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1494 dynamicWorkerUsage: false,
1495 dynamicWorkerReady: true
1497 // We need to clean up the resources after our test
1498 await pool.destroy()
1501 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
1502 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1503 let pool = new FixedThreadPool(
1505 './tests/worker-files/thread/testWorker.mjs',
1506 { workerChoiceStrategy }
1509 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1527 await pool.destroy()
1528 pool = new DynamicThreadPool(
1531 './tests/worker-files/thread/testWorker.mjs',
1532 { workerChoiceStrategy }
1535 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1553 // We need to clean up the resources after our test
1554 await pool.destroy()
1557 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1558 const pool = new FixedThreadPool(
1560 './tests/worker-files/thread/testWorker.mjs',
1561 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1563 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1564 const promises = new Set()
1565 const maxMultiplier = 2
1566 for (let i = 0; i < max * maxMultiplier; i++) {
1567 promises.add(pool.execute())
1569 await Promise.all(promises)
1570 for (const workerNode of pool.workerNodes) {
1571 expect(workerNode.usage).toStrictEqual({
1573 executed: expect.any(Number),
1577 sequentiallyStolen: 0,
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 ).workerNodeVirtualTaskRunTime
1625 ).toBeGreaterThanOrEqual(0)
1626 // We need to clean up the resources after our test
1627 await pool.destroy()
1630 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1631 const pool = new DynamicThreadPool(
1634 './tests/worker-files/thread/testWorker.mjs',
1635 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1637 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1638 const promises = new Set()
1639 const maxMultiplier = 2
1640 for (let i = 0; i < max * maxMultiplier; i++) {
1641 promises.add(pool.execute())
1643 await Promise.all(promises)
1644 for (const workerNode of pool.workerNodes) {
1645 expect(workerNode.usage).toStrictEqual({
1647 executed: expect.any(Number),
1651 sequentiallyStolen: 0,
1655 runTime: expect.objectContaining({
1656 history: expect.any(CircularArray)
1659 history: new CircularArray()
1663 history: new CircularArray()
1666 history: new CircularArray()
1670 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1671 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1674 if (workerNode.usage.runTime.aggregate == null) {
1675 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1677 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1679 if (workerNode.usage.runTime.average == null) {
1680 expect(workerNode.usage.runTime.average).toBeUndefined()
1682 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1686 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1687 pool.workerChoiceStrategyContext.workerChoiceStrategy
1691 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1692 pool.workerChoiceStrategyContext.workerChoiceStrategy
1693 ).previousWorkerNodeKey
1696 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1697 pool.workerChoiceStrategyContext.workerChoiceStrategy
1698 ).workerNodeVirtualTaskRunTime
1699 ).toBeGreaterThanOrEqual(0)
1700 // We need to clean up the resources after our test
1701 await pool.destroy()
1704 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
1705 const pool = new DynamicThreadPool(
1708 './tests/worker-files/thread/testWorker.mjs',
1710 workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN,
1711 workerChoiceStrategyOptions: {
1712 runTime: { median: true }
1716 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1717 const promises = new Set()
1718 const maxMultiplier = 2
1719 for (let i = 0; i < max * maxMultiplier; i++) {
1720 promises.add(pool.execute())
1722 await Promise.all(promises)
1723 for (const workerNode of pool.workerNodes) {
1724 expect(workerNode.usage).toStrictEqual({
1726 executed: expect.any(Number),
1730 sequentiallyStolen: 0,
1734 runTime: expect.objectContaining({
1735 history: expect.any(CircularArray)
1738 history: new CircularArray()
1742 history: new CircularArray()
1745 history: new CircularArray()
1749 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1750 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1753 if (workerNode.usage.runTime.aggregate == null) {
1754 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1756 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1758 if (workerNode.usage.runTime.median == null) {
1759 expect(workerNode.usage.runTime.median).toBeUndefined()
1761 expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
1765 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1766 pool.workerChoiceStrategyContext.workerChoiceStrategy
1770 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1771 pool.workerChoiceStrategyContext.workerChoiceStrategy
1772 ).previousWorkerNodeKey
1775 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1776 pool.workerChoiceStrategyContext.workerChoiceStrategy
1777 ).workerNodeVirtualTaskRunTime
1778 ).toBeGreaterThanOrEqual(0)
1779 // We need to clean up the resources after our test
1780 await pool.destroy()
1783 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1784 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1785 let pool = new FixedThreadPool(
1787 './tests/worker-files/thread/testWorker.mjs'
1790 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1791 workerChoiceStrategy
1795 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1796 workerChoiceStrategy
1797 ).previousWorkerNodeKey
1800 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1801 workerChoiceStrategy
1802 ).workerNodeVirtualTaskRunTime
1804 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1806 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1807 pool.workerChoiceStrategyContext.workerChoiceStrategy
1811 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1812 pool.workerChoiceStrategyContext.workerChoiceStrategy
1813 ).previousWorkerNodeKey
1816 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1817 pool.workerChoiceStrategyContext.workerChoiceStrategy
1818 ).workerNodeVirtualTaskRunTime
1820 await pool.destroy()
1821 pool = new DynamicThreadPool(
1824 './tests/worker-files/thread/testWorker.mjs'
1827 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1828 workerChoiceStrategy
1832 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1833 workerChoiceStrategy
1834 ).previousWorkerNodeKey
1837 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1838 workerChoiceStrategy
1839 ).workerNodeVirtualTaskRunTime
1841 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1843 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1844 pool.workerChoiceStrategyContext.workerChoiceStrategy
1848 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1849 pool.workerChoiceStrategyContext.workerChoiceStrategy
1850 ).previousWorkerNodeKey
1853 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1854 pool.workerChoiceStrategyContext.workerChoiceStrategy
1855 ).workerNodeVirtualTaskRunTime
1857 // We need to clean up the resources after our test
1858 await pool.destroy()
1861 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1862 const workerChoiceStrategy =
1863 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1864 let pool = new FixedThreadPool(
1866 './tests/worker-files/thread/testWorker.mjs',
1867 { workerChoiceStrategy }
1869 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1870 dynamicWorkerUsage: false,
1871 dynamicWorkerReady: true
1873 await pool.destroy()
1874 pool = new DynamicThreadPool(
1877 './tests/worker-files/thread/testWorker.mjs',
1878 { workerChoiceStrategy }
1880 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1881 dynamicWorkerUsage: false,
1882 dynamicWorkerReady: true
1884 // We need to clean up the resources after our test
1885 await pool.destroy()
1888 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
1889 const workerChoiceStrategy =
1890 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1891 let pool = new FixedThreadPool(
1893 './tests/worker-files/thread/testWorker.mjs',
1894 { workerChoiceStrategy }
1897 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1915 await pool.destroy()
1916 pool = new DynamicThreadPool(
1919 './tests/worker-files/thread/testWorker.mjs',
1920 { workerChoiceStrategy }
1923 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1941 // We need to clean up the resources after our test
1942 await pool.destroy()
1945 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1946 const pool = new FixedThreadPool(
1948 './tests/worker-files/thread/testWorker.mjs',
1950 workerChoiceStrategy:
1951 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1954 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1955 const promises = new Set()
1956 const maxMultiplier = 2
1957 for (let i = 0; i < max * maxMultiplier; i++) {
1958 promises.add(pool.execute())
1960 await Promise.all(promises)
1961 for (const workerNode of pool.workerNodes) {
1962 expect(workerNode.usage).toStrictEqual({
1964 executed: expect.any(Number),
1968 sequentiallyStolen: 0,
1972 runTime: expect.objectContaining({
1973 history: expect.any(CircularArray)
1976 history: new CircularArray()
1980 history: new CircularArray()
1983 history: new CircularArray()
1987 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1988 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1993 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1994 pool.workerChoiceStrategyContext.workerChoiceStrategy
1998 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1999 pool.workerChoiceStrategyContext.workerChoiceStrategy
2003 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2004 pool.workerChoiceStrategyContext.workerChoiceStrategy
2008 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2009 pool.workerChoiceStrategyContext.workerChoiceStrategy
2010 ).previousWorkerNodeKey
2013 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2014 pool.workerChoiceStrategyContext.workerChoiceStrategy
2015 ).roundWeights.length
2018 Number.isSafeInteger(
2019 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2020 pool.workerChoiceStrategyContext.workerChoiceStrategy
2024 // We need to clean up the resources after our test
2025 await pool.destroy()
2028 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
2029 const pool = new DynamicThreadPool(
2032 './tests/worker-files/thread/testWorker.mjs',
2034 workerChoiceStrategy:
2035 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2038 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
2039 const promises = new Set()
2040 const maxMultiplier = 2
2041 for (let i = 0; i < max * maxMultiplier; i++) {
2042 promises.add(pool.execute())
2044 await Promise.all(promises)
2045 for (const workerNode of pool.workerNodes) {
2046 expect(workerNode.usage).toStrictEqual({
2048 executed: expect.any(Number),
2052 sequentiallyStolen: 0,
2056 runTime: expect.objectContaining({
2057 history: expect.any(CircularArray)
2060 history: new CircularArray()
2064 history: new CircularArray()
2067 history: new CircularArray()
2071 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
2072 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
2077 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2078 pool.workerChoiceStrategyContext.workerChoiceStrategy
2082 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2083 pool.workerChoiceStrategyContext.workerChoiceStrategy
2087 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2088 pool.workerChoiceStrategyContext.workerChoiceStrategy
2092 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2093 pool.workerChoiceStrategyContext.workerChoiceStrategy
2094 ).previousWorkerNodeKey
2097 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2098 pool.workerChoiceStrategyContext.workerChoiceStrategy
2099 ).roundWeights.length
2102 Number.isSafeInteger(
2103 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2104 pool.workerChoiceStrategyContext.workerChoiceStrategy
2108 // We need to clean up the resources after our test
2109 await pool.destroy()
2112 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
2113 const workerChoiceStrategy =
2114 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2115 let pool = new FixedThreadPool(
2117 './tests/worker-files/thread/testWorker.mjs'
2120 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2121 workerChoiceStrategy
2125 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2126 workerChoiceStrategy
2130 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2131 workerChoiceStrategy
2135 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2136 workerChoiceStrategy
2137 ).previousWorkerNodeKey
2140 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2141 workerChoiceStrategy
2144 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
2146 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2147 pool.workerChoiceStrategyContext.workerChoiceStrategy
2151 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2152 pool.workerChoiceStrategyContext.workerChoiceStrategy
2156 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2157 pool.workerChoiceStrategyContext.workerChoiceStrategy
2161 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2162 pool.workerChoiceStrategyContext.workerChoiceStrategy
2163 ).previousWorkerNodeKey
2166 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2167 pool.workerChoiceStrategyContext.workerChoiceStrategy
2168 ).roundWeights.length
2171 Number.isSafeInteger(
2172 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2173 pool.workerChoiceStrategyContext.workerChoiceStrategy
2177 await pool.destroy()
2178 pool = new DynamicThreadPool(
2181 './tests/worker-files/thread/testWorker.mjs'
2184 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2185 workerChoiceStrategy
2189 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2190 workerChoiceStrategy
2194 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2195 workerChoiceStrategy
2199 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2200 workerChoiceStrategy
2201 ).previousWorkerNodeKey
2204 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2205 workerChoiceStrategy
2208 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
2210 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2211 pool.workerChoiceStrategyContext.workerChoiceStrategy
2215 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2216 pool.workerChoiceStrategyContext.workerChoiceStrategy
2220 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2221 pool.workerChoiceStrategyContext.workerChoiceStrategy
2225 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2226 pool.workerChoiceStrategyContext.workerChoiceStrategy
2227 ).previousWorkerNodeKey
2230 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2231 pool.workerChoiceStrategyContext.workerChoiceStrategy
2232 ).roundWeights.length
2235 Number.isSafeInteger(
2236 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2237 pool.workerChoiceStrategyContext.workerChoiceStrategy
2241 // We need to clean up the resources after our test
2242 await pool.destroy()
2245 it('Verify unknown strategy throw error', () => {
2248 new DynamicThreadPool(
2251 './tests/worker-files/thread/testWorker.mjs',
2252 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
2254 ).toThrow("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")