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