1 import { expect } from 'expect'
3 import { CircularArray } from '../../../lib/circular-array.cjs'
10 } from '../../../lib/index.cjs'
12 describe('Selection strategies test suite', () => {
16 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
17 expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN')
18 expect(WorkerChoiceStrategies.LEAST_USED).toBe('LEAST_USED')
19 expect(WorkerChoiceStrategies.LEAST_BUSY).toBe('LEAST_BUSY')
20 expect(WorkerChoiceStrategies.LEAST_ELU).toBe('LEAST_ELU')
21 expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE')
22 expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe(
23 'WEIGHTED_ROUND_ROBIN'
25 expect(WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN).toBe(
26 'INTERLEAVED_WEIGHTED_ROUND_ROBIN'
30 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
31 const pool = new DynamicThreadPool(
34 './tests/worker-files/thread/testWorker.mjs'
36 expect(pool.opts.workerChoiceStrategy).toBe(
37 WorkerChoiceStrategies.ROUND_ROBIN
39 // We need to clean up the resources after our test
43 it('Verify available strategies are taken at pool creation', async () => {
44 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
45 const pool = new FixedThreadPool(
47 './tests/worker-files/thread/testWorker.mjs',
48 { workerChoiceStrategy }
50 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
51 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
58 it('Verify available strategies can be set after pool creation', async () => {
59 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
60 const pool = new DynamicThreadPool(
63 './tests/worker-files/thread/testWorker.mjs'
65 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
66 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
67 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
72 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
73 const pool = new DynamicClusterPool(
76 './tests/worker-files/cluster/testWorker.cjs'
78 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
79 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
80 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
87 it('Verify available strategies default internals at pool creation', async () => {
88 const pool = new FixedThreadPool(
90 './tests/worker-files/thread/testWorker.mjs'
92 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
94 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
99 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
101 ).previousWorkerNodeKey
104 workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
107 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
109 ).workerNodeVirtualTaskRunTime
112 workerChoiceStrategy ===
113 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
116 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
118 ).workerNodeVirtualTaskRunTime
121 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
126 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
131 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
133 ).roundWeights.length
136 Number.isSafeInteger(
137 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
147 it('Verify ROUND_ROBIN strategy default policy', async () => {
148 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
149 let pool = new FixedThreadPool(
151 './tests/worker-files/thread/testWorker.mjs',
152 { workerChoiceStrategy }
154 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
155 dynamicWorkerUsage: false,
156 dynamicWorkerReady: true
159 pool = new DynamicThreadPool(
162 './tests/worker-files/thread/testWorker.mjs',
163 { workerChoiceStrategy }
165 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
166 dynamicWorkerUsage: false,
167 dynamicWorkerReady: true
169 // We need to clean up the resources after our test
173 it('Verify ROUND_ROBIN strategy default tasks statistics requirements', async () => {
174 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
175 let pool = new FixedThreadPool(
177 './tests/worker-files/thread/testWorker.mjs',
178 { workerChoiceStrategy }
181 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
200 pool = new DynamicThreadPool(
203 './tests/worker-files/thread/testWorker.mjs',
204 { workerChoiceStrategy }
207 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
225 // We need to clean up the resources after our test
229 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
230 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
231 const pool = new FixedThreadPool(
233 './tests/worker-files/thread/testWorker.mjs',
234 { workerChoiceStrategy }
236 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
237 const promises = new Set()
238 const maxMultiplier = 2
239 for (let i = 0; i < max * maxMultiplier; i++) {
240 promises.add(pool.execute())
242 await Promise.all(promises)
243 for (const workerNode of pool.workerNodes) {
244 expect(workerNode.usage).toStrictEqual({
246 executed: maxMultiplier,
250 sequentiallyStolen: 0,
255 history: new CircularArray()
258 history: new CircularArray()
262 history: new CircularArray()
265 history: new CircularArray()
271 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
272 pool.workerChoiceStrategyContext.workerChoiceStrategy
276 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
277 pool.workerChoiceStrategyContext.workerChoiceStrategy
278 ).previousWorkerNodeKey
279 ).toBe(pool.workerNodes.length - 1)
280 // We need to clean up the resources after our test
284 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
285 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
286 const pool = new DynamicThreadPool(
289 './tests/worker-files/thread/testWorker.mjs',
290 { workerChoiceStrategy }
292 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
293 const promises = new Set()
294 const maxMultiplier = 2
295 for (let i = 0; i < max * maxMultiplier; i++) {
296 promises.add(pool.execute())
298 await Promise.all(promises)
299 for (const workerNode of pool.workerNodes) {
300 expect(workerNode.usage).toStrictEqual({
302 executed: expect.any(Number),
306 sequentiallyStolen: 0,
311 history: new CircularArray()
314 history: new CircularArray()
318 history: new CircularArray()
321 history: new CircularArray()
325 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
326 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
331 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
332 pool.workerChoiceStrategyContext.workerChoiceStrategy
336 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
337 pool.workerChoiceStrategyContext.workerChoiceStrategy
338 ).previousWorkerNodeKey
339 ).toBe(pool.workerNodes.length - 1)
340 // We need to clean up the resources after our test
344 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
345 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
346 let pool = new FixedClusterPool(
348 './tests/worker-files/cluster/testWorker.cjs',
349 { workerChoiceStrategy }
351 let results = new Set()
352 for (let i = 0; i < max; i++) {
353 results.add(pool.workerNodes[pool.chooseWorkerNode()].info.id)
355 expect(results.size).toBe(max)
357 pool = new FixedThreadPool(
359 './tests/worker-files/thread/testWorker.mjs',
360 { workerChoiceStrategy }
363 for (let i = 0; i < max; i++) {
364 results.add(pool.workerNodes[pool.chooseWorkerNode()].info.id)
366 expect(results.size).toBe(max)
370 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
371 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
372 let pool = new FixedThreadPool(
374 './tests/worker-files/thread/testWorker.mjs',
375 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
378 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
379 pool.workerChoiceStrategyContext.workerChoiceStrategy
383 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
384 pool.workerChoiceStrategyContext.workerChoiceStrategy
385 ).previousWorkerNodeKey
387 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
389 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
390 pool.workerChoiceStrategyContext.workerChoiceStrategy
394 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
395 pool.workerChoiceStrategyContext.workerChoiceStrategy
396 ).previousWorkerNodeKey
399 pool = new DynamicThreadPool(
402 './tests/worker-files/thread/testWorker.mjs',
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
426 // We need to clean up the resources after our test
430 it('Verify LEAST_USED strategy default policy', async () => {
431 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
432 let pool = new FixedThreadPool(
434 './tests/worker-files/thread/testWorker.mjs',
435 { workerChoiceStrategy }
437 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
438 dynamicWorkerUsage: false,
439 dynamicWorkerReady: true
442 pool = new DynamicThreadPool(
445 './tests/worker-files/thread/testWorker.mjs',
446 { workerChoiceStrategy }
448 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
449 dynamicWorkerUsage: false,
450 dynamicWorkerReady: true
452 // We need to clean up the resources after our test
456 it('Verify LEAST_USED strategy default tasks statistics requirements', async () => {
457 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
458 let pool = new FixedThreadPool(
460 './tests/worker-files/thread/testWorker.mjs',
461 { workerChoiceStrategy }
464 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
483 pool = new DynamicThreadPool(
486 './tests/worker-files/thread/testWorker.mjs',
487 { workerChoiceStrategy }
490 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
508 // We need to clean up the resources after our test
512 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
513 const pool = new FixedThreadPool(
515 './tests/worker-files/thread/testWorker.mjs',
516 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
518 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
519 const promises = new Set()
520 const maxMultiplier = 2
521 for (let i = 0; i < max * maxMultiplier; i++) {
522 promises.add(pool.execute())
524 await Promise.all(promises)
525 for (const workerNode of pool.workerNodes) {
526 expect(workerNode.usage).toStrictEqual({
528 executed: expect.any(Number),
532 sequentiallyStolen: 0,
537 history: new CircularArray()
540 history: new CircularArray()
544 history: new CircularArray()
547 history: new CircularArray()
551 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
552 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
557 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
558 pool.workerChoiceStrategyContext.workerChoiceStrategy
560 ).toEqual(expect.any(Number))
562 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
563 pool.workerChoiceStrategyContext.workerChoiceStrategy
564 ).previousWorkerNodeKey
565 ).toEqual(expect.any(Number))
566 // We need to clean up the resources after our test
570 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
571 const pool = new DynamicThreadPool(
574 './tests/worker-files/thread/testWorker.mjs',
575 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
577 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
578 const promises = new Set()
579 const maxMultiplier = 2
580 for (let i = 0; i < max * maxMultiplier; i++) {
581 promises.add(pool.execute())
583 await Promise.all(promises)
584 for (const workerNode of pool.workerNodes) {
585 expect(workerNode.usage).toStrictEqual({
587 executed: expect.any(Number),
591 sequentiallyStolen: 0,
596 history: new CircularArray()
599 history: new CircularArray()
603 history: new CircularArray()
606 history: new CircularArray()
610 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
611 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
616 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
617 pool.workerChoiceStrategyContext.workerChoiceStrategy
619 ).toEqual(expect.any(Number))
621 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
622 pool.workerChoiceStrategyContext.workerChoiceStrategy
623 ).previousWorkerNodeKey
624 ).toEqual(expect.any(Number))
625 // We need to clean up the resources after our test
629 it('Verify LEAST_BUSY strategy default policy', async () => {
630 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
631 let pool = new FixedThreadPool(
633 './tests/worker-files/thread/testWorker.mjs',
634 { workerChoiceStrategy }
636 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
637 dynamicWorkerUsage: false,
638 dynamicWorkerReady: true
641 pool = new DynamicThreadPool(
644 './tests/worker-files/thread/testWorker.mjs',
645 { workerChoiceStrategy }
647 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
648 dynamicWorkerUsage: false,
649 dynamicWorkerReady: true
651 // We need to clean up the resources after our test
655 it('Verify LEAST_BUSY strategy default tasks statistics requirements', async () => {
656 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
657 let pool = new FixedThreadPool(
659 './tests/worker-files/thread/testWorker.mjs',
660 { workerChoiceStrategy }
663 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
682 pool = new DynamicThreadPool(
685 './tests/worker-files/thread/testWorker.mjs',
686 { workerChoiceStrategy }
689 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
707 // We need to clean up the resources after our test
711 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
712 const pool = new FixedThreadPool(
714 './tests/worker-files/thread/testWorker.mjs',
715 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
717 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
718 const promises = new Set()
719 const maxMultiplier = 2
720 for (let i = 0; i < max * maxMultiplier; i++) {
721 promises.add(pool.execute())
723 await Promise.all(promises)
724 for (const workerNode of pool.workerNodes) {
725 expect(workerNode.usage).toStrictEqual({
727 executed: expect.any(Number),
731 sequentiallyStolen: 0,
735 runTime: expect.objectContaining({
736 history: expect.any(CircularArray)
738 waitTime: expect.objectContaining({
739 history: expect.any(CircularArray)
743 history: new CircularArray()
746 history: new CircularArray()
750 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
751 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
754 if (workerNode.usage.runTime.aggregate == null) {
755 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
757 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
759 if (workerNode.usage.waitTime.aggregate == null) {
760 expect(workerNode.usage.waitTime.aggregate).toBeUndefined()
762 expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
766 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
767 pool.workerChoiceStrategyContext.workerChoiceStrategy
769 ).toEqual(expect.any(Number))
771 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
772 pool.workerChoiceStrategyContext.workerChoiceStrategy
773 ).previousWorkerNodeKey
774 ).toEqual(expect.any(Number))
775 // We need to clean up the resources after our test
779 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
780 const pool = new DynamicThreadPool(
783 './tests/worker-files/thread/testWorker.mjs',
784 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
786 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
787 const promises = new Set()
788 const maxMultiplier = 2
789 for (let i = 0; i < max * maxMultiplier; i++) {
790 promises.add(pool.execute())
792 await Promise.all(promises)
793 for (const workerNode of pool.workerNodes) {
794 expect(workerNode.usage).toStrictEqual({
796 executed: expect.any(Number),
800 sequentiallyStolen: 0,
804 runTime: expect.objectContaining({
805 history: expect.any(CircularArray)
807 waitTime: expect.objectContaining({
808 history: expect.any(CircularArray)
812 history: new CircularArray()
815 history: new CircularArray()
819 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
820 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
823 if (workerNode.usage.runTime.aggregate == null) {
824 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
826 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
828 if (workerNode.usage.waitTime.aggregate == null) {
829 expect(workerNode.usage.waitTime.aggregate).toBeUndefined()
831 expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
835 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
836 pool.workerChoiceStrategyContext.workerChoiceStrategy
838 ).toEqual(expect.any(Number))
840 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
841 pool.workerChoiceStrategyContext.workerChoiceStrategy
842 ).previousWorkerNodeKey
843 ).toEqual(expect.any(Number))
844 // We need to clean up the resources after our test
848 it('Verify LEAST_ELU strategy default policy', async () => {
849 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
850 let pool = new FixedThreadPool(
852 './tests/worker-files/thread/testWorker.mjs',
853 { workerChoiceStrategy }
855 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
856 dynamicWorkerUsage: false,
857 dynamicWorkerReady: true
860 pool = new DynamicThreadPool(
863 './tests/worker-files/thread/testWorker.mjs',
864 { workerChoiceStrategy }
866 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
867 dynamicWorkerUsage: false,
868 dynamicWorkerReady: true
870 // We need to clean up the resources after our test
874 it('Verify LEAST_ELU strategy default tasks statistics requirements', async () => {
875 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
876 let pool = new FixedThreadPool(
878 './tests/worker-files/thread/testWorker.mjs',
879 { workerChoiceStrategy }
882 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
901 pool = new DynamicThreadPool(
904 './tests/worker-files/thread/testWorker.mjs',
905 { workerChoiceStrategy }
908 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
926 // We need to clean up the resources after our test
930 it('Verify LEAST_ELU strategy can be run in a fixed pool', async () => {
931 const pool = new FixedThreadPool(
933 './tests/worker-files/thread/testWorker.mjs',
934 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_ELU }
936 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
937 const promises = new Set()
938 const maxMultiplier = 2
939 for (let i = 0; i < max * maxMultiplier; i++) {
940 promises.add(pool.execute())
942 await Promise.all(promises)
943 for (const workerNode of pool.workerNodes) {
944 expect(workerNode.usage).toStrictEqual({
946 executed: expect.any(Number),
950 sequentiallyStolen: 0,
955 history: new CircularArray()
958 history: new CircularArray()
960 elu: expect.objectContaining({
961 idle: expect.objectContaining({
962 history: expect.any(CircularArray)
964 active: expect.objectContaining({
965 history: expect.any(CircularArray)
969 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
970 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
973 if (workerNode.usage.elu.active.aggregate == null) {
974 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
976 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
978 if (workerNode.usage.elu.idle.aggregate == null) {
979 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
981 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
983 if (workerNode.usage.elu.utilization == null) {
984 expect(workerNode.usage.elu.utilization).toBeUndefined()
986 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
987 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
991 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
992 pool.workerChoiceStrategyContext.workerChoiceStrategy
994 ).toEqual(expect.any(Number))
996 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
997 pool.workerChoiceStrategyContext.workerChoiceStrategy
998 ).previousWorkerNodeKey
999 ).toEqual(expect.any(Number))
1000 // We need to clean up the resources after our test
1001 await pool.destroy()
1004 it('Verify LEAST_ELU strategy can be run in a dynamic pool', async () => {
1005 const pool = new DynamicThreadPool(
1008 './tests/worker-files/thread/testWorker.mjs',
1009 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_ELU }
1011 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
1012 const promises = new Set()
1013 const maxMultiplier = 2
1014 for (let i = 0; i < max * maxMultiplier; i++) {
1015 promises.add(pool.execute())
1017 await Promise.all(promises)
1018 for (const workerNode of pool.workerNodes) {
1019 expect(workerNode.usage).toStrictEqual({
1021 executed: expect.any(Number),
1025 sequentiallyStolen: 0,
1030 history: new CircularArray()
1033 history: new CircularArray()
1035 elu: expect.objectContaining({
1036 idle: expect.objectContaining({
1037 history: expect.any(CircularArray)
1039 active: expect.objectContaining({
1040 history: expect.any(CircularArray)
1044 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1045 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1048 if (workerNode.usage.elu.active.aggregate == null) {
1049 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1051 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1053 if (workerNode.usage.elu.idle.aggregate == null) {
1054 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1056 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1058 if (workerNode.usage.elu.utilization == null) {
1059 expect(workerNode.usage.elu.utilization).toBeUndefined()
1061 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1062 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1066 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1067 pool.workerChoiceStrategyContext.workerChoiceStrategy
1069 ).toEqual(expect.any(Number))
1071 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1072 pool.workerChoiceStrategyContext.workerChoiceStrategy
1073 ).previousWorkerNodeKey
1074 ).toEqual(expect.any(Number))
1075 // We need to clean up the resources after our test
1076 await pool.destroy()
1079 it('Verify FAIR_SHARE strategy default policy', async () => {
1080 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
1081 let pool = new FixedThreadPool(
1083 './tests/worker-files/thread/testWorker.mjs',
1084 { workerChoiceStrategy }
1086 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1087 dynamicWorkerUsage: false,
1088 dynamicWorkerReady: true
1090 await pool.destroy()
1091 pool = new DynamicThreadPool(
1094 './tests/worker-files/thread/testWorker.mjs',
1095 { workerChoiceStrategy }
1097 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1098 dynamicWorkerUsage: false,
1099 dynamicWorkerReady: true
1101 // We need to clean up the resources after our test
1102 await pool.destroy()
1105 it('Verify FAIR_SHARE strategy default tasks statistics requirements', async () => {
1106 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
1107 let pool = new FixedThreadPool(
1109 './tests/worker-files/thread/testWorker.mjs',
1110 { workerChoiceStrategy }
1113 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1131 await pool.destroy()
1132 pool = new DynamicThreadPool(
1135 './tests/worker-files/thread/testWorker.mjs',
1136 { workerChoiceStrategy }
1139 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1157 // We need to clean up the resources after our test
1158 await pool.destroy()
1161 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
1162 const pool = new FixedThreadPool(
1164 './tests/worker-files/thread/testWorker.mjs',
1165 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
1167 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1168 const promises = new Set()
1169 const maxMultiplier = 2
1170 for (let i = 0; i < max * maxMultiplier; i++) {
1171 promises.add(pool.execute())
1173 await Promise.all(promises)
1174 for (const workerNode of pool.workerNodes) {
1175 expect(workerNode.usage).toStrictEqual({
1177 executed: expect.any(Number),
1181 sequentiallyStolen: 0,
1185 runTime: expect.objectContaining({
1186 history: expect.any(CircularArray)
1189 history: new CircularArray()
1191 elu: expect.objectContaining({
1192 idle: expect.objectContaining({
1193 history: expect.any(CircularArray)
1195 active: expect.objectContaining({
1196 history: expect.any(CircularArray)
1200 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1201 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1204 if (workerNode.usage.runTime.aggregate == null) {
1205 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1207 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1209 if (workerNode.usage.runTime.average == null) {
1210 expect(workerNode.usage.runTime.average).toBeUndefined()
1212 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1214 if (workerNode.usage.elu.active.aggregate == null) {
1215 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1217 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1219 if (workerNode.usage.elu.idle.aggregate == null) {
1220 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1222 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1224 if (workerNode.usage.elu.utilization == null) {
1225 expect(workerNode.usage.elu.utilization).toBeUndefined()
1227 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1228 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1230 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
1233 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1234 pool.workerChoiceStrategyContext.workerChoiceStrategy
1236 ).toEqual(expect.any(Number))
1238 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1239 pool.workerChoiceStrategyContext.workerChoiceStrategy
1240 ).previousWorkerNodeKey
1241 ).toEqual(expect.any(Number))
1242 // We need to clean up the resources after our test
1243 await pool.destroy()
1246 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
1247 const pool = new DynamicThreadPool(
1250 './tests/worker-files/thread/testWorker.mjs',
1251 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
1253 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1254 const promises = new Set()
1255 const maxMultiplier = 2
1256 for (let i = 0; i < max * maxMultiplier; i++) {
1257 promises.add(pool.execute())
1259 await Promise.all(promises)
1260 for (const workerNode of pool.workerNodes) {
1261 expect(workerNode.usage).toStrictEqual({
1263 executed: expect.any(Number),
1267 sequentiallyStolen: 0,
1271 runTime: expect.objectContaining({
1272 history: expect.any(CircularArray)
1275 history: new CircularArray()
1277 elu: expect.objectContaining({
1278 idle: expect.objectContaining({
1279 history: expect.any(CircularArray)
1281 active: expect.objectContaining({
1282 history: expect.any(CircularArray)
1286 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1287 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1290 if (workerNode.usage.runTime.aggregate == null) {
1291 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1293 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1295 if (workerNode.usage.runTime.average == null) {
1296 expect(workerNode.usage.runTime.average).toBeUndefined()
1298 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1300 if (workerNode.usage.elu.active.aggregate == null) {
1301 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1303 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1305 if (workerNode.usage.elu.idle.aggregate == null) {
1306 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1308 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1310 if (workerNode.usage.elu.utilization == null) {
1311 expect(workerNode.usage.elu.utilization).toBeUndefined()
1313 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1314 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1316 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
1319 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1320 pool.workerChoiceStrategyContext.workerChoiceStrategy
1322 ).toEqual(expect.any(Number))
1324 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1325 pool.workerChoiceStrategyContext.workerChoiceStrategy
1326 ).previousWorkerNodeKey
1327 ).toEqual(expect.any(Number))
1328 // We need to clean up the resources after our test
1329 await pool.destroy()
1332 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
1333 const pool = new DynamicThreadPool(
1336 './tests/worker-files/thread/testWorker.mjs',
1338 workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE,
1339 workerChoiceStrategyOptions: {
1340 runTime: { median: true }
1344 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1345 const promises = new Set()
1346 const maxMultiplier = 2
1347 for (let i = 0; i < max * maxMultiplier; i++) {
1348 promises.add(pool.execute())
1350 await Promise.all(promises)
1351 for (const workerNode of pool.workerNodes) {
1352 expect(workerNode.usage).toStrictEqual({
1354 executed: expect.any(Number),
1358 sequentiallyStolen: 0,
1362 runTime: expect.objectContaining({
1363 history: expect.any(CircularArray)
1366 history: new CircularArray()
1368 elu: expect.objectContaining({
1369 idle: expect.objectContaining({
1370 history: expect.any(CircularArray)
1372 active: expect.objectContaining({
1373 history: expect.any(CircularArray)
1377 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1378 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1381 if (workerNode.usage.runTime.aggregate == null) {
1382 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1384 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1386 if (workerNode.usage.runTime.median == null) {
1387 expect(workerNode.usage.runTime.median).toBeUndefined()
1389 expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
1391 if (workerNode.usage.elu.active.aggregate == null) {
1392 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1394 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1396 if (workerNode.usage.elu.idle.aggregate == null) {
1397 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1399 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1401 if (workerNode.usage.elu.utilization == null) {
1402 expect(workerNode.usage.elu.utilization).toBeUndefined()
1404 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1405 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1407 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
1410 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1411 pool.workerChoiceStrategyContext.workerChoiceStrategy
1413 ).toEqual(expect.any(Number))
1415 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1416 pool.workerChoiceStrategyContext.workerChoiceStrategy
1417 ).previousWorkerNodeKey
1418 ).toEqual(expect.any(Number))
1419 // We need to clean up the resources after our test
1420 await pool.destroy()
1423 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
1424 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
1425 let pool = new FixedThreadPool(
1427 './tests/worker-files/thread/testWorker.mjs'
1429 for (const workerNode of pool.workerNodes) {
1430 workerNode.strategyData = {
1431 virtualTaskEndTimestamp: performance.now()
1434 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1435 for (const workerNode of pool.workerNodes) {
1436 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeUndefined()
1438 await pool.destroy()
1439 pool = new DynamicThreadPool(
1442 './tests/worker-files/thread/testWorker.mjs'
1444 for (const workerNode of pool.workerNodes) {
1445 workerNode.strategyData = {
1446 virtualTaskEndTimestamp: performance.now()
1449 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1450 for (const workerNode of pool.workerNodes) {
1451 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeUndefined()
1453 // We need to clean up the resources after our test
1454 await pool.destroy()
1457 it('Verify WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1458 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1459 let pool = new FixedThreadPool(
1461 './tests/worker-files/thread/testWorker.mjs',
1462 { workerChoiceStrategy }
1464 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1465 dynamicWorkerUsage: false,
1466 dynamicWorkerReady: true
1468 await pool.destroy()
1469 pool = new DynamicThreadPool(
1472 './tests/worker-files/thread/testWorker.mjs',
1473 { workerChoiceStrategy }
1475 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1476 dynamicWorkerUsage: false,
1477 dynamicWorkerReady: true
1479 // We need to clean up the resources after our test
1480 await pool.destroy()
1483 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
1484 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1485 let pool = new FixedThreadPool(
1487 './tests/worker-files/thread/testWorker.mjs',
1488 { workerChoiceStrategy }
1491 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1509 await pool.destroy()
1510 pool = new DynamicThreadPool(
1513 './tests/worker-files/thread/testWorker.mjs',
1514 { workerChoiceStrategy }
1517 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1535 // We need to clean up the resources after our test
1536 await pool.destroy()
1539 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1540 const pool = new FixedThreadPool(
1542 './tests/worker-files/thread/testWorker.mjs',
1543 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1545 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1546 const promises = new Set()
1547 const maxMultiplier = 2
1548 for (let i = 0; i < max * maxMultiplier; i++) {
1549 promises.add(pool.execute())
1551 await Promise.all(promises)
1552 for (const workerNode of pool.workerNodes) {
1553 expect(workerNode.usage).toStrictEqual({
1555 executed: expect.any(Number),
1559 sequentiallyStolen: 0,
1563 runTime: expect.objectContaining({
1564 history: expect.any(CircularArray)
1567 history: new CircularArray()
1571 history: new CircularArray()
1574 history: new CircularArray()
1578 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1579 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1582 if (workerNode.usage.runTime.aggregate == null) {
1583 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1585 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1587 if (workerNode.usage.runTime.average == null) {
1588 expect(workerNode.usage.runTime.average).toBeUndefined()
1590 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1594 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1595 pool.workerChoiceStrategyContext.workerChoiceStrategy
1599 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1600 pool.workerChoiceStrategyContext.workerChoiceStrategy
1601 ).previousWorkerNodeKey
1604 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1605 pool.workerChoiceStrategyContext.workerChoiceStrategy
1606 ).workerNodeVirtualTaskRunTime
1607 ).toBeGreaterThanOrEqual(0)
1608 // We need to clean up the resources after our test
1609 await pool.destroy()
1612 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1613 const pool = new DynamicThreadPool(
1616 './tests/worker-files/thread/testWorker.mjs',
1617 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1619 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1620 const promises = new Set()
1621 const maxMultiplier = 2
1622 for (let i = 0; i < max * maxMultiplier; i++) {
1623 promises.add(pool.execute())
1625 await Promise.all(promises)
1626 for (const workerNode of pool.workerNodes) {
1627 expect(workerNode.usage).toStrictEqual({
1629 executed: expect.any(Number),
1633 sequentiallyStolen: 0,
1637 runTime: expect.objectContaining({
1638 history: expect.any(CircularArray)
1641 history: new CircularArray()
1645 history: new CircularArray()
1648 history: new CircularArray()
1652 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1653 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1656 if (workerNode.usage.runTime.aggregate == null) {
1657 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1659 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1661 if (workerNode.usage.runTime.average == null) {
1662 expect(workerNode.usage.runTime.average).toBeUndefined()
1664 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1668 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1669 pool.workerChoiceStrategyContext.workerChoiceStrategy
1673 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1674 pool.workerChoiceStrategyContext.workerChoiceStrategy
1675 ).previousWorkerNodeKey
1678 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1679 pool.workerChoiceStrategyContext.workerChoiceStrategy
1680 ).workerNodeVirtualTaskRunTime
1681 ).toBeGreaterThanOrEqual(0)
1682 // We need to clean up the resources after our test
1683 await pool.destroy()
1686 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
1687 const pool = new DynamicThreadPool(
1690 './tests/worker-files/thread/testWorker.mjs',
1692 workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN,
1693 workerChoiceStrategyOptions: {
1694 runTime: { median: true }
1698 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1699 const promises = new Set()
1700 const maxMultiplier = 2
1701 for (let i = 0; i < max * maxMultiplier; i++) {
1702 promises.add(pool.execute())
1704 await Promise.all(promises)
1705 for (const workerNode of pool.workerNodes) {
1706 expect(workerNode.usage).toStrictEqual({
1708 executed: expect.any(Number),
1712 sequentiallyStolen: 0,
1716 runTime: expect.objectContaining({
1717 history: expect.any(CircularArray)
1720 history: new CircularArray()
1724 history: new CircularArray()
1727 history: new CircularArray()
1731 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1732 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1735 if (workerNode.usage.runTime.aggregate == null) {
1736 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1738 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1740 if (workerNode.usage.runTime.median == null) {
1741 expect(workerNode.usage.runTime.median).toBeUndefined()
1743 expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
1747 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1748 pool.workerChoiceStrategyContext.workerChoiceStrategy
1752 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1753 pool.workerChoiceStrategyContext.workerChoiceStrategy
1754 ).previousWorkerNodeKey
1757 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1758 pool.workerChoiceStrategyContext.workerChoiceStrategy
1759 ).workerNodeVirtualTaskRunTime
1760 ).toBeGreaterThanOrEqual(0)
1761 // We need to clean up the resources after our test
1762 await pool.destroy()
1765 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1766 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1767 let pool = new FixedThreadPool(
1769 './tests/worker-files/thread/testWorker.mjs'
1772 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1773 workerChoiceStrategy
1777 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1778 workerChoiceStrategy
1779 ).previousWorkerNodeKey
1782 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1783 workerChoiceStrategy
1784 ).workerNodeVirtualTaskRunTime
1786 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1788 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1789 pool.workerChoiceStrategyContext.workerChoiceStrategy
1793 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1794 pool.workerChoiceStrategyContext.workerChoiceStrategy
1795 ).previousWorkerNodeKey
1798 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1799 pool.workerChoiceStrategyContext.workerChoiceStrategy
1800 ).workerNodeVirtualTaskRunTime
1802 await pool.destroy()
1803 pool = new DynamicThreadPool(
1806 './tests/worker-files/thread/testWorker.mjs'
1809 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1810 workerChoiceStrategy
1814 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1815 workerChoiceStrategy
1816 ).previousWorkerNodeKey
1819 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1820 workerChoiceStrategy
1821 ).workerNodeVirtualTaskRunTime
1823 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1825 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1826 pool.workerChoiceStrategyContext.workerChoiceStrategy
1830 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1831 pool.workerChoiceStrategyContext.workerChoiceStrategy
1832 ).previousWorkerNodeKey
1835 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1836 pool.workerChoiceStrategyContext.workerChoiceStrategy
1837 ).workerNodeVirtualTaskRunTime
1839 // We need to clean up the resources after our test
1840 await pool.destroy()
1843 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1844 const workerChoiceStrategy =
1845 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1846 let pool = new FixedThreadPool(
1848 './tests/worker-files/thread/testWorker.mjs',
1849 { workerChoiceStrategy }
1851 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1852 dynamicWorkerUsage: false,
1853 dynamicWorkerReady: true
1855 await pool.destroy()
1856 pool = new DynamicThreadPool(
1859 './tests/worker-files/thread/testWorker.mjs',
1860 { workerChoiceStrategy }
1862 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1863 dynamicWorkerUsage: false,
1864 dynamicWorkerReady: true
1866 // We need to clean up the resources after our test
1867 await pool.destroy()
1870 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
1871 const workerChoiceStrategy =
1872 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1873 let pool = new FixedThreadPool(
1875 './tests/worker-files/thread/testWorker.mjs',
1876 { workerChoiceStrategy }
1879 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1897 await pool.destroy()
1898 pool = new DynamicThreadPool(
1901 './tests/worker-files/thread/testWorker.mjs',
1902 { workerChoiceStrategy }
1905 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1923 // We need to clean up the resources after our test
1924 await pool.destroy()
1927 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1928 const pool = new FixedThreadPool(
1930 './tests/worker-files/thread/testWorker.mjs',
1932 workerChoiceStrategy:
1933 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1936 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1937 const promises = new Set()
1938 const maxMultiplier = 2
1939 for (let i = 0; i < max * maxMultiplier; i++) {
1940 promises.add(pool.execute())
1942 await Promise.all(promises)
1943 for (const workerNode of pool.workerNodes) {
1944 expect(workerNode.usage).toStrictEqual({
1946 executed: expect.any(Number),
1950 sequentiallyStolen: 0,
1954 runTime: expect.objectContaining({
1955 history: expect.any(CircularArray)
1958 history: new CircularArray()
1962 history: new CircularArray()
1965 history: new CircularArray()
1969 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1970 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1975 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1976 pool.workerChoiceStrategyContext.workerChoiceStrategy
1980 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1981 pool.workerChoiceStrategyContext.workerChoiceStrategy
1985 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1986 pool.workerChoiceStrategyContext.workerChoiceStrategy
1990 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1991 pool.workerChoiceStrategyContext.workerChoiceStrategy
1992 ).previousWorkerNodeKey
1995 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1996 pool.workerChoiceStrategyContext.workerChoiceStrategy
1997 ).roundWeights.length
2000 Number.isSafeInteger(
2001 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2002 pool.workerChoiceStrategyContext.workerChoiceStrategy
2006 // We need to clean up the resources after our test
2007 await pool.destroy()
2010 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
2011 const pool = new DynamicThreadPool(
2014 './tests/worker-files/thread/testWorker.mjs',
2016 workerChoiceStrategy:
2017 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2020 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
2021 const promises = new Set()
2022 const maxMultiplier = 2
2023 for (let i = 0; i < max * maxMultiplier; i++) {
2024 promises.add(pool.execute())
2026 await Promise.all(promises)
2027 for (const workerNode of pool.workerNodes) {
2028 expect(workerNode.usage).toStrictEqual({
2030 executed: expect.any(Number),
2034 sequentiallyStolen: 0,
2038 runTime: expect.objectContaining({
2039 history: expect.any(CircularArray)
2042 history: new CircularArray()
2046 history: new CircularArray()
2049 history: new CircularArray()
2053 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
2054 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
2059 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2060 pool.workerChoiceStrategyContext.workerChoiceStrategy
2064 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2065 pool.workerChoiceStrategyContext.workerChoiceStrategy
2069 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2070 pool.workerChoiceStrategyContext.workerChoiceStrategy
2074 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2075 pool.workerChoiceStrategyContext.workerChoiceStrategy
2076 ).previousWorkerNodeKey
2079 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2080 pool.workerChoiceStrategyContext.workerChoiceStrategy
2081 ).roundWeights.length
2084 Number.isSafeInteger(
2085 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2086 pool.workerChoiceStrategyContext.workerChoiceStrategy
2090 // We need to clean up the resources after our test
2091 await pool.destroy()
2094 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
2095 const workerChoiceStrategy =
2096 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2097 let pool = new FixedThreadPool(
2099 './tests/worker-files/thread/testWorker.mjs'
2102 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2103 workerChoiceStrategy
2107 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2108 workerChoiceStrategy
2112 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2113 workerChoiceStrategy
2117 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2118 workerChoiceStrategy
2119 ).previousWorkerNodeKey
2122 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2123 workerChoiceStrategy
2126 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
2128 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2129 pool.workerChoiceStrategyContext.workerChoiceStrategy
2133 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2134 pool.workerChoiceStrategyContext.workerChoiceStrategy
2138 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2139 pool.workerChoiceStrategyContext.workerChoiceStrategy
2143 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2144 pool.workerChoiceStrategyContext.workerChoiceStrategy
2145 ).previousWorkerNodeKey
2148 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2149 pool.workerChoiceStrategyContext.workerChoiceStrategy
2150 ).roundWeights.length
2153 Number.isSafeInteger(
2154 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2155 pool.workerChoiceStrategyContext.workerChoiceStrategy
2159 await pool.destroy()
2160 pool = new DynamicThreadPool(
2163 './tests/worker-files/thread/testWorker.mjs'
2166 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2167 workerChoiceStrategy
2171 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2172 workerChoiceStrategy
2176 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2177 workerChoiceStrategy
2181 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2182 workerChoiceStrategy
2183 ).previousWorkerNodeKey
2186 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2187 workerChoiceStrategy
2190 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
2192 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2193 pool.workerChoiceStrategyContext.workerChoiceStrategy
2197 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2198 pool.workerChoiceStrategyContext.workerChoiceStrategy
2202 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2203 pool.workerChoiceStrategyContext.workerChoiceStrategy
2207 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2208 pool.workerChoiceStrategyContext.workerChoiceStrategy
2209 ).previousWorkerNodeKey
2212 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2213 pool.workerChoiceStrategyContext.workerChoiceStrategy
2214 ).roundWeights.length
2217 Number.isSafeInteger(
2218 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2219 pool.workerChoiceStrategyContext.workerChoiceStrategy
2223 // We need to clean up the resources after our test
2224 await pool.destroy()
2227 it('Verify unknown strategy throw error', () => {
2230 new DynamicThreadPool(
2233 './tests/worker-files/thread/testWorker.mjs',
2234 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
2236 ).toThrow("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")