1 import { expect } from 'expect'
8 } from '../../../lib/index.cjs'
9 import { CircularArray } from '../../../lib/circular-array.cjs'
11 describe('Selection strategies test suite', () => {
15 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
16 expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN')
17 expect(WorkerChoiceStrategies.LEAST_USED).toBe('LEAST_USED')
18 expect(WorkerChoiceStrategies.LEAST_BUSY).toBe('LEAST_BUSY')
19 expect(WorkerChoiceStrategies.LEAST_ELU).toBe('LEAST_ELU')
20 expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE')
21 expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe(
22 'WEIGHTED_ROUND_ROBIN'
24 expect(WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN).toBe(
25 'INTERLEAVED_WEIGHTED_ROUND_ROBIN'
29 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
30 const pool = new DynamicThreadPool(
33 './tests/worker-files/thread/testWorker.mjs'
35 expect(pool.opts.workerChoiceStrategy).toBe(
36 WorkerChoiceStrategies.ROUND_ROBIN
38 // We need to clean up the resources after our test
42 it('Verify available strategies are taken at pool creation', async () => {
43 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
44 const pool = new FixedThreadPool(
46 './tests/worker-files/thread/testWorker.mjs',
47 { workerChoiceStrategy }
49 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
50 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
57 it('Verify available strategies can be set after pool creation', async () => {
58 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
59 const pool = new DynamicThreadPool(
62 './tests/worker-files/thread/testWorker.mjs'
64 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
65 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
66 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
71 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
72 const pool = new DynamicClusterPool(
75 './tests/worker-files/cluster/testWorker.cjs'
77 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
78 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
79 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
86 it('Verify available strategies default internals at pool creation', async () => {
87 const pool = new FixedThreadPool(
89 './tests/worker-files/thread/testWorker.mjs'
91 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
93 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
98 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
100 ).previousWorkerNodeKey
103 workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
106 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
108 ).workerNodeVirtualTaskRunTime
111 workerChoiceStrategy ===
112 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
115 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
117 ).workerNodeVirtualTaskRunTime
120 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
125 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
130 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
132 ).roundWeights.length
135 Number.isSafeInteger(
136 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
146 it('Verify ROUND_ROBIN strategy default policy', async () => {
147 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
148 let pool = new FixedThreadPool(
150 './tests/worker-files/thread/testWorker.mjs',
151 { workerChoiceStrategy }
153 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
154 dynamicWorkerUsage: false,
155 dynamicWorkerReady: true
158 pool = new DynamicThreadPool(
161 './tests/worker-files/thread/testWorker.mjs',
162 { workerChoiceStrategy }
164 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
165 dynamicWorkerUsage: false,
166 dynamicWorkerReady: true
168 // We need to clean up the resources after our test
172 it('Verify ROUND_ROBIN strategy default tasks statistics requirements', async () => {
173 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
174 let pool = new FixedThreadPool(
176 './tests/worker-files/thread/testWorker.mjs',
177 { workerChoiceStrategy }
180 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
199 pool = new DynamicThreadPool(
202 './tests/worker-files/thread/testWorker.mjs',
203 { workerChoiceStrategy }
206 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
224 // We need to clean up the resources after our test
228 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
229 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
230 const pool = new FixedThreadPool(
232 './tests/worker-files/thread/testWorker.mjs',
233 { workerChoiceStrategy }
235 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
236 const promises = new Set()
237 const maxMultiplier = 2
238 for (let i = 0; i < max * maxMultiplier; i++) {
239 promises.add(pool.execute())
241 await Promise.all(promises)
242 for (const workerNode of pool.workerNodes) {
243 expect(workerNode.usage).toStrictEqual({
245 executed: maxMultiplier,
249 sequentiallyStolen: 0,
254 history: new CircularArray()
257 history: new CircularArray()
261 history: new CircularArray()
264 history: new CircularArray()
270 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
271 pool.workerChoiceStrategyContext.workerChoiceStrategy
275 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
276 pool.workerChoiceStrategyContext.workerChoiceStrategy
277 ).previousWorkerNodeKey
278 ).toBe(pool.workerNodes.length - 1)
279 // We need to clean up the resources after our test
283 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
284 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
285 const pool = new DynamicThreadPool(
288 './tests/worker-files/thread/testWorker.mjs',
289 { workerChoiceStrategy }
291 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
292 const promises = new Set()
293 const maxMultiplier = 2
294 for (let i = 0; i < max * maxMultiplier; i++) {
295 promises.add(pool.execute())
297 await Promise.all(promises)
298 for (const workerNode of pool.workerNodes) {
299 expect(workerNode.usage).toStrictEqual({
301 executed: expect.any(Number),
305 sequentiallyStolen: 0,
310 history: new CircularArray()
313 history: new CircularArray()
317 history: new CircularArray()
320 history: new CircularArray()
324 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
325 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
330 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
331 pool.workerChoiceStrategyContext.workerChoiceStrategy
335 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
336 pool.workerChoiceStrategyContext.workerChoiceStrategy
337 ).previousWorkerNodeKey
338 ).toBe(pool.workerNodes.length - 1)
339 // We need to clean up the resources after our test
343 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
344 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
345 let pool = new FixedClusterPool(
347 './tests/worker-files/cluster/testWorker.cjs',
348 { workerChoiceStrategy }
350 let results = new Set()
351 for (let i = 0; i < max; i++) {
352 results.add(pool.workerNodes[pool.chooseWorkerNode()].info.id)
354 expect(results.size).toBe(max)
356 pool = new FixedThreadPool(
358 './tests/worker-files/thread/testWorker.mjs',
359 { workerChoiceStrategy }
362 for (let i = 0; i < max; i++) {
363 results.add(pool.workerNodes[pool.chooseWorkerNode()].info.id)
365 expect(results.size).toBe(max)
369 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
370 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
371 let pool = new FixedThreadPool(
373 './tests/worker-files/thread/testWorker.mjs',
374 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
377 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
378 pool.workerChoiceStrategyContext.workerChoiceStrategy
382 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
383 pool.workerChoiceStrategyContext.workerChoiceStrategy
384 ).previousWorkerNodeKey
386 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
388 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
389 pool.workerChoiceStrategyContext.workerChoiceStrategy
393 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
394 pool.workerChoiceStrategyContext.workerChoiceStrategy
395 ).previousWorkerNodeKey
398 pool = new DynamicThreadPool(
401 './tests/worker-files/thread/testWorker.mjs',
402 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
405 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
406 pool.workerChoiceStrategyContext.workerChoiceStrategy
410 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
411 pool.workerChoiceStrategyContext.workerChoiceStrategy
412 ).previousWorkerNodeKey
414 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
416 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
417 pool.workerChoiceStrategyContext.workerChoiceStrategy
421 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
422 pool.workerChoiceStrategyContext.workerChoiceStrategy
423 ).previousWorkerNodeKey
425 // We need to clean up the resources after our test
429 it('Verify LEAST_USED strategy default policy', async () => {
430 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
431 let pool = new FixedThreadPool(
433 './tests/worker-files/thread/testWorker.mjs',
434 { workerChoiceStrategy }
436 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
437 dynamicWorkerUsage: false,
438 dynamicWorkerReady: true
441 pool = new DynamicThreadPool(
444 './tests/worker-files/thread/testWorker.mjs',
445 { workerChoiceStrategy }
447 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
448 dynamicWorkerUsage: false,
449 dynamicWorkerReady: true
451 // We need to clean up the resources after our test
455 it('Verify LEAST_USED strategy default tasks statistics requirements', async () => {
456 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
457 let pool = new FixedThreadPool(
459 './tests/worker-files/thread/testWorker.mjs',
460 { workerChoiceStrategy }
463 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
482 pool = new DynamicThreadPool(
485 './tests/worker-files/thread/testWorker.mjs',
486 { workerChoiceStrategy }
489 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
507 // We need to clean up the resources after our test
511 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
512 const pool = new FixedThreadPool(
514 './tests/worker-files/thread/testWorker.mjs',
515 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
517 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
518 const promises = new Set()
519 const maxMultiplier = 2
520 for (let i = 0; i < max * maxMultiplier; i++) {
521 promises.add(pool.execute())
523 await Promise.all(promises)
524 for (const workerNode of pool.workerNodes) {
525 expect(workerNode.usage).toStrictEqual({
527 executed: expect.any(Number),
531 sequentiallyStolen: 0,
536 history: new CircularArray()
539 history: new CircularArray()
543 history: new CircularArray()
546 history: new CircularArray()
550 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
551 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
556 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
557 pool.workerChoiceStrategyContext.workerChoiceStrategy
559 ).toEqual(expect.any(Number))
561 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
562 pool.workerChoiceStrategyContext.workerChoiceStrategy
563 ).previousWorkerNodeKey
564 ).toEqual(expect.any(Number))
565 // We need to clean up the resources after our test
569 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
570 const pool = new DynamicThreadPool(
573 './tests/worker-files/thread/testWorker.mjs',
574 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
576 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
577 const promises = new Set()
578 const maxMultiplier = 2
579 for (let i = 0; i < max * maxMultiplier; i++) {
580 promises.add(pool.execute())
582 await Promise.all(promises)
583 for (const workerNode of pool.workerNodes) {
584 expect(workerNode.usage).toStrictEqual({
586 executed: expect.any(Number),
590 sequentiallyStolen: 0,
595 history: new CircularArray()
598 history: new CircularArray()
602 history: new CircularArray()
605 history: new CircularArray()
609 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
610 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
615 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
616 pool.workerChoiceStrategyContext.workerChoiceStrategy
618 ).toEqual(expect.any(Number))
620 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
621 pool.workerChoiceStrategyContext.workerChoiceStrategy
622 ).previousWorkerNodeKey
623 ).toEqual(expect.any(Number))
624 // We need to clean up the resources after our test
628 it('Verify LEAST_BUSY strategy default policy', async () => {
629 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
630 let pool = new FixedThreadPool(
632 './tests/worker-files/thread/testWorker.mjs',
633 { workerChoiceStrategy }
635 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
636 dynamicWorkerUsage: false,
637 dynamicWorkerReady: true
640 pool = new DynamicThreadPool(
643 './tests/worker-files/thread/testWorker.mjs',
644 { workerChoiceStrategy }
646 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
647 dynamicWorkerUsage: false,
648 dynamicWorkerReady: true
650 // We need to clean up the resources after our test
654 it('Verify LEAST_BUSY strategy default tasks statistics requirements', async () => {
655 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
656 let pool = new FixedThreadPool(
658 './tests/worker-files/thread/testWorker.mjs',
659 { workerChoiceStrategy }
662 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
681 pool = new DynamicThreadPool(
684 './tests/worker-files/thread/testWorker.mjs',
685 { workerChoiceStrategy }
688 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
706 // We need to clean up the resources after our test
710 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
711 const pool = new FixedThreadPool(
713 './tests/worker-files/thread/testWorker.mjs',
714 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
716 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
717 const promises = new Set()
718 const maxMultiplier = 2
719 for (let i = 0; i < max * maxMultiplier; i++) {
720 promises.add(pool.execute())
722 await Promise.all(promises)
723 for (const workerNode of pool.workerNodes) {
724 expect(workerNode.usage).toStrictEqual({
726 executed: expect.any(Number),
730 sequentiallyStolen: 0,
734 runTime: expect.objectContaining({
735 history: expect.any(CircularArray)
737 waitTime: expect.objectContaining({
738 history: expect.any(CircularArray)
742 history: new CircularArray()
745 history: new CircularArray()
749 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
750 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
753 if (workerNode.usage.runTime.aggregate == null) {
754 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
756 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
758 if (workerNode.usage.waitTime.aggregate == null) {
759 expect(workerNode.usage.waitTime.aggregate).toBeUndefined()
761 expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
765 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
766 pool.workerChoiceStrategyContext.workerChoiceStrategy
768 ).toEqual(expect.any(Number))
770 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
771 pool.workerChoiceStrategyContext.workerChoiceStrategy
772 ).previousWorkerNodeKey
773 ).toEqual(expect.any(Number))
774 // We need to clean up the resources after our test
778 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
779 const pool = new DynamicThreadPool(
782 './tests/worker-files/thread/testWorker.mjs',
783 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
785 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
786 const promises = new Set()
787 const maxMultiplier = 2
788 for (let i = 0; i < max * maxMultiplier; i++) {
789 promises.add(pool.execute())
791 await Promise.all(promises)
792 for (const workerNode of pool.workerNodes) {
793 expect(workerNode.usage).toStrictEqual({
795 executed: expect.any(Number),
799 sequentiallyStolen: 0,
803 runTime: expect.objectContaining({
804 history: expect.any(CircularArray)
806 waitTime: expect.objectContaining({
807 history: expect.any(CircularArray)
811 history: new CircularArray()
814 history: new CircularArray()
818 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
819 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
822 if (workerNode.usage.runTime.aggregate == null) {
823 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
825 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
827 if (workerNode.usage.waitTime.aggregate == null) {
828 expect(workerNode.usage.waitTime.aggregate).toBeUndefined()
830 expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
834 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
835 pool.workerChoiceStrategyContext.workerChoiceStrategy
837 ).toEqual(expect.any(Number))
839 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
840 pool.workerChoiceStrategyContext.workerChoiceStrategy
841 ).previousWorkerNodeKey
842 ).toEqual(expect.any(Number))
843 // We need to clean up the resources after our test
847 it('Verify LEAST_ELU strategy default policy', async () => {
848 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
849 let pool = new FixedThreadPool(
851 './tests/worker-files/thread/testWorker.mjs',
852 { workerChoiceStrategy }
854 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
855 dynamicWorkerUsage: false,
856 dynamicWorkerReady: true
859 pool = new DynamicThreadPool(
862 './tests/worker-files/thread/testWorker.mjs',
863 { workerChoiceStrategy }
865 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
866 dynamicWorkerUsage: false,
867 dynamicWorkerReady: true
869 // We need to clean up the resources after our test
873 it('Verify LEAST_ELU strategy default tasks statistics requirements', async () => {
874 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
875 let pool = new FixedThreadPool(
877 './tests/worker-files/thread/testWorker.mjs',
878 { workerChoiceStrategy }
881 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
900 pool = new DynamicThreadPool(
903 './tests/worker-files/thread/testWorker.mjs',
904 { workerChoiceStrategy }
907 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
925 // We need to clean up the resources after our test
929 it('Verify LEAST_ELU strategy can be run in a fixed pool', async () => {
930 const pool = new FixedThreadPool(
932 './tests/worker-files/thread/testWorker.mjs',
933 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_ELU }
935 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
936 const promises = new Set()
937 const maxMultiplier = 2
938 for (let i = 0; i < max * maxMultiplier; i++) {
939 promises.add(pool.execute())
941 await Promise.all(promises)
942 for (const workerNode of pool.workerNodes) {
943 expect(workerNode.usage).toStrictEqual({
945 executed: expect.any(Number),
949 sequentiallyStolen: 0,
954 history: new CircularArray()
957 history: new CircularArray()
959 elu: expect.objectContaining({
960 idle: expect.objectContaining({
961 history: expect.any(CircularArray)
963 active: expect.objectContaining({
964 history: expect.any(CircularArray)
968 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
969 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
972 if (workerNode.usage.elu.active.aggregate == null) {
973 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
975 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
977 if (workerNode.usage.elu.idle.aggregate == null) {
978 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
980 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
982 if (workerNode.usage.elu.utilization == null) {
983 expect(workerNode.usage.elu.utilization).toBeUndefined()
985 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
986 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
990 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
991 pool.workerChoiceStrategyContext.workerChoiceStrategy
993 ).toEqual(expect.any(Number))
995 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
996 pool.workerChoiceStrategyContext.workerChoiceStrategy
997 ).previousWorkerNodeKey
998 ).toEqual(expect.any(Number))
999 // We need to clean up the resources after our test
1000 await pool.destroy()
1003 it('Verify LEAST_ELU strategy can be run in a dynamic pool', async () => {
1004 const pool = new DynamicThreadPool(
1007 './tests/worker-files/thread/testWorker.mjs',
1008 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_ELU }
1010 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
1011 const promises = new Set()
1012 const maxMultiplier = 2
1013 for (let i = 0; i < max * maxMultiplier; i++) {
1014 promises.add(pool.execute())
1016 await Promise.all(promises)
1017 for (const workerNode of pool.workerNodes) {
1018 expect(workerNode.usage).toStrictEqual({
1020 executed: expect.any(Number),
1024 sequentiallyStolen: 0,
1029 history: new CircularArray()
1032 history: new CircularArray()
1034 elu: expect.objectContaining({
1035 idle: expect.objectContaining({
1036 history: expect.any(CircularArray)
1038 active: expect.objectContaining({
1039 history: expect.any(CircularArray)
1043 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1044 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1047 if (workerNode.usage.elu.active.aggregate == null) {
1048 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1050 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1052 if (workerNode.usage.elu.idle.aggregate == null) {
1053 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1055 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1057 if (workerNode.usage.elu.utilization == null) {
1058 expect(workerNode.usage.elu.utilization).toBeUndefined()
1060 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1061 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1065 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1066 pool.workerChoiceStrategyContext.workerChoiceStrategy
1068 ).toEqual(expect.any(Number))
1070 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1071 pool.workerChoiceStrategyContext.workerChoiceStrategy
1072 ).previousWorkerNodeKey
1073 ).toEqual(expect.any(Number))
1074 // We need to clean up the resources after our test
1075 await pool.destroy()
1078 it('Verify FAIR_SHARE strategy default policy', async () => {
1079 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
1080 let pool = new FixedThreadPool(
1082 './tests/worker-files/thread/testWorker.mjs',
1083 { workerChoiceStrategy }
1085 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1086 dynamicWorkerUsage: false,
1087 dynamicWorkerReady: true
1089 await pool.destroy()
1090 pool = new DynamicThreadPool(
1093 './tests/worker-files/thread/testWorker.mjs',
1094 { workerChoiceStrategy }
1096 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1097 dynamicWorkerUsage: false,
1098 dynamicWorkerReady: true
1100 // We need to clean up the resources after our test
1101 await pool.destroy()
1104 it('Verify FAIR_SHARE strategy default tasks statistics requirements', async () => {
1105 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
1106 let pool = new FixedThreadPool(
1108 './tests/worker-files/thread/testWorker.mjs',
1109 { workerChoiceStrategy }
1112 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1130 await pool.destroy()
1131 pool = new DynamicThreadPool(
1134 './tests/worker-files/thread/testWorker.mjs',
1135 { workerChoiceStrategy }
1138 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1156 // We need to clean up the resources after our test
1157 await pool.destroy()
1160 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
1161 const pool = new FixedThreadPool(
1163 './tests/worker-files/thread/testWorker.mjs',
1164 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
1166 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1167 const promises = new Set()
1168 const maxMultiplier = 2
1169 for (let i = 0; i < max * maxMultiplier; i++) {
1170 promises.add(pool.execute())
1172 await Promise.all(promises)
1173 for (const workerNode of pool.workerNodes) {
1174 expect(workerNode.usage).toStrictEqual({
1176 executed: expect.any(Number),
1180 sequentiallyStolen: 0,
1184 runTime: expect.objectContaining({
1185 history: expect.any(CircularArray)
1188 history: new CircularArray()
1190 elu: expect.objectContaining({
1191 idle: expect.objectContaining({
1192 history: expect.any(CircularArray)
1194 active: expect.objectContaining({
1195 history: expect.any(CircularArray)
1199 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1200 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1203 if (workerNode.usage.runTime.aggregate == null) {
1204 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1206 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1208 if (workerNode.usage.runTime.average == null) {
1209 expect(workerNode.usage.runTime.average).toBeUndefined()
1211 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1213 if (workerNode.usage.elu.active.aggregate == null) {
1214 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1216 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1218 if (workerNode.usage.elu.idle.aggregate == null) {
1219 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1221 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1223 if (workerNode.usage.elu.utilization == null) {
1224 expect(workerNode.usage.elu.utilization).toBeUndefined()
1226 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1227 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1229 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
1232 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1233 pool.workerChoiceStrategyContext.workerChoiceStrategy
1235 ).toEqual(expect.any(Number))
1237 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1238 pool.workerChoiceStrategyContext.workerChoiceStrategy
1239 ).previousWorkerNodeKey
1240 ).toEqual(expect.any(Number))
1241 // We need to clean up the resources after our test
1242 await pool.destroy()
1245 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
1246 const pool = new DynamicThreadPool(
1249 './tests/worker-files/thread/testWorker.mjs',
1250 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
1252 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1253 const promises = new Set()
1254 const maxMultiplier = 2
1255 for (let i = 0; i < max * maxMultiplier; i++) {
1256 promises.add(pool.execute())
1258 await Promise.all(promises)
1259 for (const workerNode of pool.workerNodes) {
1260 expect(workerNode.usage).toStrictEqual({
1262 executed: expect.any(Number),
1266 sequentiallyStolen: 0,
1270 runTime: expect.objectContaining({
1271 history: expect.any(CircularArray)
1274 history: new CircularArray()
1276 elu: expect.objectContaining({
1277 idle: expect.objectContaining({
1278 history: expect.any(CircularArray)
1280 active: expect.objectContaining({
1281 history: expect.any(CircularArray)
1285 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1286 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1289 if (workerNode.usage.runTime.aggregate == null) {
1290 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1292 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1294 if (workerNode.usage.runTime.average == null) {
1295 expect(workerNode.usage.runTime.average).toBeUndefined()
1297 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1299 if (workerNode.usage.elu.active.aggregate == null) {
1300 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1302 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1304 if (workerNode.usage.elu.idle.aggregate == null) {
1305 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1307 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1309 if (workerNode.usage.elu.utilization == null) {
1310 expect(workerNode.usage.elu.utilization).toBeUndefined()
1312 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1313 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1315 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
1318 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1319 pool.workerChoiceStrategyContext.workerChoiceStrategy
1321 ).toEqual(expect.any(Number))
1323 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1324 pool.workerChoiceStrategyContext.workerChoiceStrategy
1325 ).previousWorkerNodeKey
1326 ).toEqual(expect.any(Number))
1327 // We need to clean up the resources after our test
1328 await pool.destroy()
1331 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
1332 const pool = new DynamicThreadPool(
1335 './tests/worker-files/thread/testWorker.mjs',
1337 workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE,
1338 workerChoiceStrategyOptions: {
1339 runTime: { median: true }
1343 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1344 const promises = new Set()
1345 const maxMultiplier = 2
1346 for (let i = 0; i < max * maxMultiplier; i++) {
1347 promises.add(pool.execute())
1349 await Promise.all(promises)
1350 for (const workerNode of pool.workerNodes) {
1351 expect(workerNode.usage).toStrictEqual({
1353 executed: expect.any(Number),
1357 sequentiallyStolen: 0,
1361 runTime: expect.objectContaining({
1362 history: expect.any(CircularArray)
1365 history: new CircularArray()
1367 elu: expect.objectContaining({
1368 idle: expect.objectContaining({
1369 history: expect.any(CircularArray)
1371 active: expect.objectContaining({
1372 history: expect.any(CircularArray)
1376 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1377 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1380 if (workerNode.usage.runTime.aggregate == null) {
1381 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1383 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1385 if (workerNode.usage.runTime.median == null) {
1386 expect(workerNode.usage.runTime.median).toBeUndefined()
1388 expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
1390 if (workerNode.usage.elu.active.aggregate == null) {
1391 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1393 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1395 if (workerNode.usage.elu.idle.aggregate == null) {
1396 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1398 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1400 if (workerNode.usage.elu.utilization == null) {
1401 expect(workerNode.usage.elu.utilization).toBeUndefined()
1403 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1404 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1406 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
1409 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1410 pool.workerChoiceStrategyContext.workerChoiceStrategy
1412 ).toEqual(expect.any(Number))
1414 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1415 pool.workerChoiceStrategyContext.workerChoiceStrategy
1416 ).previousWorkerNodeKey
1417 ).toEqual(expect.any(Number))
1418 // We need to clean up the resources after our test
1419 await pool.destroy()
1422 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
1423 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
1424 let pool = new FixedThreadPool(
1426 './tests/worker-files/thread/testWorker.mjs'
1428 for (const workerNode of pool.workerNodes) {
1429 workerNode.strategyData = {
1430 virtualTaskEndTimestamp: performance.now()
1433 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1434 for (const workerNode of pool.workerNodes) {
1435 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeUndefined()
1437 await pool.destroy()
1438 pool = new DynamicThreadPool(
1441 './tests/worker-files/thread/testWorker.mjs'
1443 for (const workerNode of pool.workerNodes) {
1444 workerNode.strategyData = {
1445 virtualTaskEndTimestamp: performance.now()
1448 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1449 for (const workerNode of pool.workerNodes) {
1450 expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeUndefined()
1452 // We need to clean up the resources after our test
1453 await pool.destroy()
1456 it('Verify WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1457 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1458 let pool = new FixedThreadPool(
1460 './tests/worker-files/thread/testWorker.mjs',
1461 { workerChoiceStrategy }
1463 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1464 dynamicWorkerUsage: false,
1465 dynamicWorkerReady: true
1467 await pool.destroy()
1468 pool = new DynamicThreadPool(
1471 './tests/worker-files/thread/testWorker.mjs',
1472 { workerChoiceStrategy }
1474 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1475 dynamicWorkerUsage: false,
1476 dynamicWorkerReady: true
1478 // We need to clean up the resources after our test
1479 await pool.destroy()
1482 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
1483 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1484 let pool = new FixedThreadPool(
1486 './tests/worker-files/thread/testWorker.mjs',
1487 { workerChoiceStrategy }
1490 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1508 await pool.destroy()
1509 pool = new DynamicThreadPool(
1512 './tests/worker-files/thread/testWorker.mjs',
1513 { workerChoiceStrategy }
1516 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1534 // We need to clean up the resources after our test
1535 await pool.destroy()
1538 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1539 const pool = new FixedThreadPool(
1541 './tests/worker-files/thread/testWorker.mjs',
1542 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1544 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1545 const promises = new Set()
1546 const maxMultiplier = 2
1547 for (let i = 0; i < max * maxMultiplier; i++) {
1548 promises.add(pool.execute())
1550 await Promise.all(promises)
1551 for (const workerNode of pool.workerNodes) {
1552 expect(workerNode.usage).toStrictEqual({
1554 executed: expect.any(Number),
1558 sequentiallyStolen: 0,
1562 runTime: expect.objectContaining({
1563 history: expect.any(CircularArray)
1566 history: new CircularArray()
1570 history: new CircularArray()
1573 history: new CircularArray()
1577 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1578 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1581 if (workerNode.usage.runTime.aggregate == null) {
1582 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1584 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1586 if (workerNode.usage.runTime.average == null) {
1587 expect(workerNode.usage.runTime.average).toBeUndefined()
1589 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1593 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1594 pool.workerChoiceStrategyContext.workerChoiceStrategy
1598 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1599 pool.workerChoiceStrategyContext.workerChoiceStrategy
1600 ).previousWorkerNodeKey
1603 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1604 pool.workerChoiceStrategyContext.workerChoiceStrategy
1605 ).workerNodeVirtualTaskRunTime
1606 ).toBeGreaterThanOrEqual(0)
1607 // We need to clean up the resources after our test
1608 await pool.destroy()
1611 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1612 const pool = new DynamicThreadPool(
1615 './tests/worker-files/thread/testWorker.mjs',
1616 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1618 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1619 const promises = new Set()
1620 const maxMultiplier = 2
1621 for (let i = 0; i < max * maxMultiplier; i++) {
1622 promises.add(pool.execute())
1624 await Promise.all(promises)
1625 for (const workerNode of pool.workerNodes) {
1626 expect(workerNode.usage).toStrictEqual({
1628 executed: expect.any(Number),
1632 sequentiallyStolen: 0,
1636 runTime: expect.objectContaining({
1637 history: expect.any(CircularArray)
1640 history: new CircularArray()
1644 history: new CircularArray()
1647 history: new CircularArray()
1651 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1652 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1655 if (workerNode.usage.runTime.aggregate == null) {
1656 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1658 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1660 if (workerNode.usage.runTime.average == null) {
1661 expect(workerNode.usage.runTime.average).toBeUndefined()
1663 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1667 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1668 pool.workerChoiceStrategyContext.workerChoiceStrategy
1672 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1673 pool.workerChoiceStrategyContext.workerChoiceStrategy
1674 ).previousWorkerNodeKey
1677 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1678 pool.workerChoiceStrategyContext.workerChoiceStrategy
1679 ).workerNodeVirtualTaskRunTime
1680 ).toBeGreaterThanOrEqual(0)
1681 // We need to clean up the resources after our test
1682 await pool.destroy()
1685 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
1686 const pool = new DynamicThreadPool(
1689 './tests/worker-files/thread/testWorker.mjs',
1691 workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN,
1692 workerChoiceStrategyOptions: {
1693 runTime: { median: true }
1697 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1698 const promises = new Set()
1699 const maxMultiplier = 2
1700 for (let i = 0; i < max * maxMultiplier; i++) {
1701 promises.add(pool.execute())
1703 await Promise.all(promises)
1704 for (const workerNode of pool.workerNodes) {
1705 expect(workerNode.usage).toStrictEqual({
1707 executed: expect.any(Number),
1711 sequentiallyStolen: 0,
1715 runTime: expect.objectContaining({
1716 history: expect.any(CircularArray)
1719 history: new CircularArray()
1723 history: new CircularArray()
1726 history: new CircularArray()
1730 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1731 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1734 if (workerNode.usage.runTime.aggregate == null) {
1735 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1737 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1739 if (workerNode.usage.runTime.median == null) {
1740 expect(workerNode.usage.runTime.median).toBeUndefined()
1742 expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
1746 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1747 pool.workerChoiceStrategyContext.workerChoiceStrategy
1751 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1752 pool.workerChoiceStrategyContext.workerChoiceStrategy
1753 ).previousWorkerNodeKey
1756 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1757 pool.workerChoiceStrategyContext.workerChoiceStrategy
1758 ).workerNodeVirtualTaskRunTime
1759 ).toBeGreaterThanOrEqual(0)
1760 // We need to clean up the resources after our test
1761 await pool.destroy()
1764 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1765 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1766 let pool = new FixedThreadPool(
1768 './tests/worker-files/thread/testWorker.mjs'
1771 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1772 workerChoiceStrategy
1776 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1777 workerChoiceStrategy
1778 ).previousWorkerNodeKey
1781 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1782 workerChoiceStrategy
1783 ).workerNodeVirtualTaskRunTime
1785 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1787 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1788 pool.workerChoiceStrategyContext.workerChoiceStrategy
1792 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1793 pool.workerChoiceStrategyContext.workerChoiceStrategy
1794 ).previousWorkerNodeKey
1797 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1798 pool.workerChoiceStrategyContext.workerChoiceStrategy
1799 ).workerNodeVirtualTaskRunTime
1801 await pool.destroy()
1802 pool = new DynamicThreadPool(
1805 './tests/worker-files/thread/testWorker.mjs'
1808 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1809 workerChoiceStrategy
1813 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1814 workerChoiceStrategy
1815 ).previousWorkerNodeKey
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 ).workerNodeVirtualTaskRunTime
1838 // We need to clean up the resources after our test
1839 await pool.destroy()
1842 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1843 const workerChoiceStrategy =
1844 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1845 let pool = new FixedThreadPool(
1847 './tests/worker-files/thread/testWorker.mjs',
1848 { workerChoiceStrategy }
1850 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1851 dynamicWorkerUsage: false,
1852 dynamicWorkerReady: true
1854 await pool.destroy()
1855 pool = new DynamicThreadPool(
1858 './tests/worker-files/thread/testWorker.mjs',
1859 { workerChoiceStrategy }
1861 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1862 dynamicWorkerUsage: false,
1863 dynamicWorkerReady: true
1865 // We need to clean up the resources after our test
1866 await pool.destroy()
1869 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
1870 const workerChoiceStrategy =
1871 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1872 let pool = new FixedThreadPool(
1874 './tests/worker-files/thread/testWorker.mjs',
1875 { workerChoiceStrategy }
1878 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1896 await pool.destroy()
1897 pool = new DynamicThreadPool(
1900 './tests/worker-files/thread/testWorker.mjs',
1901 { workerChoiceStrategy }
1904 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1922 // We need to clean up the resources after our test
1923 await pool.destroy()
1926 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1927 const pool = new FixedThreadPool(
1929 './tests/worker-files/thread/testWorker.mjs',
1931 workerChoiceStrategy:
1932 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1935 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1936 const promises = new Set()
1937 const maxMultiplier = 2
1938 for (let i = 0; i < max * maxMultiplier; i++) {
1939 promises.add(pool.execute())
1941 await Promise.all(promises)
1942 for (const workerNode of pool.workerNodes) {
1943 expect(workerNode.usage).toStrictEqual({
1945 executed: expect.any(Number),
1949 sequentiallyStolen: 0,
1953 runTime: expect.objectContaining({
1954 history: expect.any(CircularArray)
1957 history: new CircularArray()
1961 history: new CircularArray()
1964 history: new CircularArray()
1968 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1969 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1974 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1975 pool.workerChoiceStrategyContext.workerChoiceStrategy
1979 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1980 pool.workerChoiceStrategyContext.workerChoiceStrategy
1984 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1985 pool.workerChoiceStrategyContext.workerChoiceStrategy
1989 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1990 pool.workerChoiceStrategyContext.workerChoiceStrategy
1991 ).previousWorkerNodeKey
1994 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1995 pool.workerChoiceStrategyContext.workerChoiceStrategy
1996 ).roundWeights.length
1999 Number.isSafeInteger(
2000 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2001 pool.workerChoiceStrategyContext.workerChoiceStrategy
2005 // We need to clean up the resources after our test
2006 await pool.destroy()
2009 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
2010 const pool = new DynamicThreadPool(
2013 './tests/worker-files/thread/testWorker.mjs',
2015 workerChoiceStrategy:
2016 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2019 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
2020 const promises = new Set()
2021 const maxMultiplier = 2
2022 for (let i = 0; i < max * maxMultiplier; i++) {
2023 promises.add(pool.execute())
2025 await Promise.all(promises)
2026 for (const workerNode of pool.workerNodes) {
2027 expect(workerNode.usage).toStrictEqual({
2029 executed: expect.any(Number),
2033 sequentiallyStolen: 0,
2037 runTime: expect.objectContaining({
2038 history: expect.any(CircularArray)
2041 history: new CircularArray()
2045 history: new CircularArray()
2048 history: new CircularArray()
2052 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
2053 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
2058 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2059 pool.workerChoiceStrategyContext.workerChoiceStrategy
2063 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2064 pool.workerChoiceStrategyContext.workerChoiceStrategy
2068 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2069 pool.workerChoiceStrategyContext.workerChoiceStrategy
2073 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2074 pool.workerChoiceStrategyContext.workerChoiceStrategy
2075 ).previousWorkerNodeKey
2078 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2079 pool.workerChoiceStrategyContext.workerChoiceStrategy
2080 ).roundWeights.length
2083 Number.isSafeInteger(
2084 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2085 pool.workerChoiceStrategyContext.workerChoiceStrategy
2089 // We need to clean up the resources after our test
2090 await pool.destroy()
2093 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
2094 const workerChoiceStrategy =
2095 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2096 let pool = new FixedThreadPool(
2098 './tests/worker-files/thread/testWorker.mjs'
2101 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2102 workerChoiceStrategy
2106 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2107 workerChoiceStrategy
2111 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2112 workerChoiceStrategy
2116 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2117 workerChoiceStrategy
2118 ).previousWorkerNodeKey
2121 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2122 workerChoiceStrategy
2125 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
2127 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2128 pool.workerChoiceStrategyContext.workerChoiceStrategy
2132 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2133 pool.workerChoiceStrategyContext.workerChoiceStrategy
2137 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2138 pool.workerChoiceStrategyContext.workerChoiceStrategy
2142 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2143 pool.workerChoiceStrategyContext.workerChoiceStrategy
2144 ).previousWorkerNodeKey
2147 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2148 pool.workerChoiceStrategyContext.workerChoiceStrategy
2149 ).roundWeights.length
2152 Number.isSafeInteger(
2153 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2154 pool.workerChoiceStrategyContext.workerChoiceStrategy
2158 await pool.destroy()
2159 pool = new DynamicThreadPool(
2162 './tests/worker-files/thread/testWorker.mjs'
2165 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2166 workerChoiceStrategy
2170 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2171 workerChoiceStrategy
2175 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2176 workerChoiceStrategy
2180 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2181 workerChoiceStrategy
2182 ).previousWorkerNodeKey
2185 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2186 workerChoiceStrategy
2189 pool.setWorkerChoiceStrategy(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
2206 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2207 pool.workerChoiceStrategyContext.workerChoiceStrategy
2208 ).previousWorkerNodeKey
2211 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2212 pool.workerChoiceStrategyContext.workerChoiceStrategy
2213 ).roundWeights.length
2216 Number.isSafeInteger(
2217 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2218 pool.workerChoiceStrategyContext.workerChoiceStrategy
2222 // We need to clean up the resources after our test
2223 await pool.destroy()
2226 it('Verify unknown strategy throw error', () => {
2229 new DynamicThreadPool(
2232 './tests/worker-files/thread/testWorker.mjs',
2233 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
2235 ).toThrow("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")