perf: allow finer grained control over tasks usage computation
[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/index')
8
9 describe('Selection strategies test suite', () => {
10 const min = 0
11 const max = 3
12
13 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
14 expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN')
15 expect(WorkerChoiceStrategies.LESS_USED).toBe('LESS_USED')
16 expect(WorkerChoiceStrategies.LESS_BUSY).toBe('LESS_BUSY')
17 expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE')
18 expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe(
19 'WEIGHTED_ROUND_ROBIN'
20 )
21 })
22
23 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
24 const pool = new DynamicThreadPool(
25 min,
26 max,
27 './tests/worker-files/thread/testWorker.js'
28 )
29 expect(pool.opts.workerChoiceStrategy).toBe(
30 WorkerChoiceStrategies.ROUND_ROBIN
31 )
32 // We need to clean up the resources after our test
33 await pool.destroy()
34 })
35
36 it('Verify ROUND_ROBIN strategy is taken at pool creation', async () => {
37 const pool = new FixedThreadPool(
38 max,
39 './tests/worker-files/thread/testWorker.js',
40 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
41 )
42 expect(pool.opts.workerChoiceStrategy).toBe(
43 WorkerChoiceStrategies.ROUND_ROBIN
44 )
45 expect(
46 pool.workerChoiceStrategyContext.workerChoiceStrategy.nextWorkerId
47 ).toBe(0)
48 // We need to clean up the resources after our test
49 await pool.destroy()
50 })
51
52 it('Verify ROUND_ROBIN strategy can be set after pool creation', async () => {
53 const pool = new DynamicThreadPool(
54 min,
55 max,
56 './tests/worker-files/thread/testWorker.js'
57 )
58 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
59 expect(pool.opts.workerChoiceStrategy).toBe(
60 WorkerChoiceStrategies.ROUND_ROBIN
61 )
62 // We need to clean up the resources after our test
63 await pool.destroy()
64 })
65
66 it('Verify ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
67 let pool = new FixedThreadPool(
68 max,
69 './tests/worker-files/thread/testWorker.js'
70 )
71 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
72 expect(
73 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
74 ).toBe(false)
75 expect(
76 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
77 ).toBe(false)
78 await pool.destroy()
79 pool = new DynamicThreadPool(
80 min,
81 max,
82 './tests/worker-files/thread/testWorker.js'
83 )
84 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
85 expect(
86 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
87 ).toBe(false)
88 expect(
89 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
90 ).toBe(false)
91 // We need to clean up the resources after our test
92 await pool.destroy()
93 })
94
95 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
96 const pool = new FixedThreadPool(
97 max,
98 './tests/worker-files/thread/testWorker.js',
99 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
100 )
101 expect(pool.opts.workerChoiceStrategy).toBe(
102 WorkerChoiceStrategies.ROUND_ROBIN
103 )
104 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
105 const promises = []
106 for (let i = 0; i < max * 2; i++) {
107 promises.push(pool.execute())
108 }
109 await Promise.all(promises)
110 // We need to clean up the resources after our test
111 await pool.destroy()
112 })
113
114 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
115 const pool = new DynamicThreadPool(
116 min,
117 max,
118 './tests/worker-files/thread/testWorker.js',
119 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
120 )
121 expect(pool.opts.workerChoiceStrategy).toBe(
122 WorkerChoiceStrategies.ROUND_ROBIN
123 )
124 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
125 const promises = []
126 for (let i = 0; i < max * 2; i++) {
127 promises.push(pool.execute())
128 }
129 await Promise.all(promises)
130 // We need to clean up the resources after our test
131 await pool.destroy()
132 })
133
134 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
135 let pool = new FixedClusterPool(
136 max,
137 './tests/worker-files/cluster/testWorker.js'
138 )
139 let results = new Set()
140 for (let i = 0; i < max; i++) {
141 results.add(pool.chooseWorker()[1].id)
142 }
143 expect(results.size).toBe(max)
144 await pool.destroy()
145 pool = new FixedThreadPool(max, './tests/worker-files/thread/testWorker.js')
146 results = new Set()
147 for (let i = 0; i < max; i++) {
148 results.add(pool.chooseWorker()[1].threadId)
149 }
150 expect(results.size).toBe(max)
151 await pool.destroy()
152 })
153
154 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
155 let pool = new FixedThreadPool(
156 max,
157 './tests/worker-files/thread/testWorker.js',
158 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
159 )
160 expect(
161 pool.workerChoiceStrategyContext.workerChoiceStrategy.nextWorkerId
162 ).toBeUndefined()
163 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
164 expect(
165 pool.workerChoiceStrategyContext.workerChoiceStrategy.nextWorkerId
166 ).toBe(0)
167 await pool.destroy()
168 pool = new DynamicThreadPool(
169 min,
170 max,
171 './tests/worker-files/thread/testWorker.js',
172 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
173 )
174 expect(
175 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy
176 .nextWorkerId
177 ).toBeUndefined()
178 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.ROUND_ROBIN)
179 expect(
180 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy
181 .nextWorkerId
182 ).toBe(0)
183 // We need to clean up the resources after our test
184 await pool.destroy()
185 })
186
187 it('Verify LESS_USED strategy is taken at pool creation', async () => {
188 const pool = new FixedThreadPool(
189 max,
190 './tests/worker-files/thread/testWorker.js',
191 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED }
192 )
193 expect(pool.opts.workerChoiceStrategy).toBe(
194 WorkerChoiceStrategies.LESS_USED
195 )
196 // We need to clean up the resources after our test
197 await pool.destroy()
198 })
199
200 it('Verify LESS_USED strategy can be set after pool creation', async () => {
201 const pool = new FixedThreadPool(
202 max,
203 './tests/worker-files/thread/testWorker.js'
204 )
205 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_USED)
206 expect(pool.opts.workerChoiceStrategy).toBe(
207 WorkerChoiceStrategies.LESS_USED
208 )
209 // We need to clean up the resources after our test
210 await pool.destroy()
211 })
212
213 it('Verify LESS_USED strategy default tasks usage statistics requirements', async () => {
214 let pool = new FixedThreadPool(
215 max,
216 './tests/worker-files/thread/testWorker.js'
217 )
218 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_USED)
219 expect(
220 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
221 ).toBe(false)
222 expect(
223 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
224 ).toBe(false)
225 await pool.destroy()
226 pool = new DynamicThreadPool(
227 min,
228 max,
229 './tests/worker-files/thread/testWorker.js'
230 )
231 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_USED)
232 expect(
233 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
234 ).toBe(false)
235 expect(
236 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
237 ).toBe(false)
238 // We need to clean up the resources after our test
239 await pool.destroy()
240 })
241
242 it('Verify LESS_USED strategy can be run in a fixed pool', async () => {
243 const pool = new FixedThreadPool(
244 max,
245 './tests/worker-files/thread/testWorker.js',
246 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED }
247 )
248 // TODO: Create a better test to cover `LessUsedWorkerChoiceStrategy#choose`
249 const promises = []
250 for (let i = 0; i < max * 2; i++) {
251 promises.push(pool.execute())
252 }
253 await Promise.all(promises)
254 // We need to clean up the resources after our test
255 await pool.destroy()
256 })
257
258 it('Verify LESS_USED strategy can be run in a dynamic pool', async () => {
259 const pool = new DynamicThreadPool(
260 min,
261 max,
262 './tests/worker-files/thread/testWorker.js',
263 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED }
264 )
265 // TODO: Create a better test to cover `LessUsedWorkerChoiceStrategy#choose`
266 const promises = []
267 for (let i = 0; i < max * 2; i++) {
268 promises.push(pool.execute())
269 }
270 await Promise.all(promises)
271 // We need to clean up the resources after our test
272 await pool.destroy()
273 })
274
275 it('Verify LESS_BUSY strategy is taken at pool creation', async () => {
276 const pool = new FixedThreadPool(
277 max,
278 './tests/worker-files/thread/testWorker.js',
279 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_BUSY }
280 )
281 expect(pool.opts.workerChoiceStrategy).toBe(
282 WorkerChoiceStrategies.LESS_BUSY
283 )
284 // We need to clean up the resources after our test
285 await pool.destroy()
286 })
287
288 it('Verify LESS_BUSY strategy can be set after pool creation', async () => {
289 const pool = new FixedThreadPool(
290 max,
291 './tests/worker-files/thread/testWorker.js'
292 )
293 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_BUSY)
294 expect(pool.opts.workerChoiceStrategy).toBe(
295 WorkerChoiceStrategies.LESS_BUSY
296 )
297 // We need to clean up the resources after our test
298 await pool.destroy()
299 })
300
301 it('Verify LESS_BUSY strategy default tasks usage statistics requirements', async () => {
302 let pool = new FixedThreadPool(
303 max,
304 './tests/worker-files/thread/testWorker.js'
305 )
306 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_BUSY)
307 expect(
308 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
309 ).toBe(true)
310 expect(
311 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
312 ).toBe(false)
313 await pool.destroy()
314 pool = new DynamicThreadPool(
315 min,
316 max,
317 './tests/worker-files/thread/testWorker.js'
318 )
319 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.LESS_BUSY)
320 expect(
321 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
322 ).toBe(true)
323 expect(
324 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
325 ).toBe(false)
326 // We need to clean up the resources after our test
327 await pool.destroy()
328 })
329
330 it('Verify LESS_BUSY strategy can be run in a fixed pool', async () => {
331 const pool = new FixedThreadPool(
332 max,
333 './tests/worker-files/thread/testWorker.js',
334 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_BUSY }
335 )
336 // TODO: Create a better test to cover `LessBusyWorkerChoiceStrategy#choose`
337 const promises = []
338 for (let i = 0; i < max * 2; i++) {
339 promises.push(pool.execute())
340 }
341 await Promise.all(promises)
342 // We need to clean up the resources after our test
343 await pool.destroy()
344 })
345
346 it('Verify LESS_BUSY strategy can be run in a dynamic pool', async () => {
347 const pool = new DynamicThreadPool(
348 min,
349 max,
350 './tests/worker-files/thread/testWorker.js',
351 { workerChoiceStrategy: WorkerChoiceStrategies.LESS_BUSY }
352 )
353 // TODO: Create a better test to cover `LessBusyWorkerChoiceStrategy#choose`
354 const promises = []
355 for (let i = 0; i < max * 2; i++) {
356 promises.push(pool.execute())
357 }
358 await Promise.all(promises)
359 // We need to clean up the resources after our test
360 await pool.destroy()
361 })
362
363 it('Verify FAIR_SHARE strategy is taken at pool creation', async () => {
364 const pool = new FixedThreadPool(
365 max,
366 './tests/worker-files/thread/testWorker.js',
367 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
368 )
369 expect(pool.opts.workerChoiceStrategy).toBe(
370 WorkerChoiceStrategies.FAIR_SHARE
371 )
372 for (const workerKey of pool.workerChoiceStrategyContext.workerChoiceStrategy.workerLastVirtualTaskTimestamp.keys()) {
373 expect(
374 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerLastVirtualTaskTimestamp.get(
375 workerKey
376 ).start
377 ).toBe(0)
378 expect(
379 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerLastVirtualTaskTimestamp.get(
380 workerKey
381 ).end
382 ).toBe(0)
383 }
384 // We need to clean up the resources after our test
385 await pool.destroy()
386 })
387
388 it('Verify FAIR_SHARE strategy can be set after pool creation', async () => {
389 const pool = new FixedThreadPool(
390 max,
391 './tests/worker-files/thread/testWorker.js'
392 )
393 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
394 expect(pool.opts.workerChoiceStrategy).toBe(
395 WorkerChoiceStrategies.FAIR_SHARE
396 )
397 // We need to clean up the resources after our test
398 await pool.destroy()
399 })
400
401 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
402 let pool = new FixedThreadPool(
403 max,
404 './tests/worker-files/thread/testWorker.js'
405 )
406 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
407 expect(
408 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
409 ).toBe(true)
410 expect(
411 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
412 ).toBe(true)
413 await pool.destroy()
414 pool = new DynamicThreadPool(
415 min,
416 max,
417 './tests/worker-files/thread/testWorker.js'
418 )
419 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
420 expect(
421 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
422 ).toBe(true)
423 expect(
424 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
425 ).toBe(true)
426 // We need to clean up the resources after our test
427 await pool.destroy()
428 })
429
430 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
431 const pool = new FixedThreadPool(
432 max,
433 './tests/worker-files/thread/testWorker.js',
434 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
435 )
436 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
437 const promises = []
438 for (let i = 0; i < max * 2; i++) {
439 promises.push(pool.execute())
440 }
441 await Promise.all(promises)
442 expect(
443 pool.workerChoiceStrategyContext.workerChoiceStrategy
444 .workerLastVirtualTaskTimestamp.size
445 ).toBe(pool.workers.length)
446 // We need to clean up the resources after our test
447 await pool.destroy()
448 })
449
450 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
451 const pool = new DynamicThreadPool(
452 min,
453 max,
454 './tests/worker-files/thread/testWorker.js',
455 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
456 )
457 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
458 const promises = []
459 const maxMultiplier = 2
460 for (let i = 0; i < max * maxMultiplier; i++) {
461 promises.push(pool.execute())
462 }
463 await Promise.all(promises)
464 // if (process.platform !== 'win32') {
465 // expect(
466 // pool.workerChoiceStrategyContext.workerChoiceStrategy
467 // .workerChoiceStrategy.workerLastVirtualTaskTimestamp.size
468 // ).toBe(pool.workers.length)
469 // }
470 // We need to clean up the resources after our test
471 await pool.destroy()
472 })
473
474 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
475 let pool = new FixedThreadPool(
476 max,
477 './tests/worker-files/thread/testWorker.js'
478 )
479 expect(
480 pool.workerChoiceStrategyContext.workerChoiceStrategy
481 .workerLastVirtualTaskTimestamp
482 ).toBeUndefined()
483 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
484 for (const workerKey of pool.workerChoiceStrategyContext.workerChoiceStrategy.workerLastVirtualTaskTimestamp.keys()) {
485 expect(
486 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerLastVirtualTaskTimestamp.get(
487 workerKey
488 ).start
489 ).toBe(0)
490 expect(
491 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerLastVirtualTaskTimestamp.get(
492 workerKey
493 ).end
494 ).toBe(0)
495 }
496 await pool.destroy()
497 pool = new DynamicThreadPool(
498 min,
499 max,
500 './tests/worker-files/thread/testWorker.js'
501 )
502 expect(
503 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy
504 .workerLastVirtualTaskTimestamp
505 ).toBeUndefined()
506 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.FAIR_SHARE)
507 for (const workerKey of pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy.workerLastVirtualTaskTimestamp.keys()) {
508 expect(
509 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy.workerLastVirtualTaskTimestamp.get(
510 workerKey
511 ).start
512 ).toBe(0)
513 expect(
514 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy.workerLastVirtualTaskTimestamp.get(
515 workerKey
516 ).end
517 ).toBe(0)
518 }
519 // We need to clean up the resources after our test
520 await pool.destroy()
521 })
522
523 it('Verify WEIGHTED_ROUND_ROBIN strategy is taken at pool creation', async () => {
524 const pool = new FixedThreadPool(
525 max,
526 './tests/worker-files/thread/testWorker.js',
527 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
528 )
529 expect(pool.opts.workerChoiceStrategy).toBe(
530 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
531 )
532 expect(
533 pool.workerChoiceStrategyContext.workerChoiceStrategy.currentWorkerId
534 ).toBe(0)
535 expect(
536 pool.workerChoiceStrategyContext.workerChoiceStrategy.defaultWorkerWeight
537 ).toBeGreaterThan(0)
538 for (const workerKey of pool.workerChoiceStrategyContext.workerChoiceStrategy.workersTaskRunTime.keys()) {
539 expect(
540 pool.workerChoiceStrategyContext.workerChoiceStrategy.workersTaskRunTime.get(
541 workerKey
542 ).weight
543 ).toBeGreaterThan(0)
544 expect(
545 pool.workerChoiceStrategyContext.workerChoiceStrategy.workersTaskRunTime.get(
546 workerKey
547 ).runTime
548 ).toBe(0)
549 }
550 // We need to clean up the resources after our test
551 await pool.destroy()
552 })
553
554 it('Verify WEIGHTED_ROUND_ROBIN strategy can be set after pool creation', async () => {
555 const pool = new FixedThreadPool(
556 max,
557 './tests/worker-files/thread/testWorker.js'
558 )
559 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
560 expect(pool.opts.workerChoiceStrategy).toBe(
561 WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
562 )
563 // We need to clean up the resources after our test
564 await pool.destroy()
565 })
566
567 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
568 let pool = new FixedThreadPool(
569 max,
570 './tests/worker-files/thread/testWorker.js'
571 )
572 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
573 expect(
574 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
575 ).toBe(true)
576 expect(
577 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
578 ).toBe(true)
579 await pool.destroy()
580 pool = new DynamicThreadPool(
581 min,
582 max,
583 './tests/worker-files/thread/testWorker.js'
584 )
585 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
586 expect(
587 pool.workerChoiceStrategyContext.getRequiredStatistics().runTime
588 ).toBe(true)
589 expect(
590 pool.workerChoiceStrategyContext.getRequiredStatistics().avgRunTime
591 ).toBe(true)
592 // We need to clean up the resources after our test
593 await pool.destroy()
594 })
595
596 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
597 const pool = new FixedThreadPool(
598 max,
599 './tests/worker-files/thread/testWorker.js',
600 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
601 )
602 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
603 const promises = []
604 for (let i = 0; i < max * 2; i++) {
605 promises.push(pool.execute())
606 }
607 await Promise.all(promises)
608 expect(
609 pool.workerChoiceStrategyContext.workerChoiceStrategy.workersTaskRunTime
610 .size
611 ).toBe(pool.workers.length)
612 // We need to clean up the resources after our test
613 await pool.destroy()
614 })
615
616 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
617 const pool = new DynamicThreadPool(
618 min,
619 max,
620 './tests/worker-files/thread/testWorker.js',
621 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
622 )
623 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
624 const promises = []
625 const maxMultiplier =
626 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy
627 .defaultWorkerWeight * 2
628 for (let i = 0; i < max * maxMultiplier; i++) {
629 promises.push(pool.execute())
630 }
631 await Promise.all(promises)
632 if (process.platform !== 'win32') {
633 expect(
634 pool.workerChoiceStrategyContext.workerChoiceStrategy
635 .workerChoiceStrategy.workersTaskRunTime.size
636 ).toBe(pool.workers.length)
637 }
638 // We need to clean up the resources after our test
639 await pool.destroy()
640 })
641
642 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
643 let pool = new FixedThreadPool(
644 max,
645 './tests/worker-files/thread/testWorker.js'
646 )
647 expect(
648 pool.workerChoiceStrategyContext.workerChoiceStrategy.currentWorkerId
649 ).toBeUndefined()
650 expect(
651 pool.workerChoiceStrategyContext.workerChoiceStrategy.defaultWorkerWeight
652 ).toBeUndefined()
653 expect(
654 pool.workerChoiceStrategyContext.workerChoiceStrategy.workersTaskRunTime
655 ).toBeUndefined()
656 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
657 expect(
658 pool.workerChoiceStrategyContext.workerChoiceStrategy.currentWorkerId
659 ).toBe(0)
660 expect(
661 pool.workerChoiceStrategyContext.workerChoiceStrategy.defaultWorkerWeight
662 ).toBeGreaterThan(0)
663 for (const workerKey of pool.workerChoiceStrategyContext.workerChoiceStrategy.workersTaskRunTime.keys()) {
664 expect(
665 pool.workerChoiceStrategyContext.workerChoiceStrategy.workersTaskRunTime.get(
666 workerKey
667 ).runTime
668 ).toBe(0)
669 }
670 await pool.destroy()
671 pool = new DynamicThreadPool(
672 min,
673 max,
674 './tests/worker-files/thread/testWorker.js'
675 )
676 expect(
677 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy
678 .currentWorkerId
679 ).toBeUndefined()
680 expect(
681 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy
682 .defaultWorkerWeight
683 ).toBeUndefined()
684 expect(
685 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy
686 .workersTaskRunTime
687 ).toBeUndefined()
688 pool.setWorkerChoiceStrategy(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN)
689 expect(
690 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy
691 .currentWorkerId
692 ).toBe(0)
693 expect(
694 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy
695 .defaultWorkerWeight
696 ).toBeGreaterThan(0)
697 for (const workerKey of pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy.workersTaskRunTime.keys()) {
698 expect(
699 pool.workerChoiceStrategyContext.workerChoiceStrategy.workerChoiceStrategy.workersTaskRunTime.get(
700 workerKey
701 ).runTime
702 ).toBe(0)
703 }
704 // We need to clean up the resources after our test
705 await pool.destroy()
706 })
707
708 it('Verify unknown strategies throw error', () => {
709 expect(
710 () =>
711 new DynamicThreadPool(
712 min,
713 max,
714 './tests/worker-files/thread/testWorker.js',
715 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
716 )
717 ).toThrowError(
718 new Error("Worker choice strategy 'UNKNOWN_STRATEGY' not found")
719 )
720 })
721 })