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