test: improve WCS coverage
[poolifier.git] / tests / pools / selection-strategies / selection-strategies.test.js
1 const { expect } = require('expect')
2 const {
3 DynamicClusterPool,
4 DynamicThreadPool,
5 FixedClusterPool,
6 FixedThreadPool,
7 WorkerChoiceStrategies
8 } = require('../../../lib')
9 const { CircularArray } = require('../../../lib/circular-array')
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 expect(pool.opts.workerChoiceStrategyOptions).toStrictEqual({
70 retries: 6,
71 runTime: { median: false },
72 waitTime: { median: false },
73 elu: { median: false }
74 })
75 expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({
76 retries: 6,
77 runTime: { median: false },
78 waitTime: { median: false },
79 elu: { median: false }
80 })
81 await pool.destroy()
82 }
83 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
84 const pool = new DynamicClusterPool(
85 min,
86 max,
87 './tests/worker-files/cluster/testWorker.js'
88 )
89 pool.setWorkerChoiceStrategy(workerChoiceStrategy, { retries: 3 })
90 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
91 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
92 workerChoiceStrategy
93 )
94 expect(pool.opts.workerChoiceStrategyOptions).toStrictEqual({
95 retries: 3,
96 runTime: { median: false },
97 waitTime: { median: false },
98 elu: { median: false }
99 })
100 expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({
101 retries: 3,
102 runTime: { median: false },
103 waitTime: { median: false },
104 elu: { median: false }
105 })
106 await pool.destroy()
107 }
108 })
109
110 it('Verify available strategies default internals at pool creation', async () => {
111 const pool = new FixedThreadPool(
112 max,
113 './tests/worker-files/thread/testWorker.js'
114 )
115 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
116 expect(
117 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
118 workerChoiceStrategy
119 ).nextWorkerNodeKey
120 ).toBe(0)
121 expect(
122 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
123 workerChoiceStrategy
124 ).previousWorkerNodeKey
125 ).toBe(0)
126 if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) {
127 expect(
128 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
129 workerChoiceStrategy
130 ).workersVirtualTaskEndTimestamp
131 ).toBeInstanceOf(Array)
132 expect(
133 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
134 workerChoiceStrategy
135 ).workersVirtualTaskEndTimestamp.length
136 ).toBe(0)
137 } else if (
138 workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
139 ) {
140 expect(
141 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
142 workerChoiceStrategy
143 ).defaultWorkerWeight
144 ).toBeGreaterThan(0)
145 expect(
146 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
147 workerChoiceStrategy
148 ).workerVirtualTaskRunTime
149 ).toBe(0)
150 } else if (
151 workerChoiceStrategy ===
152 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
153 ) {
154 expect(
155 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
156 workerChoiceStrategy
157 ).defaultWorkerWeight
158 ).toBeGreaterThan(0)
159 expect(
160 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
161 workerChoiceStrategy
162 ).workerVirtualTaskRunTime
163 ).toBe(0)
164 expect(
165 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
166 workerChoiceStrategy
167 ).roundId
168 ).toBe(0)
169 expect(
170 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
171 workerChoiceStrategy
172 ).workerNodeId
173 ).toBe(0)
174 expect(
175 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
176 workerChoiceStrategy
177 ).roundWeights
178 ).toStrictEqual([
179 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
180 workerChoiceStrategy
181 ).defaultWorkerWeight
182 ])
183 }
184 }
185 await pool.destroy()
186 })
187
188 it('Verify ROUND_ROBIN strategy default policy', async () => {
189 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
190 let pool = new FixedThreadPool(
191 max,
192 './tests/worker-files/thread/testWorker.js',
193 { workerChoiceStrategy }
194 )
195 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
196 dynamicWorkerUsage: false,
197 dynamicWorkerReady: true
198 })
199 await pool.destroy()
200 pool = new DynamicThreadPool(
201 min,
202 max,
203 './tests/worker-files/thread/testWorker.js',
204 { workerChoiceStrategy }
205 )
206 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
207 dynamicWorkerUsage: false,
208 dynamicWorkerReady: true
209 })
210 // We need to clean up the resources after our test
211 await pool.destroy()
212 })
213
214 it('Verify ROUND_ROBIN strategy default tasks statistics requirements', async () => {
215 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
216 let pool = new FixedThreadPool(
217 max,
218 './tests/worker-files/thread/testWorker.js',
219 { workerChoiceStrategy }
220 )
221 expect(
222 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
223 ).toStrictEqual({
224 runTime: {
225 aggregate: false,
226 average: false,
227 median: false
228 },
229 waitTime: {
230 aggregate: false,
231 average: false,
232 median: false
233 },
234 elu: {
235 aggregate: false,
236 average: false,
237 median: false
238 }
239 })
240 await pool.destroy()
241 pool = new DynamicThreadPool(
242 min,
243 max,
244 './tests/worker-files/thread/testWorker.js',
245 { workerChoiceStrategy }
246 )
247 expect(
248 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
249 ).toStrictEqual({
250 runTime: {
251 aggregate: false,
252 average: false,
253 median: false
254 },
255 waitTime: {
256 aggregate: false,
257 average: false,
258 median: false
259 },
260 elu: {
261 aggregate: false,
262 average: false,
263 median: false
264 }
265 })
266 // We need to clean up the resources after our test
267 await pool.destroy()
268 })
269
270 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
271 const pool = new FixedThreadPool(
272 max,
273 './tests/worker-files/thread/testWorker.js',
274 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
275 )
276 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
277 const promises = new Set()
278 const maxMultiplier = 2
279 for (let i = 0; i < max * maxMultiplier; i++) {
280 promises.add(pool.execute())
281 }
282 await Promise.all(promises)
283 for (const workerNode of pool.workerNodes) {
284 expect(workerNode.usage).toStrictEqual({
285 tasks: {
286 executed: maxMultiplier,
287 executing: 0,
288 queued: 0,
289 maxQueued: 0,
290 stolen: 0,
291 failed: 0
292 },
293 runTime: {
294 history: new CircularArray()
295 },
296 waitTime: {
297 history: new CircularArray()
298 },
299 elu: {
300 idle: {
301 history: new CircularArray()
302 },
303 active: {
304 history: new CircularArray()
305 }
306 }
307 })
308 }
309 expect(
310 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
311 WorkerChoiceStrategies.ROUND_ROBIN
312 ).nextWorkerNodeKey
313 ).toBe(0)
314 // We need to clean up the resources after our test
315 await pool.destroy()
316 })
317
318 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
319 const pool = new DynamicThreadPool(
320 min,
321 max,
322 './tests/worker-files/thread/testWorker.js',
323 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
324 )
325 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
326 const promises = new Set()
327 const maxMultiplier = 2
328 for (let i = 0; i < max * maxMultiplier; i++) {
329 promises.add(pool.execute())
330 }
331 await Promise.all(promises)
332 for (const workerNode of pool.workerNodes) {
333 expect(workerNode.usage).toStrictEqual({
334 tasks: {
335 executed: expect.any(Number),
336 executing: 0,
337 queued: 0,
338 maxQueued: 0,
339 stolen: 0,
340 failed: 0
341 },
342 runTime: {
343 history: new CircularArray()
344 },
345 waitTime: {
346 history: new CircularArray()
347 },
348 elu: {
349 idle: {
350 history: new CircularArray()
351 },
352 active: {
353 history: new CircularArray()
354 }
355 }
356 })
357 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
358 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
359 max * maxMultiplier
360 )
361 }
362 expect(
363 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
364 WorkerChoiceStrategies.ROUND_ROBIN
365 ).nextWorkerNodeKey
366 ).toBe(0)
367 // We need to clean up the resources after our test
368 await pool.destroy()
369 })
370
371 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
372 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
373 let pool = new FixedClusterPool(
374 max,
375 './tests/worker-files/cluster/testWorker.js',
376 { workerChoiceStrategy }
377 )
378 let results = new Set()
379 for (let i = 0; i < max; i++) {
380 results.add(pool.workerNodes[pool.chooseWorkerNode()].worker.id)
381 }
382 expect(results.size).toBe(max)
383 await pool.destroy()
384 pool = new FixedThreadPool(
385 max,
386 './tests/worker-files/thread/testWorker.js',
387 { workerChoiceStrategy }
388 )
389 results = new Set()
390 for (let i = 0; i < max; i++) {
391 results.add(pool.workerNodes[pool.chooseWorkerNode()].worker.threadId)
392 }
393 expect(results.size).toBe(max)
394 await pool.destroy()
395 })
396
397 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
398 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
399 let pool = new FixedThreadPool(
400 max,
401 './tests/worker-files/thread/testWorker.js',
402 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
403 )
404 expect(
405 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
406 workerChoiceStrategy
407 ).nextWorkerNodeKey
408 ).toBeDefined()
409 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
410 expect(
411 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
412 pool.workerChoiceStrategyContext.workerChoiceStrategy
413 ).nextWorkerNodeKey
414 ).toBe(0)
415 await pool.destroy()
416 pool = new DynamicThreadPool(
417 min,
418 max,
419 './tests/worker-files/thread/testWorker.js',
420 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
421 )
422 expect(
423 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
424 workerChoiceStrategy
425 ).nextWorkerNodeKey
426 ).toBeDefined()
427 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
428 expect(
429 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
430 pool.workerChoiceStrategyContext.workerChoiceStrategy
431 ).nextWorkerNodeKey
432 ).toBe(0)
433 // We need to clean up the resources after our test
434 await pool.destroy()
435 })
436
437 it('Verify LEAST_USED strategy default policy', async () => {
438 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
439 let pool = new FixedThreadPool(
440 max,
441 './tests/worker-files/thread/testWorker.js',
442 { workerChoiceStrategy }
443 )
444 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
445 dynamicWorkerUsage: false,
446 dynamicWorkerReady: true
447 })
448 await pool.destroy()
449 pool = new DynamicThreadPool(
450 min,
451 max,
452 './tests/worker-files/thread/testWorker.js',
453 { workerChoiceStrategy }
454 )
455 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
456 dynamicWorkerUsage: false,
457 dynamicWorkerReady: true
458 })
459 // We need to clean up the resources after our test
460 await pool.destroy()
461 })
462
463 it('Verify LEAST_USED strategy default tasks statistics requirements', async () => {
464 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
465 let pool = new FixedThreadPool(
466 max,
467 './tests/worker-files/thread/testWorker.js',
468 { workerChoiceStrategy }
469 )
470 expect(
471 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
472 ).toStrictEqual({
473 runTime: {
474 aggregate: false,
475 average: false,
476 median: false
477 },
478 waitTime: {
479 aggregate: false,
480 average: false,
481 median: false
482 },
483 elu: {
484 aggregate: false,
485 average: false,
486 median: false
487 }
488 })
489 await pool.destroy()
490 pool = new DynamicThreadPool(
491 min,
492 max,
493 './tests/worker-files/thread/testWorker.js',
494 { workerChoiceStrategy }
495 )
496 expect(
497 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
498 ).toStrictEqual({
499 runTime: {
500 aggregate: false,
501 average: false,
502 median: false
503 },
504 waitTime: {
505 aggregate: false,
506 average: false,
507 median: false
508 },
509 elu: {
510 aggregate: false,
511 average: false,
512 median: false
513 }
514 })
515 // We need to clean up the resources after our test
516 await pool.destroy()
517 })
518
519 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
520 const pool = new FixedThreadPool(
521 max,
522 './tests/worker-files/thread/testWorker.js',
523 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
524 )
525 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
526 const promises = new Set()
527 const maxMultiplier = 2
528 for (let i = 0; i < max * maxMultiplier; i++) {
529 promises.add(pool.execute())
530 }
531 await Promise.all(promises)
532 for (const workerNode of pool.workerNodes) {
533 expect(workerNode.usage).toStrictEqual({
534 tasks: {
535 executed: expect.any(Number),
536 executing: 0,
537 queued: 0,
538 maxQueued: 0,
539 stolen: 0,
540 failed: 0
541 },
542 runTime: {
543 history: new CircularArray()
544 },
545 waitTime: {
546 history: new CircularArray()
547 },
548 elu: {
549 idle: {
550 history: new CircularArray()
551 },
552 active: {
553 history: new CircularArray()
554 }
555 }
556 })
557 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
558 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
559 max * maxMultiplier
560 )
561 }
562 // We need to clean up the resources after our test
563 await pool.destroy()
564 })
565
566 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
567 const pool = new DynamicThreadPool(
568 min,
569 max,
570 './tests/worker-files/thread/testWorker.js',
571 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
572 )
573 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
574 const promises = new Set()
575 const maxMultiplier = 2
576 for (let i = 0; i < max * maxMultiplier; i++) {
577 promises.add(pool.execute())
578 }
579 await Promise.all(promises)
580 for (const workerNode of pool.workerNodes) {
581 expect(workerNode.usage).toStrictEqual({
582 tasks: {
583 executed: expect.any(Number),
584 executing: 0,
585 queued: 0,
586 maxQueued: 0,
587 stolen: 0,
588 failed: 0
589 },
590 runTime: {
591 history: new CircularArray()
592 },
593 waitTime: {
594 history: new CircularArray()
595 },
596 elu: {
597 idle: {
598 history: new CircularArray()
599 },
600 active: {
601 history: new CircularArray()
602 }
603 }
604 })
605 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
606 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
607 max * maxMultiplier
608 )
609 }
610 // We need to clean up the resources after our test
611 await pool.destroy()
612 })
613
614 it('Verify LEAST_BUSY strategy default policy', async () => {
615 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
616 let pool = new FixedThreadPool(
617 max,
618 './tests/worker-files/thread/testWorker.js',
619 { workerChoiceStrategy }
620 )
621 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
622 dynamicWorkerUsage: false,
623 dynamicWorkerReady: true
624 })
625 await pool.destroy()
626 pool = new DynamicThreadPool(
627 min,
628 max,
629 './tests/worker-files/thread/testWorker.js',
630 { workerChoiceStrategy }
631 )
632 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
633 dynamicWorkerUsage: false,
634 dynamicWorkerReady: true
635 })
636 // We need to clean up the resources after our test
637 await pool.destroy()
638 })
639
640 it('Verify LEAST_BUSY strategy default tasks statistics requirements', async () => {
641 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
642 let pool = new FixedThreadPool(
643 max,
644 './tests/worker-files/thread/testWorker.js',
645 { workerChoiceStrategy }
646 )
647 expect(
648 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
649 ).toStrictEqual({
650 runTime: {
651 aggregate: true,
652 average: false,
653 median: false
654 },
655 waitTime: {
656 aggregate: true,
657 average: false,
658 median: false
659 },
660 elu: {
661 aggregate: false,
662 average: false,
663 median: false
664 }
665 })
666 await pool.destroy()
667 pool = new DynamicThreadPool(
668 min,
669 max,
670 './tests/worker-files/thread/testWorker.js',
671 { workerChoiceStrategy }
672 )
673 expect(
674 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
675 ).toStrictEqual({
676 runTime: {
677 aggregate: true,
678 average: false,
679 median: false
680 },
681 waitTime: {
682 aggregate: true,
683 average: false,
684 median: false
685 },
686 elu: {
687 aggregate: false,
688 average: false,
689 median: false
690 }
691 })
692 // We need to clean up the resources after our test
693 await pool.destroy()
694 })
695
696 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
697 const pool = new FixedThreadPool(
698 max,
699 './tests/worker-files/thread/testWorker.js',
700 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
701 )
702 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
703 const promises = new Set()
704 const maxMultiplier = 2
705 for (let i = 0; i < max * maxMultiplier; i++) {
706 promises.add(pool.execute())
707 }
708 await Promise.all(promises)
709 for (const workerNode of pool.workerNodes) {
710 expect(workerNode.usage).toStrictEqual({
711 tasks: {
712 executed: expect.any(Number),
713 executing: 0,
714 queued: 0,
715 maxQueued: 0,
716 stolen: 0,
717 failed: 0
718 },
719 runTime: expect.objectContaining({
720 history: expect.any(CircularArray)
721 }),
722 waitTime: expect.objectContaining({
723 history: expect.any(CircularArray)
724 }),
725 elu: {
726 idle: {
727 history: new CircularArray()
728 },
729 active: {
730 history: new CircularArray()
731 }
732 }
733 })
734 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
735 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
736 max * maxMultiplier
737 )
738 if (workerNode.usage.runTime.aggregate == null) {
739 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
740 } else {
741 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
742 }
743 if (workerNode.usage.waitTime.aggregate == null) {
744 expect(workerNode.usage.waitTime.aggregate).toBeUndefined()
745 } else {
746 expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
747 }
748 }
749 // We need to clean up the resources after our test
750 await pool.destroy()
751 })
752
753 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
754 const pool = new DynamicThreadPool(
755 min,
756 max,
757 './tests/worker-files/thread/testWorker.js',
758 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
759 )
760 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
761 const promises = new Set()
762 const maxMultiplier = 2
763 for (let i = 0; i < max * maxMultiplier; i++) {
764 promises.add(pool.execute())
765 }
766 await Promise.all(promises)
767 for (const workerNode of pool.workerNodes) {
768 expect(workerNode.usage).toStrictEqual({
769 tasks: {
770 executed: expect.any(Number),
771 executing: 0,
772 queued: 0,
773 maxQueued: 0,
774 stolen: 0,
775 failed: 0
776 },
777 runTime: expect.objectContaining({
778 history: expect.any(CircularArray)
779 }),
780 waitTime: expect.objectContaining({
781 history: expect.any(CircularArray)
782 }),
783 elu: {
784 idle: {
785 history: new CircularArray()
786 },
787 active: {
788 history: new CircularArray()
789 }
790 }
791 })
792 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
793 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
794 max * maxMultiplier
795 )
796 if (workerNode.usage.runTime.aggregate == null) {
797 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
798 } else {
799 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
800 }
801 if (workerNode.usage.waitTime.aggregate == null) {
802 expect(workerNode.usage.waitTime.aggregate).toBeUndefined()
803 } else {
804 expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
805 }
806 }
807 // We need to clean up the resources after our test
808 await pool.destroy()
809 })
810
811 it('Verify LEAST_ELU strategy default policy', async () => {
812 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
813 let pool = new FixedThreadPool(
814 max,
815 './tests/worker-files/thread/testWorker.js',
816 { workerChoiceStrategy }
817 )
818 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
819 dynamicWorkerUsage: false,
820 dynamicWorkerReady: true
821 })
822 await pool.destroy()
823 pool = new DynamicThreadPool(
824 min,
825 max,
826 './tests/worker-files/thread/testWorker.js',
827 { workerChoiceStrategy }
828 )
829 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
830 dynamicWorkerUsage: false,
831 dynamicWorkerReady: true
832 })
833 // We need to clean up the resources after our test
834 await pool.destroy()
835 })
836
837 it('Verify LEAST_ELU strategy default tasks statistics requirements', async () => {
838 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_ELU
839 let pool = new FixedThreadPool(
840 max,
841 './tests/worker-files/thread/testWorker.js',
842 { workerChoiceStrategy }
843 )
844 expect(
845 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
846 ).toStrictEqual({
847 runTime: {
848 aggregate: false,
849 average: false,
850 median: false
851 },
852 waitTime: {
853 aggregate: false,
854 average: false,
855 median: false
856 },
857 elu: {
858 aggregate: true,
859 average: false,
860 median: false
861 }
862 })
863 await pool.destroy()
864 pool = new DynamicThreadPool(
865 min,
866 max,
867 './tests/worker-files/thread/testWorker.js',
868 { workerChoiceStrategy }
869 )
870 expect(
871 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
872 ).toStrictEqual({
873 runTime: {
874 aggregate: false,
875 average: false,
876 median: false
877 },
878 waitTime: {
879 aggregate: false,
880 average: false,
881 median: false
882 },
883 elu: {
884 aggregate: true,
885 average: false,
886 median: false
887 }
888 })
889 // We need to clean up the resources after our test
890 await pool.destroy()
891 })
892
893 it('Verify LEAST_ELU strategy can be run in a fixed pool', async () => {
894 const pool = new FixedThreadPool(
895 max,
896 './tests/worker-files/thread/testWorker.js',
897 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_ELU }
898 )
899 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
900 const promises = new Set()
901 const maxMultiplier = 2
902 for (let i = 0; i < max * maxMultiplier; i++) {
903 promises.add(pool.execute())
904 }
905 await Promise.all(promises)
906 for (const workerNode of pool.workerNodes) {
907 expect(workerNode.usage).toStrictEqual({
908 tasks: {
909 executed: expect.any(Number),
910 executing: 0,
911 queued: 0,
912 maxQueued: 0,
913 stolen: 0,
914 failed: 0
915 },
916 runTime: {
917 history: new CircularArray()
918 },
919 waitTime: {
920 history: new CircularArray()
921 },
922 elu: expect.objectContaining({
923 idle: expect.objectContaining({
924 history: expect.any(CircularArray)
925 }),
926 active: expect.objectContaining({
927 history: expect.any(CircularArray)
928 })
929 })
930 })
931 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
932 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
933 max * maxMultiplier
934 )
935 if (workerNode.usage.elu.active.aggregate == null) {
936 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
937 } else {
938 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
939 }
940 if (workerNode.usage.elu.idle.aggregate == null) {
941 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
942 } else {
943 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
944 }
945 if (workerNode.usage.elu.utilization == null) {
946 expect(workerNode.usage.elu.utilization).toBeUndefined()
947 } else {
948 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
949 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
950 }
951 }
952 // We need to clean up the resources after our test
953 await pool.destroy()
954 })
955
956 it('Verify LEAST_ELU strategy can be run in a dynamic pool', async () => {
957 const pool = new DynamicThreadPool(
958 min,
959 max,
960 './tests/worker-files/thread/testWorker.js',
961 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_ELU }
962 )
963 // TODO: Create a better test to cover `LeastEluWorkerChoiceStrategy#choose`
964 const promises = new Set()
965 const maxMultiplier = 2
966 for (let i = 0; i < max * maxMultiplier; i++) {
967 promises.add(pool.execute())
968 }
969 await Promise.all(promises)
970 for (const workerNode of pool.workerNodes) {
971 expect(workerNode.usage).toStrictEqual({
972 tasks: {
973 executed: expect.any(Number),
974 executing: 0,
975 queued: 0,
976 maxQueued: 0,
977 stolen: 0,
978 failed: 0
979 },
980 runTime: {
981 history: new CircularArray()
982 },
983 waitTime: {
984 history: new CircularArray()
985 },
986 elu: expect.objectContaining({
987 idle: expect.objectContaining({
988 history: expect.any(CircularArray)
989 }),
990 active: expect.objectContaining({
991 history: expect.any(CircularArray)
992 })
993 })
994 })
995 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
996 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
997 max * maxMultiplier
998 )
999 if (workerNode.usage.elu.active.aggregate == null) {
1000 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1001 } else {
1002 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1003 }
1004 if (workerNode.usage.elu.idle.aggregate == null) {
1005 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1006 } else {
1007 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1008 }
1009 if (workerNode.usage.elu.utilization == null) {
1010 expect(workerNode.usage.elu.utilization).toBeUndefined()
1011 } else {
1012 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1013 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1014 }
1015 }
1016 // We need to clean up the resources after our test
1017 await pool.destroy()
1018 })
1019
1020 it('Verify FAIR_SHARE strategy default policy', async () => {
1021 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
1022 let pool = new FixedThreadPool(
1023 max,
1024 './tests/worker-files/thread/testWorker.js',
1025 { workerChoiceStrategy }
1026 )
1027 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1028 dynamicWorkerUsage: false,
1029 dynamicWorkerReady: true
1030 })
1031 await pool.destroy()
1032 pool = new DynamicThreadPool(
1033 min,
1034 max,
1035 './tests/worker-files/thread/testWorker.js',
1036 { workerChoiceStrategy }
1037 )
1038 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1039 dynamicWorkerUsage: false,
1040 dynamicWorkerReady: true
1041 })
1042 // We need to clean up the resources after our test
1043 await pool.destroy()
1044 })
1045
1046 it('Verify FAIR_SHARE strategy default tasks statistics requirements', async () => {
1047 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
1048 let pool = new FixedThreadPool(
1049 max,
1050 './tests/worker-files/thread/testWorker.js',
1051 { workerChoiceStrategy }
1052 )
1053 expect(
1054 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1055 ).toStrictEqual({
1056 runTime: {
1057 aggregate: true,
1058 average: true,
1059 median: false
1060 },
1061 waitTime: {
1062 aggregate: false,
1063 average: false,
1064 median: false
1065 },
1066 elu: {
1067 aggregate: true,
1068 average: true,
1069 median: false
1070 }
1071 })
1072 await pool.destroy()
1073 pool = new DynamicThreadPool(
1074 min,
1075 max,
1076 './tests/worker-files/thread/testWorker.js',
1077 { workerChoiceStrategy }
1078 )
1079 expect(
1080 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1081 ).toStrictEqual({
1082 runTime: {
1083 aggregate: true,
1084 average: true,
1085 median: false
1086 },
1087 waitTime: {
1088 aggregate: false,
1089 average: false,
1090 median: false
1091 },
1092 elu: {
1093 aggregate: true,
1094 average: true,
1095 median: false
1096 }
1097 })
1098 // We need to clean up the resources after our test
1099 await pool.destroy()
1100 })
1101
1102 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
1103 const pool = new FixedThreadPool(
1104 max,
1105 './tests/worker-files/thread/testWorker.js',
1106 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
1107 )
1108 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1109 const promises = new Set()
1110 const maxMultiplier = 2
1111 for (let i = 0; i < max * maxMultiplier; i++) {
1112 promises.add(pool.execute())
1113 }
1114 await Promise.all(promises)
1115 for (const workerNode of pool.workerNodes) {
1116 expect(workerNode.usage).toStrictEqual({
1117 tasks: {
1118 executed: expect.any(Number),
1119 executing: 0,
1120 queued: 0,
1121 maxQueued: 0,
1122 stolen: 0,
1123 failed: 0
1124 },
1125 runTime: expect.objectContaining({
1126 history: expect.any(CircularArray)
1127 }),
1128 waitTime: {
1129 history: new CircularArray()
1130 },
1131 elu: expect.objectContaining({
1132 idle: expect.objectContaining({
1133 history: expect.any(CircularArray)
1134 }),
1135 active: expect.objectContaining({
1136 history: expect.any(CircularArray)
1137 })
1138 })
1139 })
1140 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1141 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1142 max * maxMultiplier
1143 )
1144 if (workerNode.usage.runTime.aggregate == null) {
1145 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1146 } else {
1147 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1148 }
1149 if (workerNode.usage.runTime.average == null) {
1150 expect(workerNode.usage.runTime.average).toBeUndefined()
1151 } else {
1152 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1153 }
1154 if (workerNode.usage.elu.active.aggregate == null) {
1155 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1156 } else {
1157 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1158 }
1159 if (workerNode.usage.elu.idle.aggregate == null) {
1160 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1161 } else {
1162 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1163 }
1164 if (workerNode.usage.elu.utilization == null) {
1165 expect(workerNode.usage.elu.utilization).toBeUndefined()
1166 } else {
1167 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1168 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1169 }
1170 }
1171 expect(
1172 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1173 pool.workerChoiceStrategyContext.workerChoiceStrategy
1174 ).workersVirtualTaskEndTimestamp.length
1175 ).toBe(pool.workerNodes.length)
1176 // We need to clean up the resources after our test
1177 await pool.destroy()
1178 })
1179
1180 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
1181 const pool = new DynamicThreadPool(
1182 min,
1183 max,
1184 './tests/worker-files/thread/testWorker.js',
1185 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
1186 )
1187 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1188 const promises = new Set()
1189 const maxMultiplier = 2
1190 for (let i = 0; i < max * maxMultiplier; i++) {
1191 promises.add(pool.execute())
1192 }
1193 await Promise.all(promises)
1194 for (const workerNode of pool.workerNodes) {
1195 expect(workerNode.usage).toStrictEqual({
1196 tasks: {
1197 executed: expect.any(Number),
1198 executing: 0,
1199 queued: 0,
1200 maxQueued: 0,
1201 stolen: 0,
1202 failed: 0
1203 },
1204 runTime: expect.objectContaining({
1205 history: expect.any(CircularArray)
1206 }),
1207 waitTime: {
1208 history: new CircularArray()
1209 },
1210 elu: expect.objectContaining({
1211 idle: expect.objectContaining({
1212 history: expect.any(CircularArray)
1213 }),
1214 active: expect.objectContaining({
1215 history: expect.any(CircularArray)
1216 })
1217 })
1218 })
1219 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1220 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1221 max * maxMultiplier
1222 )
1223 if (workerNode.usage.runTime.aggregate == null) {
1224 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1225 } else {
1226 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1227 }
1228 if (workerNode.usage.runTime.average == null) {
1229 expect(workerNode.usage.runTime.average).toBeUndefined()
1230 } else {
1231 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1232 }
1233 if (workerNode.usage.elu.active.aggregate == null) {
1234 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1235 } else {
1236 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1237 }
1238 if (workerNode.usage.elu.idle.aggregate == null) {
1239 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1240 } else {
1241 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1242 }
1243 if (workerNode.usage.elu.utilization == null) {
1244 expect(workerNode.usage.elu.utilization).toBeUndefined()
1245 } else {
1246 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1247 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1248 }
1249 }
1250 expect(
1251 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1252 pool.workerChoiceStrategyContext.workerChoiceStrategy
1253 ).workersVirtualTaskEndTimestamp.length
1254 ).toBe(pool.workerNodes.length)
1255 // We need to clean up the resources after our test
1256 await pool.destroy()
1257 })
1258
1259 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
1260 const pool = new DynamicThreadPool(
1261 min,
1262 max,
1263 './tests/worker-files/thread/testWorker.js',
1264 {
1265 workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE,
1266 workerChoiceStrategyOptions: {
1267 runTime: { median: true }
1268 }
1269 }
1270 )
1271 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
1272 const promises = new Set()
1273 const maxMultiplier = 2
1274 for (let i = 0; i < max * maxMultiplier; i++) {
1275 promises.add(pool.execute())
1276 }
1277 await Promise.all(promises)
1278 for (const workerNode of pool.workerNodes) {
1279 expect(workerNode.usage).toStrictEqual({
1280 tasks: {
1281 executed: expect.any(Number),
1282 executing: 0,
1283 queued: 0,
1284 maxQueued: 0,
1285 stolen: 0,
1286 failed: 0
1287 },
1288 runTime: expect.objectContaining({
1289 history: expect.any(CircularArray)
1290 }),
1291 waitTime: {
1292 history: new CircularArray()
1293 },
1294 elu: expect.objectContaining({
1295 idle: expect.objectContaining({
1296 history: expect.any(CircularArray)
1297 }),
1298 active: expect.objectContaining({
1299 history: expect.any(CircularArray)
1300 })
1301 })
1302 })
1303 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1304 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1305 max * maxMultiplier
1306 )
1307 if (workerNode.usage.runTime.aggregate == null) {
1308 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1309 } else {
1310 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1311 }
1312 if (workerNode.usage.runTime.median == null) {
1313 expect(workerNode.usage.runTime.median).toBeUndefined()
1314 } else {
1315 expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
1316 }
1317 if (workerNode.usage.elu.active.aggregate == null) {
1318 expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
1319 } else {
1320 expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
1321 }
1322 if (workerNode.usage.elu.idle.aggregate == null) {
1323 expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
1324 } else {
1325 expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
1326 }
1327 if (workerNode.usage.elu.utilization == null) {
1328 expect(workerNode.usage.elu.utilization).toBeUndefined()
1329 } else {
1330 expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
1331 expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
1332 }
1333 }
1334 expect(
1335 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1336 pool.workerChoiceStrategyContext.workerChoiceStrategy
1337 ).workersVirtualTaskEndTimestamp.length
1338 ).toBe(pool.workerNodes.length)
1339 // We need to clean up the resources after our test
1340 await pool.destroy()
1341 })
1342
1343 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
1344 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
1345 let pool = new FixedThreadPool(
1346 max,
1347 './tests/worker-files/thread/testWorker.js'
1348 )
1349 expect(
1350 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1351 workerChoiceStrategy
1352 ).workersVirtualTaskEndTimestamp
1353 ).toBeInstanceOf(Array)
1354 expect(
1355 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1356 workerChoiceStrategy
1357 ).workersVirtualTaskEndTimestamp.length
1358 ).toBe(0)
1359 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1360 workerChoiceStrategy
1361 ).workersVirtualTaskEndTimestamp[0] = performance.now()
1362 expect(
1363 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1364 workerChoiceStrategy
1365 ).workersVirtualTaskEndTimestamp.length
1366 ).toBe(1)
1367 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1368 expect(
1369 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1370 workerChoiceStrategy
1371 ).workersVirtualTaskEndTimestamp
1372 ).toBeInstanceOf(Array)
1373 expect(
1374 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1375 workerChoiceStrategy
1376 ).workersVirtualTaskEndTimestamp.length
1377 ).toBe(0)
1378 await pool.destroy()
1379 pool = new DynamicThreadPool(
1380 min,
1381 max,
1382 './tests/worker-files/thread/testWorker.js'
1383 )
1384 expect(
1385 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1386 workerChoiceStrategy
1387 ).workersVirtualTaskEndTimestamp
1388 ).toBeInstanceOf(Array)
1389 expect(
1390 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1391 workerChoiceStrategy
1392 ).workersVirtualTaskEndTimestamp.length
1393 ).toBe(0)
1394 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1395 workerChoiceStrategy
1396 ).workersVirtualTaskEndTimestamp[0] = performance.now()
1397 expect(
1398 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1399 workerChoiceStrategy
1400 ).workersVirtualTaskEndTimestamp.length
1401 ).toBe(1)
1402 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1403 expect(
1404 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1405 workerChoiceStrategy
1406 ).workersVirtualTaskEndTimestamp
1407 ).toBeInstanceOf(Array)
1408 expect(
1409 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1410 workerChoiceStrategy
1411 ).workersVirtualTaskEndTimestamp.length
1412 ).toBe(0)
1413 // We need to clean up the resources after our test
1414 await pool.destroy()
1415 })
1416
1417 it('Verify WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1418 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1419 let pool = new FixedThreadPool(
1420 max,
1421 './tests/worker-files/thread/testWorker.js',
1422 { workerChoiceStrategy }
1423 )
1424 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1425 dynamicWorkerUsage: false,
1426 dynamicWorkerReady: true
1427 })
1428 await pool.destroy()
1429 pool = new DynamicThreadPool(
1430 min,
1431 max,
1432 './tests/worker-files/thread/testWorker.js',
1433 { workerChoiceStrategy }
1434 )
1435 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1436 dynamicWorkerUsage: false,
1437 dynamicWorkerReady: true
1438 })
1439 // We need to clean up the resources after our test
1440 await pool.destroy()
1441 })
1442
1443 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
1444 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1445 let pool = new FixedThreadPool(
1446 max,
1447 './tests/worker-files/thread/testWorker.js',
1448 { workerChoiceStrategy }
1449 )
1450 expect(
1451 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1452 ).toStrictEqual({
1453 runTime: {
1454 aggregate: true,
1455 average: true,
1456 median: false
1457 },
1458 waitTime: {
1459 aggregate: false,
1460 average: false,
1461 median: false
1462 },
1463 elu: {
1464 aggregate: false,
1465 average: false,
1466 median: false
1467 }
1468 })
1469 await pool.destroy()
1470 pool = new DynamicThreadPool(
1471 min,
1472 max,
1473 './tests/worker-files/thread/testWorker.js',
1474 { workerChoiceStrategy }
1475 )
1476 expect(
1477 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1478 ).toStrictEqual({
1479 runTime: {
1480 aggregate: true,
1481 average: true,
1482 median: false
1483 },
1484 waitTime: {
1485 aggregate: false,
1486 average: false,
1487 median: false
1488 },
1489 elu: {
1490 aggregate: false,
1491 average: false,
1492 median: false
1493 }
1494 })
1495 // We need to clean up the resources after our test
1496 await pool.destroy()
1497 })
1498
1499 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1500 const pool = new FixedThreadPool(
1501 max,
1502 './tests/worker-files/thread/testWorker.js',
1503 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1504 )
1505 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1506 const promises = new Set()
1507 const maxMultiplier = 2
1508 for (let i = 0; i < max * maxMultiplier; i++) {
1509 promises.add(pool.execute())
1510 }
1511 await Promise.all(promises)
1512 for (const workerNode of pool.workerNodes) {
1513 expect(workerNode.usage).toStrictEqual({
1514 tasks: {
1515 executed: expect.any(Number),
1516 executing: 0,
1517 queued: 0,
1518 maxQueued: 0,
1519 stolen: 0,
1520 failed: 0
1521 },
1522 runTime: expect.objectContaining({
1523 history: expect.any(CircularArray)
1524 }),
1525 waitTime: {
1526 history: new CircularArray()
1527 },
1528 elu: {
1529 idle: {
1530 history: new CircularArray()
1531 },
1532 active: {
1533 history: new CircularArray()
1534 }
1535 }
1536 })
1537 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1538 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1539 max * maxMultiplier
1540 )
1541 if (workerNode.usage.runTime.aggregate == null) {
1542 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1543 } else {
1544 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1545 }
1546 if (workerNode.usage.runTime.average == null) {
1547 expect(workerNode.usage.runTime.average).toBeUndefined()
1548 } else {
1549 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1550 }
1551 }
1552 expect(
1553 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1554 pool.workerChoiceStrategyContext.workerChoiceStrategy
1555 ).defaultWorkerWeight
1556 ).toBeGreaterThan(0)
1557 expect(
1558 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1559 pool.workerChoiceStrategyContext.workerChoiceStrategy
1560 ).workerVirtualTaskRunTime
1561 ).toBeGreaterThanOrEqual(0)
1562 // We need to clean up the resources after our test
1563 await pool.destroy()
1564 })
1565
1566 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1567 const pool = new DynamicThreadPool(
1568 min,
1569 max,
1570 './tests/worker-files/thread/testWorker.js',
1571 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
1572 )
1573 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1574 const promises = new Set()
1575 const maxMultiplier = 2
1576 for (let i = 0; i < max * maxMultiplier; i++) {
1577 promises.add(pool.execute())
1578 }
1579 await Promise.all(promises)
1580 for (const workerNode of pool.workerNodes) {
1581 expect(workerNode.usage).toStrictEqual({
1582 tasks: {
1583 executed: expect.any(Number),
1584 executing: 0,
1585 queued: 0,
1586 maxQueued: 0,
1587 stolen: 0,
1588 failed: 0
1589 },
1590 runTime: expect.objectContaining({
1591 history: expect.any(CircularArray)
1592 }),
1593 waitTime: {
1594 history: new CircularArray()
1595 },
1596 elu: {
1597 idle: {
1598 history: new CircularArray()
1599 },
1600 active: {
1601 history: new CircularArray()
1602 }
1603 }
1604 })
1605 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1606 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1607 max * maxMultiplier
1608 )
1609 if (workerNode.usage.runTime.aggregate == null) {
1610 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1611 } else {
1612 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1613 }
1614 if (workerNode.usage.runTime.average == null) {
1615 expect(workerNode.usage.runTime.average).toBeUndefined()
1616 } else {
1617 expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
1618 }
1619 }
1620 expect(
1621 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1622 pool.workerChoiceStrategyContext.workerChoiceStrategy
1623 ).defaultWorkerWeight
1624 ).toBeGreaterThan(0)
1625 expect(
1626 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1627 pool.workerChoiceStrategyContext.workerChoiceStrategy
1628 ).workerVirtualTaskRunTime
1629 ).toBeGreaterThanOrEqual(0)
1630 // We need to clean up the resources after our test
1631 await pool.destroy()
1632 })
1633
1634 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
1635 const pool = new DynamicThreadPool(
1636 min,
1637 max,
1638 './tests/worker-files/thread/testWorker.js',
1639 {
1640 workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN,
1641 workerChoiceStrategyOptions: {
1642 runTime: { median: true }
1643 }
1644 }
1645 )
1646 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
1647 const promises = new Set()
1648 const maxMultiplier = 2
1649 for (let i = 0; i < max * maxMultiplier; i++) {
1650 promises.add(pool.execute())
1651 }
1652 await Promise.all(promises)
1653 for (const workerNode of pool.workerNodes) {
1654 expect(workerNode.usage).toStrictEqual({
1655 tasks: {
1656 executed: expect.any(Number),
1657 executing: 0,
1658 queued: 0,
1659 maxQueued: 0,
1660 stolen: 0,
1661 failed: 0
1662 },
1663 runTime: expect.objectContaining({
1664 history: expect.any(CircularArray)
1665 }),
1666 waitTime: {
1667 history: new CircularArray()
1668 },
1669 elu: {
1670 idle: {
1671 history: new CircularArray()
1672 },
1673 active: {
1674 history: new CircularArray()
1675 }
1676 }
1677 })
1678 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1679 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1680 max * maxMultiplier
1681 )
1682 if (workerNode.usage.runTime.aggregate == null) {
1683 expect(workerNode.usage.runTime.aggregate).toBeUndefined()
1684 } else {
1685 expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
1686 }
1687 if (workerNode.usage.runTime.median == null) {
1688 expect(workerNode.usage.runTime.median).toBeUndefined()
1689 } else {
1690 expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
1691 }
1692 }
1693 expect(
1694 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1695 pool.workerChoiceStrategyContext.workerChoiceStrategy
1696 ).defaultWorkerWeight
1697 ).toBeGreaterThan(0)
1698 expect(
1699 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1700 pool.workerChoiceStrategyContext.workerChoiceStrategy
1701 ).workerVirtualTaskRunTime
1702 ).toBeGreaterThanOrEqual(0)
1703 // We need to clean up the resources after our test
1704 await pool.destroy()
1705 })
1706
1707 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1708 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
1709 let pool = new FixedThreadPool(
1710 max,
1711 './tests/worker-files/thread/testWorker.js'
1712 )
1713 expect(
1714 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1715 workerChoiceStrategy
1716 ).nextWorkerNodeKey
1717 ).toBeDefined()
1718 expect(
1719 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1720 workerChoiceStrategy
1721 ).defaultWorkerWeight
1722 ).toBeDefined()
1723 expect(
1724 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1725 workerChoiceStrategy
1726 ).workerVirtualTaskRunTime
1727 ).toBeDefined()
1728 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1729 expect(
1730 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1731 pool.workerChoiceStrategyContext.workerChoiceStrategy
1732 ).nextWorkerNodeKey
1733 ).toBe(0)
1734 expect(
1735 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1736 pool.workerChoiceStrategyContext.workerChoiceStrategy
1737 ).defaultWorkerWeight
1738 ).toBeGreaterThan(0)
1739 expect(
1740 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1741 workerChoiceStrategy
1742 ).workerVirtualTaskRunTime
1743 ).toBe(0)
1744 await pool.destroy()
1745 pool = new DynamicThreadPool(
1746 min,
1747 max,
1748 './tests/worker-files/thread/testWorker.js'
1749 )
1750 expect(
1751 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1752 workerChoiceStrategy
1753 ).nextWorkerNodeKey
1754 ).toBeDefined()
1755 expect(
1756 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1757 workerChoiceStrategy
1758 ).defaultWorkerWeight
1759 ).toBeDefined()
1760 expect(
1761 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1762 workerChoiceStrategy
1763 ).workerVirtualTaskRunTime
1764 ).toBeDefined()
1765 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1766 expect(
1767 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1768 pool.workerChoiceStrategyContext.workerChoiceStrategy
1769 ).nextWorkerNodeKey
1770 ).toBe(0)
1771 expect(
1772 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1773 pool.workerChoiceStrategyContext.workerChoiceStrategy
1774 ).defaultWorkerWeight
1775 ).toBeGreaterThan(0)
1776 expect(
1777 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1778 workerChoiceStrategy
1779 ).workerVirtualTaskRunTime
1780 ).toBe(0)
1781 // We need to clean up the resources after our test
1782 await pool.destroy()
1783 })
1784
1785 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default policy', async () => {
1786 const workerChoiceStrategy =
1787 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1788 let pool = new FixedThreadPool(
1789 max,
1790 './tests/worker-files/thread/testWorker.js',
1791 { workerChoiceStrategy }
1792 )
1793 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1794 dynamicWorkerUsage: false,
1795 dynamicWorkerReady: true
1796 })
1797 await pool.destroy()
1798 pool = new DynamicThreadPool(
1799 min,
1800 max,
1801 './tests/worker-files/thread/testWorker.js',
1802 { workerChoiceStrategy }
1803 )
1804 expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
1805 dynamicWorkerUsage: false,
1806 dynamicWorkerReady: true
1807 })
1808 // We need to clean up the resources after our test
1809 await pool.destroy()
1810 })
1811
1812 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks statistics requirements', async () => {
1813 const workerChoiceStrategy =
1814 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1815 let pool = new FixedThreadPool(
1816 max,
1817 './tests/worker-files/thread/testWorker.js',
1818 { workerChoiceStrategy }
1819 )
1820 expect(
1821 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1822 ).toStrictEqual({
1823 runTime: {
1824 aggregate: true,
1825 average: true,
1826 median: false
1827 },
1828 waitTime: {
1829 aggregate: false,
1830 average: false,
1831 median: false
1832 },
1833 elu: {
1834 aggregate: false,
1835 average: false,
1836 median: false
1837 }
1838 })
1839 await pool.destroy()
1840 pool = new DynamicThreadPool(
1841 min,
1842 max,
1843 './tests/worker-files/thread/testWorker.js',
1844 { workerChoiceStrategy }
1845 )
1846 expect(
1847 pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
1848 ).toStrictEqual({
1849 runTime: {
1850 aggregate: true,
1851 average: true,
1852 median: false
1853 },
1854 waitTime: {
1855 aggregate: false,
1856 average: false,
1857 median: false
1858 },
1859 elu: {
1860 aggregate: false,
1861 average: false,
1862 median: false
1863 }
1864 })
1865 // We need to clean up the resources after our test
1866 await pool.destroy()
1867 })
1868
1869 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1870 const pool = new FixedThreadPool(
1871 max,
1872 './tests/worker-files/thread/testWorker.js',
1873 {
1874 workerChoiceStrategy:
1875 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1876 }
1877 )
1878 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1879 const promises = new Set()
1880 const maxMultiplier = 2
1881 for (let i = 0; i < max * maxMultiplier; i++) {
1882 promises.add(pool.execute())
1883 }
1884 await Promise.all(promises)
1885 for (const workerNode of pool.workerNodes) {
1886 expect(workerNode.usage).toStrictEqual({
1887 tasks: {
1888 executed: expect.any(Number),
1889 executing: 0,
1890 queued: 0,
1891 maxQueued: 0,
1892 stolen: 0,
1893 failed: 0
1894 },
1895 runTime: expect.objectContaining({
1896 history: expect.any(CircularArray)
1897 }),
1898 waitTime: {
1899 history: new CircularArray()
1900 },
1901 elu: {
1902 idle: {
1903 history: new CircularArray()
1904 },
1905 active: {
1906 history: new CircularArray()
1907 }
1908 }
1909 })
1910 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1911 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1912 max * maxMultiplier
1913 )
1914 }
1915 expect(
1916 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1917 pool.workerChoiceStrategyContext.workerChoiceStrategy
1918 ).defaultWorkerWeight
1919 ).toBeGreaterThan(0)
1920 expect(
1921 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1922 pool.workerChoiceStrategyContext.workerChoiceStrategy
1923 ).roundId
1924 ).toBe(0)
1925 expect(
1926 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1927 pool.workerChoiceStrategyContext.workerChoiceStrategy
1928 ).workerNodeId
1929 ).toBe(0)
1930 expect(
1931 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1932 pool.workerChoiceStrategyContext.workerChoiceStrategy
1933 ).nextWorkerNodeKey
1934 ).toBe(0)
1935 expect(
1936 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1937 pool.workerChoiceStrategyContext.workerChoiceStrategy
1938 ).roundWeights
1939 ).toStrictEqual([
1940 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1941 pool.workerChoiceStrategyContext.workerChoiceStrategy
1942 ).defaultWorkerWeight
1943 ])
1944 // We need to clean up the resources after our test
1945 await pool.destroy()
1946 })
1947
1948 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1949 const pool = new DynamicThreadPool(
1950 min,
1951 max,
1952 './tests/worker-files/thread/testWorker.js',
1953 {
1954 workerChoiceStrategy:
1955 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1956 }
1957 )
1958 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1959 const promises = new Set()
1960 const maxMultiplier = 2
1961 for (let i = 0; i < max * maxMultiplier; i++) {
1962 promises.add(pool.execute())
1963 }
1964 await Promise.all(promises)
1965 for (const workerNode of pool.workerNodes) {
1966 expect(workerNode.usage).toStrictEqual({
1967 tasks: {
1968 executed: expect.any(Number),
1969 executing: 0,
1970 queued: 0,
1971 maxQueued: 0,
1972 stolen: 0,
1973 failed: 0
1974 },
1975 runTime: expect.objectContaining({
1976 history: expect.any(CircularArray)
1977 }),
1978 waitTime: {
1979 history: new CircularArray()
1980 },
1981 elu: {
1982 idle: {
1983 history: new CircularArray()
1984 },
1985 active: {
1986 history: new CircularArray()
1987 }
1988 }
1989 })
1990 expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
1991 expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
1992 max * maxMultiplier
1993 )
1994 }
1995 expect(
1996 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1997 pool.workerChoiceStrategyContext.workerChoiceStrategy
1998 ).defaultWorkerWeight
1999 ).toBeGreaterThan(0)
2000 expect(
2001 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2002 pool.workerChoiceStrategyContext.workerChoiceStrategy
2003 ).roundId
2004 ).toBe(0)
2005 expect(
2006 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2007 pool.workerChoiceStrategyContext.workerChoiceStrategy
2008 ).workerNodeId
2009 ).toBe(0)
2010 expect(
2011 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2012 pool.workerChoiceStrategyContext.workerChoiceStrategy
2013 ).nextWorkerNodeKey
2014 ).toBe(0)
2015 expect(
2016 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2017 pool.workerChoiceStrategyContext.workerChoiceStrategy
2018 ).roundWeights
2019 ).toStrictEqual([
2020 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2021 pool.workerChoiceStrategyContext.workerChoiceStrategy
2022 ).defaultWorkerWeight
2023 ])
2024 // We need to clean up the resources after our test
2025 await pool.destroy()
2026 })
2027
2028 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
2029 const workerChoiceStrategy =
2030 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
2031 let pool = new FixedThreadPool(
2032 max,
2033 './tests/worker-files/thread/testWorker.js'
2034 )
2035 expect(
2036 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2037 workerChoiceStrategy
2038 ).roundId
2039 ).toBeDefined()
2040 expect(
2041 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2042 workerChoiceStrategy
2043 ).nextWorkerNodeKey
2044 ).toBeDefined()
2045 expect(
2046 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2047 workerChoiceStrategy
2048 ).defaultWorkerWeight
2049 ).toBeDefined()
2050 expect(
2051 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2052 workerChoiceStrategy
2053 ).roundWeights
2054 ).toBeDefined()
2055 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
2056 expect(
2057 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2058 workerChoiceStrategy
2059 ).roundId
2060 ).toBe(0)
2061 expect(
2062 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2063 pool.workerChoiceStrategyContext.workerChoiceStrategy
2064 ).nextWorkerNodeKey
2065 ).toBe(0)
2066 expect(
2067 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2068 pool.workerChoiceStrategyContext.workerChoiceStrategy
2069 ).defaultWorkerWeight
2070 ).toBeGreaterThan(0)
2071 expect(
2072 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2073 workerChoiceStrategy
2074 ).roundWeights
2075 ).toStrictEqual([
2076 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2077 pool.workerChoiceStrategyContext.workerChoiceStrategy
2078 ).defaultWorkerWeight
2079 ])
2080 await pool.destroy()
2081 pool = new DynamicThreadPool(
2082 min,
2083 max,
2084 './tests/worker-files/thread/testWorker.js'
2085 )
2086 expect(
2087 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2088 workerChoiceStrategy
2089 ).roundId
2090 ).toBeDefined()
2091 expect(
2092 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2093 workerChoiceStrategy
2094 ).nextWorkerNodeKey
2095 ).toBeDefined()
2096 expect(
2097 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2098 workerChoiceStrategy
2099 ).defaultWorkerWeight
2100 ).toBeDefined()
2101 expect(
2102 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2103 workerChoiceStrategy
2104 ).roundWeights
2105 ).toBeDefined()
2106 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
2107 expect(
2108 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2109 pool.workerChoiceStrategyContext.workerChoiceStrategy
2110 ).nextWorkerNodeKey
2111 ).toBe(0)
2112 expect(
2113 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2114 pool.workerChoiceStrategyContext.workerChoiceStrategy
2115 ).defaultWorkerWeight
2116 ).toBeGreaterThan(0)
2117 expect(
2118 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2119 workerChoiceStrategy
2120 ).roundWeights
2121 ).toStrictEqual([
2122 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
2123 pool.workerChoiceStrategyContext.workerChoiceStrategy
2124 ).defaultWorkerWeight
2125 ])
2126 // We need to clean up the resources after our test
2127 await pool.destroy()
2128 })
2129
2130 it('Verify unknown strategy throw error', () => {
2131 expect(
2132 () =>
2133 new DynamicThreadPool(
2134 min,
2135 max,
2136 './tests/worker-files/thread/testWorker.js',
2137 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
2138 )
2139 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")
2140 })
2141 })