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