fix: fix build after merge with main branch
[poolifier.git] / tests / pools / selection-strategies / selection-strategies.test.js
1 const { expect } = require('expect')
2 const {
3 WorkerChoiceStrategies,
4 DynamicThreadPool,
5 FixedThreadPool,
6 FixedClusterPool
7 } = require('../../../lib')
8 const { CircularArray } = require('../../../lib/circular-array')
9 const TestUtils = require('../../test-utils')
10
11 describe('Selection strategies test suite', () => {
12 const min = 0
13 const max = 3
14
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'
23 )
24 expect(WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN).toBe(
25 'INTERLEAVED_WEIGHTED_ROUND_ROBIN'
26 )
27 })
28
29 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
30 const pool = new DynamicThreadPool(
31 min,
32 max,
33 './tests/worker-files/thread/testWorker.js'
34 )
35 expect(pool.opts.workerChoiceStrategy).toBe(
36 WorkerChoiceStrategies.ROUND_ROBIN
37 )
38 // We need to clean up the resources after our test
39 await pool.destroy()
40 })
41
42 it('Verify available strategies are taken at pool creation', async () => {
43 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
44 const pool = new FixedThreadPool(
45 max,
46 './tests/worker-files/thread/testWorker.js',
47 { workerChoiceStrategy }
48 )
49 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
50 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
51 workerChoiceStrategy
52 )
53 await pool.destroy()
54 }
55 })
56
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(
60 min,
61 max,
62 './tests/worker-files/thread/testWorker.js'
63 )
64 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
65 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
66 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
67 workerChoiceStrategy
68 )
69 await pool.destroy()
70 }
71 })
72
73 it('Verify available strategies default internals at pool creation', async () => {
74 const pool = new FixedThreadPool(
75 max,
76 './tests/worker-files/thread/testWorker.js'
77 )
78 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
79 if (workerChoiceStrategy === WorkerChoiceStrategies.ROUND_ROBIN) {
80 expect(
81 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
82 workerChoiceStrategy
83 ).nextWorkerNodeId
84 ).toBe(0)
85 } else if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) {
86 expect(
87 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
88 workerChoiceStrategy
89 ).workersVirtualTaskEndTimestamp
90 ).toBeInstanceOf(Array)
91 expect(
92 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
93 workerChoiceStrategy
94 ).workersVirtualTaskEndTimestamp.length
95 ).toBe(0)
96 } else if (
97 workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
98 ) {
99 expect(
100 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
101 workerChoiceStrategy
102 ).currentWorkerNodeId
103 ).toBe(0)
104 expect(
105 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
106 workerChoiceStrategy
107 ).defaultWorkerWeight
108 ).toBeGreaterThan(0)
109 expect(
110 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
111 workerChoiceStrategy
112 ).workerVirtualTaskRunTime
113 ).toBe(0)
114 }
115 }
116 await pool.destroy()
117 })
118
119 it('Verify ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
120 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
121 let pool = new FixedThreadPool(
122 max,
123 './tests/worker-files/thread/testWorker.js',
124 { workerChoiceStrategy }
125 )
126 expect(
127 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
128 ).toStrictEqual({
129 runTime: {
130 aggregate: false,
131 average: false,
132 median: false
133 },
134 waitTime: {
135 aggregate: false,
136 average: false,
137 median: false
138 },
139 elu: false
140 })
141 await pool.destroy()
142 pool = new DynamicThreadPool(
143 min,
144 max,
145 './tests/worker-files/thread/testWorker.js',
146 { workerChoiceStrategy }
147 )
148 expect(
149 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
150 ).toStrictEqual({
151 runTime: {
152 aggregate: false,
153 average: false,
154 median: false
155 },
156 waitTime: {
157 aggregate: false,
158 average: false,
159 median: false
160 },
161 elu: false
162 })
163 // We need to clean up the resources after our test
164 await pool.destroy()
165 })
166
167 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
168 const pool = new FixedThreadPool(
169 max,
170 './tests/worker-files/thread/testWorker.js',
171 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
172 )
173 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
174 const promises = new Set()
175 const maxMultiplier = 2
176 for (let i = 0; i < max * maxMultiplier; i++) {
177 promises.add(pool.execute())
178 }
179 await Promise.all(promises)
180 for (const workerNode of pool.workerNodes) {
181 expect(workerNode.workerUsage).toStrictEqual({
182 tasks: {
183 executed: maxMultiplier,
184 executing: 0,
185 queued: 0,
186 failed: 0
187 },
188 runTime: {
189 aggregate: 0,
190 average: 0,
191 median: 0,
192 history: expect.any(CircularArray)
193 },
194 waitTime: {
195 aggregate: 0,
196 average: 0,
197 median: 0,
198 history: expect.any(CircularArray)
199 },
200 elu: undefined
201 })
202 }
203 expect(
204 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
205 WorkerChoiceStrategies.ROUND_ROBIN
206 ).nextWorkerNodeId
207 ).toBe(0)
208 // We need to clean up the resources after our test
209 await pool.destroy()
210 })
211
212 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
213 const pool = new DynamicThreadPool(
214 min,
215 max,
216 './tests/worker-files/thread/testWorker.js',
217 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
218 )
219 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
220 const promises = new Set()
221 const maxMultiplier = 2
222 for (let i = 0; i < max * maxMultiplier; i++) {
223 promises.add(pool.execute())
224 }
225 await Promise.all(promises)
226 for (const workerNode of pool.workerNodes) {
227 expect(workerNode.workerUsage).toStrictEqual({
228 tasks: {
229 executed: maxMultiplier,
230 executing: 0,
231 queued: 0,
232 failed: 0
233 },
234 runTime: {
235 aggregate: 0,
236 average: 0,
237 median: 0,
238 history: expect.any(CircularArray)
239 },
240 waitTime: {
241 aggregate: 0,
242 average: 0,
243 median: 0,
244 history: expect.any(CircularArray)
245 },
246 elu: undefined
247 })
248 }
249 expect(
250 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
251 WorkerChoiceStrategies.ROUND_ROBIN
252 ).nextWorkerNodeId
253 ).toBe(0)
254 // We need to clean up the resources after our test
255 await pool.destroy()
256 })
257
258 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
259 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
260 let pool = new FixedClusterPool(
261 max,
262 './tests/worker-files/cluster/testWorker.js',
263 { workerChoiceStrategy }
264 )
265 let results = new Set()
266 for (let i = 0; i < max; i++) {
267 results.add(pool.workerNodes[pool.chooseWorkerNode()].worker.id)
268 }
269 expect(results.size).toBe(max)
270 await pool.destroy()
271 pool = new FixedThreadPool(
272 max,
273 './tests/worker-files/thread/testWorker.js',
274 { workerChoiceStrategy }
275 )
276 results = new Set()
277 for (let i = 0; i < max; i++) {
278 results.add(pool.workerNodes[pool.chooseWorkerNode()].worker.threadId)
279 }
280 expect(results.size).toBe(max)
281 await pool.destroy()
282 })
283
284 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
285 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
286 let pool = new FixedThreadPool(
287 max,
288 './tests/worker-files/thread/testWorker.js',
289 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
290 )
291 expect(
292 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
293 workerChoiceStrategy
294 ).nextWorkerNodeId
295 ).toBeDefined()
296 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
297 expect(
298 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
299 pool.workerChoiceStrategyContext.workerChoiceStrategy
300 ).nextWorkerNodeId
301 ).toBe(0)
302 await pool.destroy()
303 pool = new DynamicThreadPool(
304 min,
305 max,
306 './tests/worker-files/thread/testWorker.js',
307 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
308 )
309 expect(
310 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
311 workerChoiceStrategy
312 ).nextWorkerNodeId
313 ).toBeDefined()
314 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
315 expect(
316 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
317 pool.workerChoiceStrategyContext.workerChoiceStrategy
318 ).nextWorkerNodeId
319 ).toBe(0)
320 // We need to clean up the resources after our test
321 await pool.destroy()
322 })
323
324 it('Verify LEAST_USED strategy default tasks usage statistics requirements', async () => {
325 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
326 let pool = new FixedThreadPool(
327 max,
328 './tests/worker-files/thread/testWorker.js',
329 { workerChoiceStrategy }
330 )
331 expect(
332 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
333 ).toStrictEqual({
334 runTime: {
335 aggregate: false,
336 average: false,
337 median: false
338 },
339 waitTime: {
340 aggregate: false,
341 average: false,
342 median: false
343 },
344 elu: false
345 })
346 await pool.destroy()
347 pool = new DynamicThreadPool(
348 min,
349 max,
350 './tests/worker-files/thread/testWorker.js',
351 { workerChoiceStrategy }
352 )
353 expect(
354 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
355 ).toStrictEqual({
356 runTime: {
357 aggregate: false,
358 average: false,
359 median: false
360 },
361 waitTime: {
362 aggregate: false,
363 average: false,
364 median: false
365 },
366 elu: false
367 })
368 // We need to clean up the resources after our test
369 await pool.destroy()
370 })
371
372 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
373 const pool = new FixedThreadPool(
374 max,
375 './tests/worker-files/thread/testWorker.js',
376 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
377 )
378 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
379 const promises = new Set()
380 const maxMultiplier = 2
381 for (let i = 0; i < max * maxMultiplier; i++) {
382 promises.add(pool.execute())
383 }
384 await Promise.all(promises)
385 for (const workerNode of pool.workerNodes) {
386 expect(workerNode.workerUsage).toStrictEqual({
387 tasks: {
388 executed: maxMultiplier,
389 executing: 0,
390 queued: 0,
391 failed: 0
392 },
393 runTime: {
394 aggregate: 0,
395 average: 0,
396 median: 0,
397 history: expect.any(CircularArray)
398 },
399 waitTime: {
400 aggregate: 0,
401 average: 0,
402 median: 0,
403 history: expect.any(CircularArray)
404 },
405 elu: undefined
406 })
407 }
408 // We need to clean up the resources after our test
409 await pool.destroy()
410 })
411
412 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
413 const pool = new DynamicThreadPool(
414 min,
415 max,
416 './tests/worker-files/thread/testWorker.js',
417 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
418 )
419 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
420 const promises = new Set()
421 const maxMultiplier = 2
422 for (let i = 0; i < max * maxMultiplier; i++) {
423 promises.add(pool.execute())
424 }
425 await Promise.all(promises)
426 for (const workerNode of pool.workerNodes) {
427 expect(workerNode.workerUsage).toStrictEqual({
428 tasks: {
429 executed: maxMultiplier,
430 executing: 0,
431 queued: 0,
432 failed: 0
433 },
434 runTime: {
435 aggregate: 0,
436 average: 0,
437 median: 0,
438 history: expect.any(CircularArray)
439 },
440 waitTime: {
441 aggregate: 0,
442 average: 0,
443 median: 0,
444 history: expect.any(CircularArray)
445 },
446
447 elu: undefined
448 })
449 }
450 // We need to clean up the resources after our test
451 await pool.destroy()
452 })
453
454 it('Verify LEAST_BUSY strategy default tasks usage statistics requirements', async () => {
455 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
456 let pool = new FixedThreadPool(
457 max,
458 './tests/worker-files/thread/testWorker.js',
459 { workerChoiceStrategy }
460 )
461 expect(
462 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
463 ).toStrictEqual({
464 runTime: {
465 aggregate: true,
466 average: false,
467 median: false
468 },
469 waitTime: {
470 aggregate: true,
471 average: false,
472 median: false
473 },
474 elu: false
475 })
476 await pool.destroy()
477 pool = new DynamicThreadPool(
478 min,
479 max,
480 './tests/worker-files/thread/testWorker.js',
481 { workerChoiceStrategy }
482 )
483 expect(
484 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
485 ).toStrictEqual({
486 runTime: {
487 aggregate: true,
488 average: false,
489 median: false
490 },
491 waitTime: {
492 aggregate: true,
493 average: false,
494 median: false
495 },
496 elu: false
497 })
498 // We need to clean up the resources after our test
499 await pool.destroy()
500 })
501
502 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
503 const pool = new FixedThreadPool(
504 max,
505 './tests/worker-files/thread/testWorker.js',
506 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
507 )
508 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
509 const promises = new Set()
510 const maxMultiplier = 2
511 for (let i = 0; i < max * maxMultiplier; i++) {
512 promises.add(pool.execute())
513 }
514 await Promise.all(promises)
515 for (const workerNode of pool.workerNodes) {
516 expect(workerNode.workerUsage).toStrictEqual({
517 tasks: {
518 executed: expect.any(Number),
519 executing: 0,
520 queued: 0,
521 failed: 0
522 },
523 runTime: {
524 aggregate: expect.any(Number),
525 average: 0,
526 median: 0,
527 history: expect.any(CircularArray)
528 },
529 waitTime: {
530 aggregate: expect.any(Number),
531 average: 0,
532 median: 0,
533 history: expect.any(CircularArray)
534 },
535 elu: undefined
536 })
537 expect(workerNode.workerUsage.tasks.executed).toBeGreaterThanOrEqual(0)
538 expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
539 max * maxMultiplier
540 )
541 expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThanOrEqual(0)
542 expect(workerNode.workerUsage.waitTime.aggregate).toBeGreaterThanOrEqual(
543 0
544 )
545 }
546 // We need to clean up the resources after our test
547 await pool.destroy()
548 })
549
550 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
551 const pool = new DynamicThreadPool(
552 min,
553 max,
554 './tests/worker-files/thread/testWorker.js',
555 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
556 )
557 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
558 const promises = new Set()
559 const maxMultiplier = 2
560 for (let i = 0; i < max * maxMultiplier; i++) {
561 promises.add(pool.execute())
562 }
563 await Promise.all(promises)
564 for (const workerNode of pool.workerNodes) {
565 expect(workerNode.workerUsage).toStrictEqual({
566 tasks: {
567 executed: expect.any(Number),
568 executing: 0,
569 queued: 0,
570 failed: 0
571 },
572 runTime: {
573 aggregate: expect.any(Number),
574 average: 0,
575 median: 0,
576 history: expect.any(CircularArray)
577 },
578 waitTime: {
579 aggregate: expect.any(Number),
580 average: 0,
581 median: 0,
582 history: expect.any(CircularArray)
583 },
584 elu: undefined
585 })
586 expect(workerNode.workerUsage.tasks.executed).toBeGreaterThan(0)
587 expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
588 max * maxMultiplier
589 )
590 expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
591 expect(workerNode.workerUsage.waitTime.aggregate).toBeGreaterThan(0)
592 }
593 // We need to clean up the resources after our test
594 await pool.destroy()
595 })
596
597 it('Verify LEAST_ELU strategy default tasks usage statistics requirements', async () => {
598 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
599 let pool = new FixedThreadPool(
600 max,
601 './tests/worker-files/thread/testWorker.js',
602 { workerChoiceStrategy }
603 )
604 expect(
605 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
606 ).toStrictEqual({
607 runTime: {
608 aggregate: false,
609 average: false,
610 median: false
611 },
612 waitTime: {
613 aggregate: false,
614 average: false,
615 median: false
616 },
617 elu: true
618 })
619 await pool.destroy()
620 pool = new DynamicThreadPool(
621 min,
622 max,
623 './tests/worker-files/thread/testWorker.js',
624 { workerChoiceStrategy }
625 )
626 expect(
627 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
628 ).toStrictEqual({
629 runTime: {
630 aggregate: false,
631 average: false,
632 median: false
633 },
634 waitTime: {
635 aggregate: false,
636 average: false,
637 median: false
638 },
639 elu: true
640 })
641 // We need to clean up the resources after our test
642 await pool.destroy()
643 })
644
645 it('Verify LEAST_ELU strategy can be run in a fixed pool', async () => {
646 const pool = new FixedThreadPool(
647 max,
648 './tests/worker-files/thread/testWorker.js',
649 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_ELU }
650 )
651 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
652 const maxMultiplier = 2
653 for (let i = 0; i < max * maxMultiplier; i++) {
654 await pool.execute()
655 if (i !== max * maxMultiplier - 1) await TestUtils.sleep(500)
656 }
657 for (const workerNode of pool.workerNodes) {
658 const expectedWorkerUsage = {
659 tasks: {
660 executed: expect.any(Number),
661 executing: 0,
662 queued: 0,
663 failed: 0
664 },
665 runTime: {
666 aggregate: 0,
667 average: 0,
668 median: 0,
669 history: expect.any(CircularArray)
670 },
671 waitTime: {
672 aggregate: 0,
673 average: 0,
674 median: 0,
675 history: expect.any(CircularArray)
676 }
677 }
678 if (workerNode.workerUsage.elu === undefined) {
679 expect(workerNode.workerUsage).toStrictEqual({
680 ...expectedWorkerUsage,
681 elu: undefined
682 })
683 } else {
684 expect(workerNode.workerUsage).toStrictEqual({
685 ...expectedWorkerUsage,
686 elu: {
687 active: expect.any(Number),
688 idle: 0,
689 utilization: 1
690 }
691 })
692 }
693 expect(workerNode.workerUsage.tasks.executed).toBeGreaterThanOrEqual(0)
694 expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
695 max * maxMultiplier
696 )
697 }
698 // We need to clean up the resources after our test
699 await pool.destroy()
700 })
701
702 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
703 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
704 let pool = new FixedThreadPool(
705 max,
706 './tests/worker-files/thread/testWorker.js',
707 { workerChoiceStrategy }
708 )
709 expect(
710 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
711 ).toStrictEqual({
712 runTime: {
713 aggregate: true,
714 average: true,
715 median: false
716 },
717 waitTime: {
718 aggregate: false,
719 average: false,
720 median: false
721 },
722 elu: false
723 })
724 await pool.destroy()
725 pool = new DynamicThreadPool(
726 min,
727 max,
728 './tests/worker-files/thread/testWorker.js',
729 { workerChoiceStrategy }
730 )
731 expect(
732 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
733 ).toStrictEqual({
734 runTime: {
735 aggregate: true,
736 average: true,
737 median: false
738 },
739 waitTime: {
740 aggregate: false,
741 average: false,
742 median: false
743 },
744 elu: false
745 })
746 // We need to clean up the resources after our test
747 await pool.destroy()
748 })
749
750 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
751 const pool = new FixedThreadPool(
752 max,
753 './tests/worker-files/thread/testWorker.js',
754 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
755 )
756 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
757 const promises = new Set()
758 const maxMultiplier = 2
759 for (let i = 0; i < max * maxMultiplier; i++) {
760 promises.add(pool.execute())
761 }
762 await Promise.all(promises)
763 for (const workerNode of pool.workerNodes) {
764 expect(workerNode.workerUsage).toStrictEqual({
765 tasks: {
766 executed: maxMultiplier,
767 executing: 0,
768 queued: 0,
769 failed: 0
770 },
771 runTime: {
772 aggregate: expect.any(Number),
773 average: expect.any(Number),
774 median: 0,
775 history: expect.any(CircularArray)
776 },
777 waitTime: {
778 aggregate: 0,
779 average: 0,
780 median: 0,
781 history: expect.any(CircularArray)
782 },
783 elu: undefined
784 })
785 expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
786 expect(workerNode.workerUsage.runTime.average).toBeGreaterThan(0)
787 }
788 expect(
789 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
790 pool.workerChoiceStrategyContext.workerChoiceStrategy
791 ).workersVirtualTaskEndTimestamp.length
792 ).toBe(pool.workerNodes.length)
793 // We need to clean up the resources after our test
794 await pool.destroy()
795 })
796
797 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
798 const pool = new DynamicThreadPool(
799 min,
800 max,
801 './tests/worker-files/thread/testWorker.js',
802 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
803 )
804 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
805 const promises = new Set()
806 const maxMultiplier = 2
807 for (let i = 0; i < max * maxMultiplier; i++) {
808 promises.add(pool.execute())
809 }
810 await Promise.all(promises)
811 for (const workerNode of pool.workerNodes) {
812 expect(workerNode.workerUsage).toStrictEqual({
813 tasks: {
814 executed: maxMultiplier,
815 executing: 0,
816 queued: 0,
817 failed: 0
818 },
819 runTime: {
820 aggregate: expect.any(Number),
821 average: expect.any(Number),
822 median: 0,
823 history: expect.any(CircularArray)
824 },
825 waitTime: {
826 aggregate: 0,
827 average: 0,
828 median: 0,
829 history: expect.any(CircularArray)
830 },
831 elu: undefined
832 })
833 expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
834 expect(workerNode.workerUsage.runTime.average).toBeGreaterThan(0)
835 }
836 expect(
837 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
838 pool.workerChoiceStrategyContext.workerChoiceStrategy
839 ).workersVirtualTaskEndTimestamp.length
840 ).toBe(pool.workerNodes.length)
841 // We need to clean up the resources after our test
842 await pool.destroy()
843 })
844
845 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
846 const pool = new DynamicThreadPool(
847 min,
848 max,
849 './tests/worker-files/thread/testWorker.js',
850 {
851 workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE,
852 workerChoiceStrategyOptions: {
853 runTime: { median: true }
854 }
855 }
856 )
857 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
858 const promises = new Set()
859 const maxMultiplier = 2
860 for (let i = 0; i < max * maxMultiplier; i++) {
861 promises.add(pool.execute())
862 }
863 await Promise.all(promises)
864 for (const workerNode of pool.workerNodes) {
865 expect(workerNode.workerUsage).toStrictEqual({
866 tasks: {
867 executed: maxMultiplier,
868 executing: 0,
869 queued: 0,
870 failed: 0
871 },
872 runTime: {
873 aggregate: expect.any(Number),
874 average: 0,
875 median: expect.any(Number),
876 history: expect.any(CircularArray)
877 },
878 waitTime: {
879 aggregate: 0,
880 average: 0,
881 median: 0,
882 history: expect.any(CircularArray)
883 },
884 elu: undefined
885 })
886 expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
887 expect(workerNode.workerUsage.runTime.median).toBeGreaterThan(0)
888 }
889 expect(
890 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
891 pool.workerChoiceStrategyContext.workerChoiceStrategy
892 ).workersVirtualTaskEndTimestamp.length
893 ).toBe(pool.workerNodes.length)
894 // We need to clean up the resources after our test
895 await pool.destroy()
896 })
897
898 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
899 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
900 let pool = new FixedThreadPool(
901 max,
902 './tests/worker-files/thread/testWorker.js'
903 )
904 expect(
905 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
906 workerChoiceStrategy
907 ).workersVirtualTaskEndTimestamp
908 ).toBeInstanceOf(Array)
909 expect(
910 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
911 workerChoiceStrategy
912 ).workersVirtualTaskEndTimestamp.length
913 ).toBe(0)
914 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
915 workerChoiceStrategy
916 ).workersVirtualTaskEndTimestamp[0] = performance.now()
917 expect(
918 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
919 workerChoiceStrategy
920 ).workersVirtualTaskEndTimestamp.length
921 ).toBe(1)
922 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
923 expect(
924 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
925 workerChoiceStrategy
926 ).workersVirtualTaskEndTimestamp
927 ).toBeInstanceOf(Array)
928 expect(
929 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
930 workerChoiceStrategy
931 ).workersVirtualTaskEndTimestamp.length
932 ).toBe(0)
933 await pool.destroy()
934 pool = new DynamicThreadPool(
935 min,
936 max,
937 './tests/worker-files/thread/testWorker.js'
938 )
939 expect(
940 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
941 workerChoiceStrategy
942 ).workersVirtualTaskEndTimestamp
943 ).toBeInstanceOf(Array)
944 expect(
945 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
946 workerChoiceStrategy
947 ).workersVirtualTaskEndTimestamp.length
948 ).toBe(0)
949 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
950 workerChoiceStrategy
951 ).workersVirtualTaskEndTimestamp[0] = performance.now()
952 expect(
953 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
954 workerChoiceStrategy
955 ).workersVirtualTaskEndTimestamp.length
956 ).toBe(1)
957 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
958 expect(
959 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
960 workerChoiceStrategy
961 ).workersVirtualTaskEndTimestamp
962 ).toBeInstanceOf(Array)
963 expect(
964 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
965 workerChoiceStrategy
966 ).workersVirtualTaskEndTimestamp.length
967 ).toBe(0)
968 // We need to clean up the resources after our test
969 await pool.destroy()
970 })
971
972 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
973 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
974 let pool = new FixedThreadPool(
975 max,
976 './tests/worker-files/thread/testWorker.js',
977 { workerChoiceStrategy }
978 )
979 expect(
980 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
981 ).toStrictEqual({
982 runTime: {
983 aggregate: true,
984 average: true,
985 median: false
986 },
987 waitTime: {
988 aggregate: false,
989 average: false,
990 median: false
991 },
992 elu: false
993 })
994 await pool.destroy()
995 pool = new DynamicThreadPool(
996 min,
997 max,
998 './tests/worker-files/thread/testWorker.js',
999 { workerChoiceStrategy }
1000 )
1001 expect(
1002 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1003 ).toStrictEqual({
1004 runTime: {
1005 aggregate: true,
1006 average: true,
1007 median: false
1008 },
1009 waitTime: {
1010 aggregate: false,
1011 average: false,
1012 median: false
1013 },
1014 elu: false
1015 })
1016 // We need to clean up the resources after our test
1017 await pool.destroy()
1018 })
1019
1020 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1021 const pool = new FixedThreadPool(
1022 max,
1023 './tests/worker-files/thread/testWorker.js',
1024 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1025 )
1026 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1027 const promises = new Set()
1028 const maxMultiplier = 2
1029 for (let i = 0; i < max * maxMultiplier; i++) {
1030 promises.add(pool.execute())
1031 }
1032 await Promise.all(promises)
1033 for (const workerNode of pool.workerNodes) {
1034 expect(workerNode.workerUsage).toStrictEqual({
1035 tasks: {
1036 executed: expect.any(Number),
1037 executing: 0,
1038 queued: 0,
1039 failed: 0
1040 },
1041 runTime: {
1042 aggregate: expect.any(Number),
1043 average: expect.any(Number),
1044 median: 0,
1045 history: expect.any(CircularArray)
1046 },
1047 waitTime: {
1048 aggregate: 0,
1049 average: 0,
1050 median: 0,
1051 history: expect.any(CircularArray)
1052 },
1053 elu: undefined
1054 })
1055 expect(workerNode.workerUsage.tasks.executed).toBeGreaterThanOrEqual(0)
1056 expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
1057 max * maxMultiplier
1058 )
1059 expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThanOrEqual(0)
1060 expect(workerNode.workerUsage.runTime.average).toBeGreaterThanOrEqual(0)
1061 }
1062 expect(
1063 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1064 pool.workerChoiceStrategyContext.workerChoiceStrategy
1065 ).defaultWorkerWeight
1066 ).toBeGreaterThan(0)
1067 expect(
1068 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1069 pool.workerChoiceStrategyContext.workerChoiceStrategy
1070 ).workerVirtualTaskRunTime
1071 ).toBeGreaterThanOrEqual(0)
1072 // We need to clean up the resources after our test
1073 await pool.destroy()
1074 })
1075
1076 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1077 const pool = new DynamicThreadPool(
1078 min,
1079 max,
1080 './tests/worker-files/thread/testWorker.js',
1081 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1082 )
1083 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1084 const promises = new Set()
1085 const maxMultiplier = 2
1086 for (let i = 0; i < max * maxMultiplier; i++) {
1087 promises.add(pool.execute())
1088 }
1089 await Promise.all(promises)
1090 for (const workerNode of pool.workerNodes) {
1091 expect(workerNode.workerUsage).toStrictEqual({
1092 tasks: {
1093 executed: expect.any(Number),
1094 executing: 0,
1095 queued: 0,
1096 failed: 0
1097 },
1098 runTime: {
1099 aggregate: expect.any(Number),
1100 average: expect.any(Number),
1101 median: 0,
1102 history: expect.any(CircularArray)
1103 },
1104 waitTime: {
1105 aggregate: 0,
1106 average: 0,
1107 median: 0,
1108 history: expect.any(CircularArray)
1109 },
1110 elu: undefined
1111 })
1112 expect(workerNode.workerUsage.tasks.executed).toBeGreaterThan(0)
1113 expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
1114 max * maxMultiplier
1115 )
1116 expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
1117 expect(workerNode.workerUsage.runTime.average).toBeGreaterThan(0)
1118 }
1119 expect(
1120 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1121 pool.workerChoiceStrategyContext.workerChoiceStrategy
1122 ).defaultWorkerWeight
1123 ).toBeGreaterThan(0)
1124 expect(
1125 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1126 pool.workerChoiceStrategyContext.workerChoiceStrategy
1127 ).workerVirtualTaskRunTime
1128 ).toBeGreaterThanOrEqual(0)
1129 // We need to clean up the resources after our test
1130 await pool.destroy()
1131 })
1132
1133 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
1134 const pool = new DynamicThreadPool(
1135 min,
1136 max,
1137 './tests/worker-files/thread/testWorker.js',
1138 {
1139 workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN,
1140 workerChoiceStrategyOptions: {
1141 runTime: { median: true }
1142 }
1143 }
1144 )
1145 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1146 const promises = new Set()
1147 const maxMultiplier = 2
1148 for (let i = 0; i < max * maxMultiplier; i++) {
1149 promises.add(pool.execute())
1150 }
1151 await Promise.all(promises)
1152 for (const workerNode of pool.workerNodes) {
1153 expect(workerNode.workerUsage).toStrictEqual({
1154 tasks: {
1155 executed: expect.any(Number),
1156 executing: 0,
1157 queued: 0,
1158 failed: 0
1159 },
1160 runTime: {
1161 aggregate: expect.any(Number),
1162 average: 0,
1163 median: expect.any(Number),
1164 history: expect.any(CircularArray)
1165 },
1166 waitTime: {
1167 aggregate: 0,
1168 average: 0,
1169 median: 0,
1170 history: expect.any(CircularArray)
1171 },
1172 elu: undefined
1173 })
1174 expect(workerNode.workerUsage.tasks.executed).toBeGreaterThan(0)
1175 expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
1176 max * maxMultiplier
1177 )
1178 expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
1179 expect(workerNode.workerUsage.runTime.median).toBeGreaterThan(0)
1180 }
1181 expect(
1182 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1183 pool.workerChoiceStrategyContext.workerChoiceStrategy
1184 ).defaultWorkerWeight
1185 ).toBeGreaterThan(0)
1186 expect(
1187 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1188 pool.workerChoiceStrategyContext.workerChoiceStrategy
1189 ).workerVirtualTaskRunTime
1190 ).toBeGreaterThanOrEqual(0)
1191 // We need to clean up the resources after our test
1192 await pool.destroy()
1193 })
1194
1195 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1196 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1197 let pool = new FixedThreadPool(
1198 max,
1199 './tests/worker-files/thread/testWorker.js'
1200 )
1201 expect(
1202 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1203 workerChoiceStrategy
1204 ).currentWorkerNodeId
1205 ).toBeDefined()
1206 expect(
1207 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1208 workerChoiceStrategy
1209 ).defaultWorkerWeight
1210 ).toBeDefined()
1211 expect(
1212 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1213 workerChoiceStrategy
1214 ).workerVirtualTaskRunTime
1215 ).toBeDefined()
1216 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1217 expect(
1218 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1219 pool.workerChoiceStrategyContext.workerChoiceStrategy
1220 ).currentWorkerNodeId
1221 ).toBe(0)
1222 expect(
1223 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1224 pool.workerChoiceStrategyContext.workerChoiceStrategy
1225 ).defaultWorkerWeight
1226 ).toBeGreaterThan(0)
1227 expect(
1228 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1229 workerChoiceStrategy
1230 ).workerVirtualTaskRunTime
1231 ).toBe(0)
1232 await pool.destroy()
1233 pool = new DynamicThreadPool(
1234 min,
1235 max,
1236 './tests/worker-files/thread/testWorker.js'
1237 )
1238 expect(
1239 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1240 workerChoiceStrategy
1241 ).currentWorkerNodeId
1242 ).toBeDefined()
1243 expect(
1244 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1245 workerChoiceStrategy
1246 ).defaultWorkerWeight
1247 ).toBeDefined()
1248 expect(
1249 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1250 workerChoiceStrategy
1251 ).workerVirtualTaskRunTime
1252 ).toBeDefined()
1253 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1254 expect(
1255 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1256 pool.workerChoiceStrategyContext.workerChoiceStrategy
1257 ).currentWorkerNodeId
1258 ).toBe(0)
1259 expect(
1260 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1261 pool.workerChoiceStrategyContext.workerChoiceStrategy
1262 ).defaultWorkerWeight
1263 ).toBeGreaterThan(0)
1264 expect(
1265 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1266 workerChoiceStrategy
1267 ).workerVirtualTaskRunTime
1268 ).toBe(0)
1269 // We need to clean up the resources after our test
1270 await pool.destroy()
1271 })
1272
1273 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1274 const workerChoiceStrategy =
1275 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1276 let pool = new FixedThreadPool(
1277 max,
1278 './tests/worker-files/thread/testWorker.js',
1279 { workerChoiceStrategy }
1280 )
1281 expect(
1282 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1283 ).toStrictEqual({
1284 runTime: {
1285 aggregate: false,
1286 average: false,
1287 median: false
1288 },
1289 waitTime: {
1290 aggregate: false,
1291 average: false,
1292 median: false
1293 },
1294 elu: false
1295 })
1296 await pool.destroy()
1297 pool = new DynamicThreadPool(
1298 min,
1299 max,
1300 './tests/worker-files/thread/testWorker.js',
1301 { workerChoiceStrategy }
1302 )
1303 expect(
1304 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1305 ).toStrictEqual({
1306 runTime: {
1307 aggregate: false,
1308 average: false,
1309 median: false
1310 },
1311 waitTime: {
1312 aggregate: false,
1313 average: false,
1314 median: false
1315 },
1316 elu: false
1317 })
1318 // We need to clean up the resources after our test
1319 await pool.destroy()
1320 })
1321
1322 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1323 const pool = new FixedThreadPool(
1324 max,
1325 './tests/worker-files/thread/testWorker.js',
1326 {
1327 workerChoiceStrategy:
1328 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1329 }
1330 )
1331 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1332 const promises = new Set()
1333 const maxMultiplier = 2
1334 for (let i = 0; i < max * maxMultiplier; i++) {
1335 promises.add(pool.execute())
1336 }
1337 await Promise.all(promises)
1338 for (const workerNode of pool.workerNodes) {
1339 expect(workerNode.workerUsage).toStrictEqual({
1340 tasks: {
1341 executed: maxMultiplier,
1342 executing: 0,
1343 queued: 0,
1344 failed: 0
1345 },
1346 runTime: {
1347 aggregate: 0,
1348 average: 0,
1349 median: 0,
1350 history: expect.any(CircularArray)
1351 },
1352 waitTime: {
1353 aggregate: 0,
1354 average: 0,
1355 median: 0,
1356 history: expect.any(CircularArray)
1357 },
1358 elu: undefined
1359 })
1360 }
1361 expect(
1362 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1363 pool.workerChoiceStrategyContext.workerChoiceStrategy
1364 ).defaultWorkerWeight
1365 ).toBeGreaterThan(0)
1366 expect(
1367 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1368 pool.workerChoiceStrategyContext.workerChoiceStrategy
1369 ).currentRoundId
1370 ).toBe(0)
1371 expect(
1372 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1373 pool.workerChoiceStrategyContext.workerChoiceStrategy
1374 ).currentWorkerNodeId
1375 ).toBe(0)
1376 expect(
1377 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1378 pool.workerChoiceStrategyContext.workerChoiceStrategy
1379 ).roundWeights
1380 ).toStrictEqual([
1381 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1382 pool.workerChoiceStrategyContext.workerChoiceStrategy
1383 ).defaultWorkerWeight
1384 ])
1385 // We need to clean up the resources after our test
1386 await pool.destroy()
1387 })
1388
1389 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1390 const pool = new DynamicThreadPool(
1391 min,
1392 max,
1393 './tests/worker-files/thread/testWorker.js',
1394 {
1395 workerChoiceStrategy:
1396 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1397 }
1398 )
1399 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1400 const promises = new Set()
1401 const maxMultiplier = 2
1402 for (let i = 0; i < max * maxMultiplier; i++) {
1403 promises.add(pool.execute())
1404 }
1405 await Promise.all(promises)
1406 for (const workerNode of pool.workerNodes) {
1407 expect(workerNode.workerUsage).toStrictEqual({
1408 tasks: {
1409 executed: maxMultiplier,
1410 executing: 0,
1411 queued: 0,
1412 failed: 0
1413 },
1414 runTime: {
1415 aggregate: 0,
1416 average: 0,
1417 median: 0,
1418 history: expect.any(CircularArray)
1419 },
1420 waitTime: {
1421 aggregate: 0,
1422 average: 0,
1423 median: 0,
1424 history: expect.any(CircularArray)
1425 },
1426 elu: undefined
1427 })
1428 }
1429 expect(
1430 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1431 pool.workerChoiceStrategyContext.workerChoiceStrategy
1432 ).defaultWorkerWeight
1433 ).toBeGreaterThan(0)
1434 expect(
1435 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1436 pool.workerChoiceStrategyContext.workerChoiceStrategy
1437 ).currentRoundId
1438 ).toBe(0)
1439 expect(
1440 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1441 pool.workerChoiceStrategyContext.workerChoiceStrategy
1442 ).currentWorkerNodeId
1443 ).toBe(0)
1444 expect(
1445 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1446 pool.workerChoiceStrategyContext.workerChoiceStrategy
1447 ).roundWeights
1448 ).toStrictEqual([
1449 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1450 pool.workerChoiceStrategyContext.workerChoiceStrategy
1451 ).defaultWorkerWeight
1452 ])
1453 // We need to clean up the resources after our test
1454 await pool.destroy()
1455 })
1456
1457 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1458 const workerChoiceStrategy =
1459 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1460 let pool = new FixedThreadPool(
1461 max,
1462 './tests/worker-files/thread/testWorker.js'
1463 )
1464 expect(
1465 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1466 workerChoiceStrategy
1467 ).currentRoundId
1468 ).toBeDefined()
1469 expect(
1470 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1471 workerChoiceStrategy
1472 ).currentWorkerNodeId
1473 ).toBeDefined()
1474 expect(
1475 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1476 workerChoiceStrategy
1477 ).defaultWorkerWeight
1478 ).toBeDefined()
1479 expect(
1480 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1481 workerChoiceStrategy
1482 ).roundWeights
1483 ).toBeDefined()
1484 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1485 expect(
1486 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1487 workerChoiceStrategy
1488 ).currentRoundId
1489 ).toBe(0)
1490 expect(
1491 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1492 pool.workerChoiceStrategyContext.workerChoiceStrategy
1493 ).currentWorkerNodeId
1494 ).toBe(0)
1495 expect(
1496 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1497 pool.workerChoiceStrategyContext.workerChoiceStrategy
1498 ).defaultWorkerWeight
1499 ).toBeGreaterThan(0)
1500 expect(
1501 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1502 workerChoiceStrategy
1503 ).roundWeights
1504 ).toStrictEqual([
1505 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1506 pool.workerChoiceStrategyContext.workerChoiceStrategy
1507 ).defaultWorkerWeight
1508 ])
1509 await pool.destroy()
1510 pool = new DynamicThreadPool(
1511 min,
1512 max,
1513 './tests/worker-files/thread/testWorker.js'
1514 )
1515 expect(
1516 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1517 workerChoiceStrategy
1518 ).currentRoundId
1519 ).toBeDefined()
1520 expect(
1521 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1522 workerChoiceStrategy
1523 ).currentWorkerNodeId
1524 ).toBeDefined()
1525 expect(
1526 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1527 workerChoiceStrategy
1528 ).defaultWorkerWeight
1529 ).toBeDefined()
1530 expect(
1531 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1532 workerChoiceStrategy
1533 ).roundWeights
1534 ).toBeDefined()
1535 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1536 expect(
1537 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1538 pool.workerChoiceStrategyContext.workerChoiceStrategy
1539 ).currentWorkerNodeId
1540 ).toBe(0)
1541 expect(
1542 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1543 pool.workerChoiceStrategyContext.workerChoiceStrategy
1544 ).defaultWorkerWeight
1545 ).toBeGreaterThan(0)
1546 expect(
1547 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1548 workerChoiceStrategy
1549 ).roundWeights
1550 ).toStrictEqual([
1551 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1552 pool.workerChoiceStrategyContext.workerChoiceStrategy
1553 ).defaultWorkerWeight
1554 ])
1555 // We need to clean up the resources after our test
1556 await pool.destroy()
1557 })
1558
1559 it('Verify unknown strategy throw error', () => {
1560 expect(
1561 () =>
1562 new DynamicThreadPool(
1563 min,
1564 max,
1565 './tests/worker-files/thread/testWorker.js',
1566 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
1567 )
1568 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")
1569 })
1570 })