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