d609915842011ebb8651c95c8ae98bf06a5064c3
[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: false,
608 avgRunTime: false,
609 medRunTime: false,
610 waitTime: false,
611 avgWaitTime: false,
612 medWaitTime: false,
613 elu: true
614 })
615 await pool.destroy()
616 pool = new DynamicThreadPool(
617 min,
618 max,
619 './tests/worker-files/thread/testWorker.js',
620 { workerChoiceStrategy }
621 )
622 expect(
623 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
624 ).toStrictEqual({
625 runTime: false,
626 avgRunTime: false,
627 medRunTime: false,
628 waitTime: false,
629 avgWaitTime: false,
630 medWaitTime: false,
631 elu: true
632 })
633 // We need to clean up the resources after our test
634 await pool.destroy()
635 })
636
637 it('Verify LEAST_ELU strategy can be run in a fixed pool', async () => {
638 const pool = new FixedThreadPool(
639 max,
640 './tests/worker-files/thread/testWorker.js',
641 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_ELU }
642 )
643 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
644 const maxMultiplier = 2
645 for (let i = 0; i < max * maxMultiplier; i++) {
646 await pool.execute()
647 if (i !== max * maxMultiplier - 1) await TestUtils.sleep(500)
648 }
649 for (const workerNode of pool.workerNodes) {
650 const expectedWorkerUsage = {
651 tasks: {
652 executed: expect.any(Number),
653 executing: 0,
654 queued: 0,
655 failed: 0
656 },
657 runTime: {
658 aggregation: 0,
659 average: 0,
660 median: 0,
661 history: expect.any(CircularArray)
662 },
663 waitTime: {
664 aggregation: 0,
665 average: 0,
666 median: 0,
667 history: expect.any(CircularArray)
668 }
669 }
670 if (workerNode.workerUsage.elu === undefined) {
671 expect(workerNode.workerUsage).toStrictEqual({
672 ...expectedWorkerUsage,
673 elu: undefined
674 })
675 } else {
676 expect(workerNode.workerUsage).toStrictEqual({
677 ...expectedWorkerUsage,
678 elu: {
679 active: expect.any(Number),
680 idle: 0,
681 utilization: 1
682 }
683 })
684 }
685 expect(workerNode.workerUsage.tasks.executed).toBeGreaterThanOrEqual(0)
686 expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
687 max * maxMultiplier
688 )
689 }
690 // We need to clean up the resources after our test
691 await pool.destroy()
692 })
693
694 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
695 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
696 let pool = new FixedThreadPool(
697 max,
698 './tests/worker-files/thread/testWorker.js',
699 { workerChoiceStrategy }
700 )
701 expect(
702 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
703 ).toStrictEqual({
704 runTime: {
705 aggregate: true,
706 average: true,
707 median: false
708 },
709 waitTime: {
710 aggregate: false,
711 average: false,
712 median: false
713 },
714 elu: false
715 })
716 await pool.destroy()
717 pool = new DynamicThreadPool(
718 min,
719 max,
720 './tests/worker-files/thread/testWorker.js',
721 { workerChoiceStrategy }
722 )
723 expect(
724 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
725 ).toStrictEqual({
726 runTime: {
727 aggregate: true,
728 average: true,
729 median: false
730 },
731 waitTime: {
732 aggregate: false,
733 average: false,
734 median: false
735 },
736 elu: false
737 })
738 // We need to clean up the resources after our test
739 await pool.destroy()
740 })
741
742 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
743 const pool = new FixedThreadPool(
744 max,
745 './tests/worker-files/thread/testWorker.js',
746 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
747 )
748 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
749 const promises = new Set()
750 const maxMultiplier = 2
751 for (let i = 0; i < max * maxMultiplier; i++) {
752 promises.add(pool.execute())
753 }
754 await Promise.all(promises)
755 for (const workerNode of pool.workerNodes) {
756 expect(workerNode.workerUsage).toStrictEqual({
757 tasks: {
758 executed: maxMultiplier,
759 executing: 0,
760 queued: 0,
761 failed: 0
762 },
763 runTime: {
764 aggregate: expect.any(Number),
765 average: expect.any(Number),
766 median: 0,
767 history: expect.any(CircularArray)
768 },
769 waitTime: {
770 aggregate: 0,
771 average: 0,
772 median: 0,
773 history: expect.any(CircularArray)
774 },
775 elu: undefined
776 })
777 expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
778 expect(workerNode.workerUsage.runTime.average).toBeGreaterThan(0)
779 }
780 expect(
781 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
782 pool.workerChoiceStrategyContext.workerChoiceStrategy
783 ).workersVirtualTaskEndTimestamp.length
784 ).toBe(pool.workerNodes.length)
785 // We need to clean up the resources after our test
786 await pool.destroy()
787 })
788
789 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
790 const pool = new DynamicThreadPool(
791 min,
792 max,
793 './tests/worker-files/thread/testWorker.js',
794 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
795 )
796 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
797 const promises = new Set()
798 const maxMultiplier = 2
799 for (let i = 0; i < max * maxMultiplier; i++) {
800 promises.add(pool.execute())
801 }
802 await Promise.all(promises)
803 for (const workerNode of pool.workerNodes) {
804 expect(workerNode.workerUsage).toStrictEqual({
805 tasks: {
806 executed: maxMultiplier,
807 executing: 0,
808 queued: 0,
809 failed: 0
810 },
811 runTime: {
812 aggregate: expect.any(Number),
813 average: expect.any(Number),
814 median: 0,
815 history: expect.any(CircularArray)
816 },
817 waitTime: {
818 aggregate: 0,
819 average: 0,
820 median: 0,
821 history: expect.any(CircularArray)
822 },
823 elu: undefined
824 })
825 expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
826 expect(workerNode.workerUsage.runTime.average).toBeGreaterThan(0)
827 }
828 expect(
829 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
830 pool.workerChoiceStrategyContext.workerChoiceStrategy
831 ).workersVirtualTaskEndTimestamp.length
832 ).toBe(pool.workerNodes.length)
833 // We need to clean up the resources after our test
834 await pool.destroy()
835 })
836
837 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
838 const pool = new DynamicThreadPool(
839 min,
840 max,
841 './tests/worker-files/thread/testWorker.js',
842 {
843 workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE,
844 workerChoiceStrategyOptions: {
845 runTime: { median: true }
846 }
847 }
848 )
849 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
850 const promises = new Set()
851 const maxMultiplier = 2
852 for (let i = 0; i < max * maxMultiplier; i++) {
853 promises.add(pool.execute())
854 }
855 await Promise.all(promises)
856 for (const workerNode of pool.workerNodes) {
857 expect(workerNode.workerUsage).toStrictEqual({
858 tasks: {
859 executed: maxMultiplier,
860 executing: 0,
861 queued: 0,
862 failed: 0
863 },
864 runTime: {
865 aggregate: expect.any(Number),
866 average: 0,
867 median: expect.any(Number),
868 history: expect.any(CircularArray)
869 },
870 waitTime: {
871 aggregate: 0,
872 average: 0,
873 median: 0,
874 history: expect.any(CircularArray)
875 },
876 elu: undefined
877 })
878 expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
879 expect(workerNode.workerUsage.runTime.median).toBeGreaterThan(0)
880 }
881 expect(
882 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
883 pool.workerChoiceStrategyContext.workerChoiceStrategy
884 ).workersVirtualTaskEndTimestamp.length
885 ).toBe(pool.workerNodes.length)
886 // We need to clean up the resources after our test
887 await pool.destroy()
888 })
889
890 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
891 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
892 let pool = new FixedThreadPool(
893 max,
894 './tests/worker-files/thread/testWorker.js'
895 )
896 expect(
897 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
898 workerChoiceStrategy
899 ).workersVirtualTaskEndTimestamp
900 ).toBeInstanceOf(Array)
901 expect(
902 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
903 workerChoiceStrategy
904 ).workersVirtualTaskEndTimestamp.length
905 ).toBe(0)
906 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
907 workerChoiceStrategy
908 ).workersVirtualTaskEndTimestamp[0] = performance.now()
909 expect(
910 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
911 workerChoiceStrategy
912 ).workersVirtualTaskEndTimestamp.length
913 ).toBe(1)
914 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
915 expect(
916 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
917 workerChoiceStrategy
918 ).workersVirtualTaskEndTimestamp
919 ).toBeInstanceOf(Array)
920 expect(
921 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
922 workerChoiceStrategy
923 ).workersVirtualTaskEndTimestamp.length
924 ).toBe(0)
925 await pool.destroy()
926 pool = new DynamicThreadPool(
927 min,
928 max,
929 './tests/worker-files/thread/testWorker.js'
930 )
931 expect(
932 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
933 workerChoiceStrategy
934 ).workersVirtualTaskEndTimestamp
935 ).toBeInstanceOf(Array)
936 expect(
937 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
938 workerChoiceStrategy
939 ).workersVirtualTaskEndTimestamp.length
940 ).toBe(0)
941 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
942 workerChoiceStrategy
943 ).workersVirtualTaskEndTimestamp[0] = performance.now()
944 expect(
945 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
946 workerChoiceStrategy
947 ).workersVirtualTaskEndTimestamp.length
948 ).toBe(1)
949 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
950 expect(
951 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
952 workerChoiceStrategy
953 ).workersVirtualTaskEndTimestamp
954 ).toBeInstanceOf(Array)
955 expect(
956 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
957 workerChoiceStrategy
958 ).workersVirtualTaskEndTimestamp.length
959 ).toBe(0)
960 // We need to clean up the resources after our test
961 await pool.destroy()
962 })
963
964 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
965 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
966 let pool = new FixedThreadPool(
967 max,
968 './tests/worker-files/thread/testWorker.js',
969 { workerChoiceStrategy }
970 )
971 expect(
972 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
973 ).toStrictEqual({
974 runTime: {
975 aggregate: true,
976 average: true,
977 median: false
978 },
979 waitTime: {
980 aggregate: false,
981 average: false,
982 median: false
983 },
984 elu: false
985 })
986 await pool.destroy()
987 pool = new DynamicThreadPool(
988 min,
989 max,
990 './tests/worker-files/thread/testWorker.js',
991 { workerChoiceStrategy }
992 )
993 expect(
994 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
995 ).toStrictEqual({
996 runTime: {
997 aggregate: true,
998 average: true,
999 median: false
1000 },
1001 waitTime: {
1002 aggregate: false,
1003 average: false,
1004 median: false
1005 },
1006 elu: false
1007 })
1008 // We need to clean up the resources after our test
1009 await pool.destroy()
1010 })
1011
1012 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1013 const pool = new FixedThreadPool(
1014 max,
1015 './tests/worker-files/thread/testWorker.js',
1016 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1017 )
1018 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1019 const promises = new Set()
1020 const maxMultiplier = 2
1021 for (let i = 0; i < max * maxMultiplier; i++) {
1022 promises.add(pool.execute())
1023 }
1024 await Promise.all(promises)
1025 for (const workerNode of pool.workerNodes) {
1026 expect(workerNode.workerUsage).toStrictEqual({
1027 tasks: {
1028 executed: expect.any(Number),
1029 executing: 0,
1030 queued: 0,
1031 failed: 0
1032 },
1033 runTime: {
1034 aggregate: expect.any(Number),
1035 average: expect.any(Number),
1036 median: 0,
1037 history: expect.any(CircularArray)
1038 },
1039 waitTime: {
1040 aggregate: 0,
1041 average: 0,
1042 median: 0,
1043 history: expect.any(CircularArray)
1044 },
1045 elu: undefined
1046 })
1047 expect(workerNode.workerUsage.tasks.executed).toBeGreaterThanOrEqual(0)
1048 expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
1049 max * maxMultiplier
1050 )
1051 expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThanOrEqual(0)
1052 expect(workerNode.workerUsage.runTime.average).toBeGreaterThanOrEqual(0)
1053 }
1054 expect(
1055 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1056 pool.workerChoiceStrategyContext.workerChoiceStrategy
1057 ).defaultWorkerWeight
1058 ).toBeGreaterThan(0)
1059 expect(
1060 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1061 pool.workerChoiceStrategyContext.workerChoiceStrategy
1062 ).workerVirtualTaskRunTime
1063 ).toBeGreaterThanOrEqual(0)
1064 // We need to clean up the resources after our test
1065 await pool.destroy()
1066 })
1067
1068 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1069 const pool = new DynamicThreadPool(
1070 min,
1071 max,
1072 './tests/worker-files/thread/testWorker.js',
1073 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1074 )
1075 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1076 const promises = new Set()
1077 const maxMultiplier = 2
1078 for (let i = 0; i < max * maxMultiplier; i++) {
1079 promises.add(pool.execute())
1080 }
1081 await Promise.all(promises)
1082 for (const workerNode of pool.workerNodes) {
1083 expect(workerNode.workerUsage).toStrictEqual({
1084 tasks: {
1085 executed: expect.any(Number),
1086 executing: 0,
1087 queued: 0,
1088 failed: 0
1089 },
1090 runTime: {
1091 aggregate: expect.any(Number),
1092 average: expect.any(Number),
1093 median: 0,
1094 history: expect.any(CircularArray)
1095 },
1096 waitTime: {
1097 aggregate: 0,
1098 average: 0,
1099 median: 0,
1100 history: expect.any(CircularArray)
1101 },
1102 elu: undefined
1103 })
1104 expect(workerNode.workerUsage.tasks.executed).toBeGreaterThan(0)
1105 expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
1106 max * maxMultiplier
1107 )
1108 expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
1109 expect(workerNode.workerUsage.runTime.average).toBeGreaterThan(0)
1110 }
1111 expect(
1112 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1113 pool.workerChoiceStrategyContext.workerChoiceStrategy
1114 ).defaultWorkerWeight
1115 ).toBeGreaterThan(0)
1116 expect(
1117 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1118 pool.workerChoiceStrategyContext.workerChoiceStrategy
1119 ).workerVirtualTaskRunTime
1120 ).toBeGreaterThanOrEqual(0)
1121 // We need to clean up the resources after our test
1122 await pool.destroy()
1123 })
1124
1125 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
1126 const pool = new DynamicThreadPool(
1127 min,
1128 max,
1129 './tests/worker-files/thread/testWorker.js',
1130 {
1131 workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN,
1132 workerChoiceStrategyOptions: {
1133 runTime: { median: true }
1134 }
1135 }
1136 )
1137 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1138 const promises = new Set()
1139 const maxMultiplier = 2
1140 for (let i = 0; i < max * maxMultiplier; i++) {
1141 promises.add(pool.execute())
1142 }
1143 await Promise.all(promises)
1144 for (const workerNode of pool.workerNodes) {
1145 expect(workerNode.workerUsage).toStrictEqual({
1146 tasks: {
1147 executed: expect.any(Number),
1148 executing: 0,
1149 queued: 0,
1150 failed: 0
1151 },
1152 runTime: {
1153 aggregate: expect.any(Number),
1154 average: 0,
1155 median: expect.any(Number),
1156 history: expect.any(CircularArray)
1157 },
1158 waitTime: {
1159 aggregate: 0,
1160 average: 0,
1161 median: 0,
1162 history: expect.any(CircularArray)
1163 },
1164 elu: undefined
1165 })
1166 expect(workerNode.workerUsage.tasks.executed).toBeGreaterThan(0)
1167 expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
1168 max * maxMultiplier
1169 )
1170 expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
1171 expect(workerNode.workerUsage.runTime.median).toBeGreaterThan(0)
1172 }
1173 expect(
1174 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1175 pool.workerChoiceStrategyContext.workerChoiceStrategy
1176 ).defaultWorkerWeight
1177 ).toBeGreaterThan(0)
1178 expect(
1179 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1180 pool.workerChoiceStrategyContext.workerChoiceStrategy
1181 ).workerVirtualTaskRunTime
1182 ).toBeGreaterThanOrEqual(0)
1183 // We need to clean up the resources after our test
1184 await pool.destroy()
1185 })
1186
1187 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1188 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1189 let pool = new FixedThreadPool(
1190 max,
1191 './tests/worker-files/thread/testWorker.js'
1192 )
1193 expect(
1194 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1195 workerChoiceStrategy
1196 ).currentWorkerNodeId
1197 ).toBeDefined()
1198 expect(
1199 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1200 workerChoiceStrategy
1201 ).defaultWorkerWeight
1202 ).toBeDefined()
1203 expect(
1204 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1205 workerChoiceStrategy
1206 ).workerVirtualTaskRunTime
1207 ).toBeDefined()
1208 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1209 expect(
1210 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1211 pool.workerChoiceStrategyContext.workerChoiceStrategy
1212 ).currentWorkerNodeId
1213 ).toBe(0)
1214 expect(
1215 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1216 pool.workerChoiceStrategyContext.workerChoiceStrategy
1217 ).defaultWorkerWeight
1218 ).toBeGreaterThan(0)
1219 expect(
1220 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1221 workerChoiceStrategy
1222 ).workerVirtualTaskRunTime
1223 ).toBe(0)
1224 await pool.destroy()
1225 pool = new DynamicThreadPool(
1226 min,
1227 max,
1228 './tests/worker-files/thread/testWorker.js'
1229 )
1230 expect(
1231 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1232 workerChoiceStrategy
1233 ).currentWorkerNodeId
1234 ).toBeDefined()
1235 expect(
1236 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1237 workerChoiceStrategy
1238 ).defaultWorkerWeight
1239 ).toBeDefined()
1240 expect(
1241 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1242 workerChoiceStrategy
1243 ).workerVirtualTaskRunTime
1244 ).toBeDefined()
1245 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1246 expect(
1247 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1248 pool.workerChoiceStrategyContext.workerChoiceStrategy
1249 ).currentWorkerNodeId
1250 ).toBe(0)
1251 expect(
1252 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1253 pool.workerChoiceStrategyContext.workerChoiceStrategy
1254 ).defaultWorkerWeight
1255 ).toBeGreaterThan(0)
1256 expect(
1257 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1258 workerChoiceStrategy
1259 ).workerVirtualTaskRunTime
1260 ).toBe(0)
1261 // We need to clean up the resources after our test
1262 await pool.destroy()
1263 })
1264
1265 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1266 const workerChoiceStrategy =
1267 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1268 let pool = new FixedThreadPool(
1269 max,
1270 './tests/worker-files/thread/testWorker.js',
1271 { workerChoiceStrategy }
1272 )
1273 expect(
1274 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1275 ).toStrictEqual({
1276 runTime: {
1277 aggregate: false,
1278 average: false,
1279 median: false
1280 },
1281 waitTime: {
1282 aggregate: false,
1283 average: false,
1284 median: false
1285 },
1286 elu: false
1287 })
1288 await pool.destroy()
1289 pool = new DynamicThreadPool(
1290 min,
1291 max,
1292 './tests/worker-files/thread/testWorker.js',
1293 { workerChoiceStrategy }
1294 )
1295 expect(
1296 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1297 ).toStrictEqual({
1298 runTime: {
1299 aggregate: false,
1300 average: false,
1301 median: false
1302 },
1303 waitTime: {
1304 aggregate: false,
1305 average: false,
1306 median: false
1307 },
1308 elu: false
1309 })
1310 // We need to clean up the resources after our test
1311 await pool.destroy()
1312 })
1313
1314 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1315 const pool = new FixedThreadPool(
1316 max,
1317 './tests/worker-files/thread/testWorker.js',
1318 {
1319 workerChoiceStrategy:
1320 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1321 }
1322 )
1323 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1324 const promises = new Set()
1325 const maxMultiplier = 2
1326 for (let i = 0; i < max * maxMultiplier; i++) {
1327 promises.add(pool.execute())
1328 }
1329 await Promise.all(promises)
1330 for (const workerNode of pool.workerNodes) {
1331 expect(workerNode.workerUsage).toStrictEqual({
1332 tasks: {
1333 executed: maxMultiplier,
1334 executing: 0,
1335 queued: 0,
1336 failed: 0
1337 },
1338 runTime: {
1339 aggregate: 0,
1340 average: 0,
1341 median: 0,
1342 history: expect.any(CircularArray)
1343 },
1344 waitTime: {
1345 aggregate: 0,
1346 average: 0,
1347 median: 0,
1348 history: expect.any(CircularArray)
1349 },
1350 elu: undefined
1351 })
1352 }
1353 expect(
1354 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1355 pool.workerChoiceStrategyContext.workerChoiceStrategy
1356 ).defaultWorkerWeight
1357 ).toBeGreaterThan(0)
1358 expect(
1359 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1360 pool.workerChoiceStrategyContext.workerChoiceStrategy
1361 ).currentRoundId
1362 ).toBe(0)
1363 expect(
1364 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1365 pool.workerChoiceStrategyContext.workerChoiceStrategy
1366 ).currentWorkerNodeId
1367 ).toBe(0)
1368 expect(
1369 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1370 pool.workerChoiceStrategyContext.workerChoiceStrategy
1371 ).roundWeights
1372 ).toStrictEqual([
1373 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1374 pool.workerChoiceStrategyContext.workerChoiceStrategy
1375 ).defaultWorkerWeight
1376 ])
1377 // We need to clean up the resources after our test
1378 await pool.destroy()
1379 })
1380
1381 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1382 const pool = new DynamicThreadPool(
1383 min,
1384 max,
1385 './tests/worker-files/thread/testWorker.js',
1386 {
1387 workerChoiceStrategy:
1388 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1389 }
1390 )
1391 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1392 const promises = new Set()
1393 const maxMultiplier = 2
1394 for (let i = 0; i < max * maxMultiplier; i++) {
1395 promises.add(pool.execute())
1396 }
1397 await Promise.all(promises)
1398 for (const workerNode of pool.workerNodes) {
1399 expect(workerNode.workerUsage).toStrictEqual({
1400 tasks: {
1401 executed: maxMultiplier,
1402 executing: 0,
1403 queued: 0,
1404 failed: 0
1405 },
1406 runTime: {
1407 aggregate: 0,
1408 average: 0,
1409 median: 0,
1410 history: expect.any(CircularArray)
1411 },
1412 waitTime: {
1413 aggregate: 0,
1414 average: 0,
1415 median: 0,
1416 history: expect.any(CircularArray)
1417 },
1418 elu: undefined
1419 })
1420 }
1421 expect(
1422 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1423 pool.workerChoiceStrategyContext.workerChoiceStrategy
1424 ).defaultWorkerWeight
1425 ).toBeGreaterThan(0)
1426 expect(
1427 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1428 pool.workerChoiceStrategyContext.workerChoiceStrategy
1429 ).currentRoundId
1430 ).toBe(0)
1431 expect(
1432 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1433 pool.workerChoiceStrategyContext.workerChoiceStrategy
1434 ).currentWorkerNodeId
1435 ).toBe(0)
1436 expect(
1437 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1438 pool.workerChoiceStrategyContext.workerChoiceStrategy
1439 ).roundWeights
1440 ).toStrictEqual([
1441 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1442 pool.workerChoiceStrategyContext.workerChoiceStrategy
1443 ).defaultWorkerWeight
1444 ])
1445 // We need to clean up the resources after our test
1446 await pool.destroy()
1447 })
1448
1449 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1450 const workerChoiceStrategy =
1451 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1452 let pool = new FixedThreadPool(
1453 max,
1454 './tests/worker-files/thread/testWorker.js'
1455 )
1456 expect(
1457 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1458 workerChoiceStrategy
1459 ).currentRoundId
1460 ).toBeDefined()
1461 expect(
1462 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1463 workerChoiceStrategy
1464 ).currentWorkerNodeId
1465 ).toBeDefined()
1466 expect(
1467 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1468 workerChoiceStrategy
1469 ).defaultWorkerWeight
1470 ).toBeDefined()
1471 expect(
1472 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1473 workerChoiceStrategy
1474 ).roundWeights
1475 ).toBeDefined()
1476 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1477 expect(
1478 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1479 workerChoiceStrategy
1480 ).currentRoundId
1481 ).toBe(0)
1482 expect(
1483 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1484 pool.workerChoiceStrategyContext.workerChoiceStrategy
1485 ).currentWorkerNodeId
1486 ).toBe(0)
1487 expect(
1488 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1489 pool.workerChoiceStrategyContext.workerChoiceStrategy
1490 ).defaultWorkerWeight
1491 ).toBeGreaterThan(0)
1492 expect(
1493 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1494 workerChoiceStrategy
1495 ).roundWeights
1496 ).toStrictEqual([
1497 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1498 pool.workerChoiceStrategyContext.workerChoiceStrategy
1499 ).defaultWorkerWeight
1500 ])
1501 await pool.destroy()
1502 pool = new DynamicThreadPool(
1503 min,
1504 max,
1505 './tests/worker-files/thread/testWorker.js'
1506 )
1507 expect(
1508 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1509 workerChoiceStrategy
1510 ).currentRoundId
1511 ).toBeDefined()
1512 expect(
1513 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1514 workerChoiceStrategy
1515 ).currentWorkerNodeId
1516 ).toBeDefined()
1517 expect(
1518 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1519 workerChoiceStrategy
1520 ).defaultWorkerWeight
1521 ).toBeDefined()
1522 expect(
1523 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1524 workerChoiceStrategy
1525 ).roundWeights
1526 ).toBeDefined()
1527 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1528 expect(
1529 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1530 pool.workerChoiceStrategyContext.workerChoiceStrategy
1531 ).currentWorkerNodeId
1532 ).toBe(0)
1533 expect(
1534 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1535 pool.workerChoiceStrategyContext.workerChoiceStrategy
1536 ).defaultWorkerWeight
1537 ).toBeGreaterThan(0)
1538 expect(
1539 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1540 workerChoiceStrategy
1541 ).roundWeights
1542 ).toStrictEqual([
1543 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1544 pool.workerChoiceStrategyContext.workerChoiceStrategy
1545 ).defaultWorkerWeight
1546 ])
1547 // We need to clean up the resources after our test
1548 await pool.destroy()
1549 })
1550
1551 it('Verify unknown strategy throw error', () => {
1552 expect(
1553 () =>
1554 new DynamicThreadPool(
1555 min,
1556 max,
1557 './tests/worker-files/thread/testWorker.js',
1558 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
1559 )
1560 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")
1561 })
1562 })