fix: ensure the least busy strategy only relies on task runtime
[poolifier.git] / tests / pools / selection-strategies / selection-strategies.test.js
CommitLineData
a61a0724 1const { expect } = require('expect')
a35560ba
S
2const {
3 WorkerChoiceStrategies,
4 DynamicThreadPool,
2ced693a
JB
5 FixedThreadPool,
6 FixedClusterPool
cdace0e5 7} = require('../../../lib')
86bf340d 8const { CircularArray } = require('../../../lib/circular-array')
a35560ba
S
9
10describe('Selection strategies test suite', () => {
e1ffb94f
JB
11 const min = 0
12 const max = 3
13
a35560ba
S
14 it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
15 expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN')
e4543b14
JB
16 expect(WorkerChoiceStrategies.LEAST_USED).toBe('LEAST_USED')
17 expect(WorkerChoiceStrategies.LEAST_BUSY).toBe('LEAST_BUSY')
23ff945a 18 expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE')
b3432a63
JB
19 expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe(
20 'WEIGHTED_ROUND_ROBIN'
21 )
feec6e8c
JB
22 expect(WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN).toBe(
23 'INTERLEAVED_WEIGHTED_ROUND_ROBIN'
24 )
a35560ba
S
25 })
26
e843b904 27 it('Verify ROUND_ROBIN strategy is the default at pool creation', async () => {
e843b904
JB
28 const pool = new DynamicThreadPool(
29 min,
30 max,
31 './tests/worker-files/thread/testWorker.js'
32 )
33 expect(pool.opts.workerChoiceStrategy).toBe(
34 WorkerChoiceStrategies.ROUND_ROBIN
35 )
36 // We need to clean up the resources after our test
37 await pool.destroy()
38 })
39
594bfb84
JB
40 it('Verify available strategies are taken at pool creation', async () => {
41 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
42 const pool = new FixedThreadPool(
43 max,
44 './tests/worker-files/thread/testWorker.js',
45 { workerChoiceStrategy }
46 )
47 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
48 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
49 workerChoiceStrategy
50 )
51 await pool.destroy()
52 }
d2f7b7a2
JB
53 })
54
594bfb84
JB
55 it('Verify available strategies can be set after pool creation', async () => {
56 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
57 const pool = new DynamicThreadPool(
58 min,
59 max,
ec82cfa1 60 './tests/worker-files/thread/testWorker.js'
594bfb84
JB
61 )
62 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
63 expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
64 expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
65 workerChoiceStrategy
66 )
67 await pool.destroy()
68 }
69 })
70
71 it('Verify available strategies default internals at pool creation', async () => {
72 const pool = new FixedThreadPool(
e843b904
JB
73 max,
74 './tests/worker-files/thread/testWorker.js'
75 )
594bfb84
JB
76 for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
77 if (workerChoiceStrategy === WorkerChoiceStrategies.ROUND_ROBIN) {
78 expect(
79 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
80 workerChoiceStrategy
81 ).nextWorkerNodeId
82 ).toBe(0)
83 } else if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) {
08f3f44c
JB
84 expect(
85 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
86 workerChoiceStrategy
b0d6ed8f 87 ).workersVirtualTaskEndTimestamp
08f3f44c
JB
88 ).toBeInstanceOf(Array)
89 expect(
90 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
91 workerChoiceStrategy
b0d6ed8f 92 ).workersVirtualTaskEndTimestamp.length
08f3f44c 93 ).toBe(0)
594bfb84
JB
94 } else if (
95 workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
96 ) {
97 expect(
98 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
99 workerChoiceStrategy
100 ).currentWorkerNodeId
101 ).toBe(0)
102 expect(
103 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
104 workerChoiceStrategy
105 ).defaultWorkerWeight
106 ).toBeGreaterThan(0)
08f3f44c
JB
107 expect(
108 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
109 workerChoiceStrategy
110 ).workerVirtualTaskRunTime
111 ).toBe(0)
594bfb84
JB
112 }
113 }
e843b904
JB
114 await pool.destroy()
115 })
116
10fcfaf4 117 it('Verify ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
594bfb84 118 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
10fcfaf4
JB
119 let pool = new FixedThreadPool(
120 max,
d710242d 121 './tests/worker-files/thread/testWorker.js',
594bfb84 122 { workerChoiceStrategy }
10fcfaf4 123 )
b6b32453 124 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
125 runTime: false,
126 avgRunTime: false,
127 medRunTime: false,
128 waitTime: false,
129 avgWaitTime: false,
d44d5953
JB
130 medWaitTime: false,
131 elu: false
86bf340d 132 })
fd7ebd49 133 await pool.destroy()
10fcfaf4
JB
134 pool = new DynamicThreadPool(
135 min,
136 max,
d710242d 137 './tests/worker-files/thread/testWorker.js',
594bfb84 138 { workerChoiceStrategy }
10fcfaf4 139 )
b6b32453 140 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
141 runTime: false,
142 avgRunTime: false,
143 medRunTime: false,
144 waitTime: false,
145 avgWaitTime: false,
d44d5953
JB
146 medWaitTime: false,
147 elu: false
86bf340d 148 })
10fcfaf4
JB
149 // We need to clean up the resources after our test
150 await pool.destroy()
151 })
152
bdaf31cd 153 it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
bdaf31cd
JB
154 const pool = new FixedThreadPool(
155 max,
156 './tests/worker-files/thread/testWorker.js',
157 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
158 )
bdaf31cd 159 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
ee9f5295 160 const promises = new Set()
a20f0ba5
JB
161 const maxMultiplier = 2
162 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 163 promises.add(pool.execute())
e211bc18
JB
164 }
165 await Promise.all(promises)
166 for (const workerNode of pool.workerNodes) {
167 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 168 ran: maxMultiplier,
e211bc18
JB
169 running: 0,
170 runTime: 0,
171 runTimeHistory: expect.any(CircularArray),
172 avgRunTime: 0,
173 medRunTime: 0,
174 waitTime: 0,
175 waitTimeHistory: expect.any(CircularArray),
176 avgWaitTime: 0,
177 medWaitTime: 0,
d44d5953
JB
178 error: 0,
179 elu: undefined
e211bc18 180 })
bdaf31cd 181 }
9458090a
JB
182 expect(
183 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
184 WorkerChoiceStrategies.ROUND_ROBIN
185 ).nextWorkerNodeId
186 ).toBe(0)
bdaf31cd
JB
187 // We need to clean up the resources after our test
188 await pool.destroy()
189 })
190
191 it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
bdaf31cd
JB
192 const pool = new DynamicThreadPool(
193 min,
194 max,
195 './tests/worker-files/thread/testWorker.js',
196 { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
197 )
bdaf31cd 198 // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
ee9f5295 199 const promises = new Set()
a20f0ba5
JB
200 const maxMultiplier = 2
201 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 202 promises.add(pool.execute())
e211bc18
JB
203 }
204 await Promise.all(promises)
205 for (const workerNode of pool.workerNodes) {
206 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 207 ran: maxMultiplier,
e211bc18
JB
208 running: 0,
209 runTime: 0,
210 runTimeHistory: expect.any(CircularArray),
211 avgRunTime: 0,
212 medRunTime: 0,
213 waitTime: 0,
214 waitTimeHistory: expect.any(CircularArray),
215 avgWaitTime: 0,
216 medWaitTime: 0,
d44d5953
JB
217 error: 0,
218 elu: undefined
e211bc18 219 })
bdaf31cd 220 }
9458090a
JB
221 expect(
222 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
223 WorkerChoiceStrategies.ROUND_ROBIN
224 ).nextWorkerNodeId
225 ).toBe(0)
bdaf31cd
JB
226 // We need to clean up the resources after our test
227 await pool.destroy()
228 })
229
2ced693a 230 it('Verify ROUND_ROBIN strategy runtime behavior', async () => {
594bfb84 231 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
2ced693a
JB
232 let pool = new FixedClusterPool(
233 max,
594bfb84
JB
234 './tests/worker-files/cluster/testWorker.js',
235 { workerChoiceStrategy }
2ced693a
JB
236 )
237 let results = new Set()
238 for (let i = 0; i < max; i++) {
20dcad1a 239 results.add(pool.workerNodes[pool.chooseWorkerNode()].worker.id)
2ced693a
JB
240 }
241 expect(results.size).toBe(max)
242 await pool.destroy()
594bfb84
JB
243 pool = new FixedThreadPool(
244 max,
245 './tests/worker-files/thread/testWorker.js',
246 { workerChoiceStrategy }
247 )
2ced693a
JB
248 results = new Set()
249 for (let i = 0; i < max; i++) {
20dcad1a 250 results.add(pool.workerNodes[pool.chooseWorkerNode()].worker.threadId)
2ced693a
JB
251 }
252 expect(results.size).toBe(max)
253 await pool.destroy()
254 })
255
a6f7f1b4 256 it('Verify ROUND_ROBIN strategy internals are resets after setting it', async () => {
594bfb84 257 const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
a6f7f1b4
JB
258 let pool = new FixedThreadPool(
259 max,
260 './tests/worker-files/thread/testWorker.js',
261 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
262 )
38f6e859 263 expect(
95c83464 264 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 265 workerChoiceStrategy
f06e48d8 266 ).nextWorkerNodeId
b529c323 267 ).toBeDefined()
594bfb84 268 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 269 expect(
95c83464 270 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 271 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 272 ).nextWorkerNodeId
a6f7f1b4
JB
273 ).toBe(0)
274 await pool.destroy()
275 pool = new DynamicThreadPool(
276 min,
277 max,
278 './tests/worker-files/thread/testWorker.js',
279 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
280 )
38f6e859 281 expect(
95c83464 282 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 283 workerChoiceStrategy
f06e48d8 284 ).nextWorkerNodeId
b529c323 285 ).toBeDefined()
594bfb84 286 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 287 expect(
95c83464 288 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 289 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 290 ).nextWorkerNodeId
a6f7f1b4
JB
291 ).toBe(0)
292 // We need to clean up the resources after our test
293 await pool.destroy()
294 })
295
e4543b14
JB
296 it('Verify LEAST_USED strategy default tasks usage statistics requirements', async () => {
297 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
10fcfaf4
JB
298 let pool = new FixedThreadPool(
299 max,
d710242d 300 './tests/worker-files/thread/testWorker.js',
594bfb84 301 { workerChoiceStrategy }
10fcfaf4 302 )
b6b32453 303 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
304 runTime: false,
305 avgRunTime: false,
306 medRunTime: false,
307 waitTime: false,
308 avgWaitTime: false,
d44d5953
JB
309 medWaitTime: false,
310 elu: false
86bf340d 311 })
fd7ebd49 312 await pool.destroy()
10fcfaf4
JB
313 pool = new DynamicThreadPool(
314 min,
315 max,
d710242d 316 './tests/worker-files/thread/testWorker.js',
594bfb84 317 { workerChoiceStrategy }
10fcfaf4 318 )
b6b32453 319 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
320 runTime: false,
321 avgRunTime: false,
322 medRunTime: false,
323 waitTime: false,
324 avgWaitTime: false,
d44d5953
JB
325 medWaitTime: false,
326 elu: false
86bf340d 327 })
10fcfaf4
JB
328 // We need to clean up the resources after our test
329 await pool.destroy()
330 })
331
e4543b14 332 it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
b98ec2e6
JB
333 const pool = new FixedThreadPool(
334 max,
335 './tests/worker-files/thread/testWorker.js',
e4543b14 336 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
b98ec2e6 337 )
e4543b14 338 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
ee9f5295 339 const promises = new Set()
a20f0ba5
JB
340 const maxMultiplier = 2
341 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 342 promises.add(pool.execute())
e211bc18
JB
343 }
344 await Promise.all(promises)
345 for (const workerNode of pool.workerNodes) {
346 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 347 ran: maxMultiplier,
e211bc18
JB
348 running: 0,
349 runTime: 0,
350 runTimeHistory: expect.any(CircularArray),
351 avgRunTime: 0,
352 medRunTime: 0,
353 waitTime: 0,
354 waitTimeHistory: expect.any(CircularArray),
355 avgWaitTime: 0,
356 medWaitTime: 0,
d44d5953
JB
357 error: 0,
358 elu: undefined
e211bc18 359 })
a35560ba 360 }
a35560ba
S
361 // We need to clean up the resources after our test
362 await pool.destroy()
363 })
364
e4543b14 365 it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
ff5e76e1
JB
366 const pool = new DynamicThreadPool(
367 min,
368 max,
369 './tests/worker-files/thread/testWorker.js',
e4543b14 370 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
ff5e76e1 371 )
e4543b14 372 // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
ee9f5295 373 const promises = new Set()
a20f0ba5
JB
374 const maxMultiplier = 2
375 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 376 promises.add(pool.execute())
e211bc18
JB
377 }
378 await Promise.all(promises)
379 for (const workerNode of pool.workerNodes) {
380 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 381 ran: maxMultiplier,
e211bc18
JB
382 running: 0,
383 runTime: 0,
384 runTimeHistory: expect.any(CircularArray),
385 avgRunTime: 0,
386 medRunTime: 0,
387 waitTime: 0,
388 waitTimeHistory: expect.any(CircularArray),
389 avgWaitTime: 0,
390 medWaitTime: 0,
d44d5953
JB
391 error: 0,
392 elu: undefined
e211bc18 393 })
168c526f 394 }
168c526f
JB
395 // We need to clean up the resources after our test
396 await pool.destroy()
397 })
398
e4543b14
JB
399 it('Verify LEAST_BUSY strategy default tasks usage statistics requirements', async () => {
400 const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
168c526f
JB
401 let pool = new FixedThreadPool(
402 max,
d710242d 403 './tests/worker-files/thread/testWorker.js',
594bfb84 404 { workerChoiceStrategy }
168c526f 405 )
b6b32453 406 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
407 runTime: true,
408 avgRunTime: false,
409 medRunTime: false,
410 waitTime: false,
411 avgWaitTime: false,
d44d5953
JB
412 medWaitTime: false,
413 elu: false
86bf340d 414 })
168c526f
JB
415 await pool.destroy()
416 pool = new DynamicThreadPool(
417 min,
418 max,
d710242d 419 './tests/worker-files/thread/testWorker.js',
594bfb84 420 { workerChoiceStrategy }
168c526f 421 )
b6b32453 422 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
423 runTime: true,
424 avgRunTime: false,
425 medRunTime: false,
426 waitTime: false,
427 avgWaitTime: false,
d44d5953
JB
428 medWaitTime: false,
429 elu: false
86bf340d 430 })
168c526f
JB
431 // We need to clean up the resources after our test
432 await pool.destroy()
433 })
434
e4543b14 435 it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
168c526f
JB
436 const pool = new FixedThreadPool(
437 max,
438 './tests/worker-files/thread/testWorker.js',
e4543b14 439 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
168c526f 440 )
e4543b14 441 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
ee9f5295 442 const promises = new Set()
a20f0ba5
JB
443 const maxMultiplier = 2
444 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 445 promises.add(pool.execute())
e211bc18
JB
446 }
447 await Promise.all(promises)
448 for (const workerNode of pool.workerNodes) {
449 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 450 ran: expect.any(Number),
e211bc18
JB
451 running: 0,
452 runTime: expect.any(Number),
453 runTimeHistory: expect.any(CircularArray),
454 avgRunTime: 0,
455 medRunTime: 0,
456 waitTime: 0,
457 waitTimeHistory: expect.any(CircularArray),
458 avgWaitTime: 0,
459 medWaitTime: 0,
d44d5953
JB
460 error: 0,
461 elu: undefined
e211bc18 462 })
272d4d8f 463 expect(workerNode.tasksUsage.ran).toBeGreaterThanOrEqual(0)
1ab50fe5 464 expect(workerNode.tasksUsage.ran).toBeLessThanOrEqual(max * maxMultiplier)
272d4d8f 465 expect(workerNode.tasksUsage.runTime).toBeGreaterThanOrEqual(0)
168c526f 466 }
168c526f
JB
467 // We need to clean up the resources after our test
468 await pool.destroy()
469 })
470
e4543b14 471 it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
168c526f
JB
472 const pool = new DynamicThreadPool(
473 min,
474 max,
475 './tests/worker-files/thread/testWorker.js',
e4543b14 476 { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
168c526f 477 )
e4543b14 478 // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
ee9f5295 479 const promises = new Set()
a20f0ba5
JB
480 const maxMultiplier = 2
481 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 482 promises.add(pool.execute())
e211bc18
JB
483 }
484 await Promise.all(promises)
485 for (const workerNode of pool.workerNodes) {
486 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 487 ran: expect.any(Number),
e211bc18
JB
488 running: 0,
489 runTime: expect.any(Number),
490 runTimeHistory: expect.any(CircularArray),
491 avgRunTime: 0,
492 medRunTime: 0,
493 waitTime: 0,
494 waitTimeHistory: expect.any(CircularArray),
495 avgWaitTime: 0,
496 medWaitTime: 0,
d44d5953
JB
497 error: 0,
498 elu: undefined
e211bc18 499 })
1ab50fe5
JB
500 expect(workerNode.tasksUsage.ran).toBeGreaterThan(0)
501 expect(workerNode.tasksUsage.ran).toBeLessThanOrEqual(max * maxMultiplier)
e211bc18 502 expect(workerNode.tasksUsage.runTime).toBeGreaterThan(0)
ff5e76e1 503 }
ff5e76e1
JB
504 // We need to clean up the resources after our test
505 await pool.destroy()
506 })
507
10fcfaf4 508 it('Verify FAIR_SHARE strategy default tasks usage statistics requirements', async () => {
594bfb84 509 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
10fcfaf4
JB
510 let pool = new FixedThreadPool(
511 max,
d710242d 512 './tests/worker-files/thread/testWorker.js',
594bfb84 513 { workerChoiceStrategy }
10fcfaf4 514 )
b6b32453 515 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
516 runTime: true,
517 avgRunTime: true,
518 medRunTime: false,
519 waitTime: false,
520 avgWaitTime: false,
d44d5953
JB
521 medWaitTime: false,
522 elu: false
86bf340d 523 })
fd7ebd49 524 await pool.destroy()
10fcfaf4
JB
525 pool = new DynamicThreadPool(
526 min,
527 max,
d710242d 528 './tests/worker-files/thread/testWorker.js',
594bfb84 529 { workerChoiceStrategy }
10fcfaf4 530 )
b6b32453 531 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
532 runTime: true,
533 avgRunTime: true,
534 medRunTime: false,
535 waitTime: false,
536 avgWaitTime: false,
d44d5953
JB
537 medWaitTime: false,
538 elu: false
86bf340d 539 })
10fcfaf4
JB
540 // We need to clean up the resources after our test
541 await pool.destroy()
542 })
543
23ff945a 544 it('Verify FAIR_SHARE strategy can be run in a fixed pool', async () => {
23ff945a
JB
545 const pool = new FixedThreadPool(
546 max,
547 './tests/worker-files/thread/testWorker.js',
548 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
549 )
550 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
ee9f5295 551 const promises = new Set()
a20f0ba5
JB
552 const maxMultiplier = 2
553 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 554 promises.add(pool.execute())
23ff945a 555 }
e211bc18 556 await Promise.all(promises)
138d29a8 557 for (const workerNode of pool.workerNodes) {
86bf340d 558 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 559 ran: maxMultiplier,
86bf340d
JB
560 running: 0,
561 runTime: expect.any(Number),
562 runTimeHistory: expect.any(CircularArray),
563 avgRunTime: expect.any(Number),
564 medRunTime: 0,
565 waitTime: 0,
566 waitTimeHistory: expect.any(CircularArray),
567 avgWaitTime: 0,
568 medWaitTime: 0,
d44d5953
JB
569 error: 0,
570 elu: undefined
86bf340d 571 })
e211bc18
JB
572 expect(workerNode.tasksUsage.runTime).toBeGreaterThan(0)
573 expect(workerNode.tasksUsage.avgRunTime).toBeGreaterThan(0)
138d29a8 574 }
97a2abc3 575 expect(
95c83464 576 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 577 pool.workerChoiceStrategyContext.workerChoiceStrategy
b0d6ed8f 578 ).workersVirtualTaskEndTimestamp.length
f06e48d8 579 ).toBe(pool.workerNodes.length)
23ff945a
JB
580 // We need to clean up the resources after our test
581 await pool.destroy()
582 })
583
584 it('Verify FAIR_SHARE strategy can be run in a dynamic pool', async () => {
23ff945a
JB
585 const pool = new DynamicThreadPool(
586 min,
587 max,
588 './tests/worker-files/thread/testWorker.js',
589 { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE }
590 )
591 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
ee9f5295 592 const promises = new Set()
f7070eee 593 const maxMultiplier = 2
804a889e 594 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 595 promises.add(pool.execute())
23ff945a 596 }
e211bc18 597 await Promise.all(promises)
138d29a8 598 for (const workerNode of pool.workerNodes) {
86bf340d 599 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 600 ran: maxMultiplier,
86bf340d
JB
601 running: 0,
602 runTime: expect.any(Number),
603 runTimeHistory: expect.any(CircularArray),
604 avgRunTime: expect.any(Number),
605 medRunTime: 0,
606 waitTime: 0,
607 waitTimeHistory: expect.any(CircularArray),
608 avgWaitTime: 0,
609 medWaitTime: 0,
d44d5953
JB
610 error: 0,
611 elu: undefined
86bf340d 612 })
e211bc18
JB
613 expect(workerNode.tasksUsage.runTime).toBeGreaterThan(0)
614 expect(workerNode.tasksUsage.avgRunTime).toBeGreaterThan(0)
138d29a8 615 }
2b4fddb8
JB
616 expect(
617 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
618 pool.workerChoiceStrategyContext.workerChoiceStrategy
b0d6ed8f 619 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 620 ).toBe(pool.workerNodes.length)
23ff945a
JB
621 // We need to clean up the resources after our test
622 await pool.destroy()
623 })
624
9e775f96 625 it('Verify FAIR_SHARE strategy can be run in a dynamic pool with median runtime statistic', async () => {
010d7020
JB
626 const pool = new DynamicThreadPool(
627 min,
628 max,
629 './tests/worker-files/thread/testWorker.js',
630 {
631 workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE,
632 workerChoiceStrategyOptions: {
633 medRunTime: true
634 }
635 }
636 )
637 // TODO: Create a better test to cover `FairShareChoiceStrategy#choose`
ee9f5295 638 const promises = new Set()
010d7020
JB
639 const maxMultiplier = 2
640 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 641 promises.add(pool.execute())
010d7020 642 }
e211bc18 643 await Promise.all(promises)
010d7020 644 for (const workerNode of pool.workerNodes) {
86bf340d 645 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 646 ran: maxMultiplier,
86bf340d
JB
647 running: 0,
648 runTime: expect.any(Number),
649 runTimeHistory: expect.any(CircularArray),
650 avgRunTime: 0,
651 medRunTime: expect.any(Number),
652 waitTime: 0,
653 waitTimeHistory: expect.any(CircularArray),
654 avgWaitTime: 0,
655 medWaitTime: 0,
d44d5953
JB
656 error: 0,
657 elu: undefined
86bf340d 658 })
e211bc18
JB
659 expect(workerNode.tasksUsage.runTime).toBeGreaterThan(0)
660 expect(workerNode.tasksUsage.medRunTime).toBeGreaterThan(0)
010d7020 661 }
2b4fddb8
JB
662 expect(
663 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
664 pool.workerChoiceStrategyContext.workerChoiceStrategy
b0d6ed8f 665 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 666 ).toBe(pool.workerNodes.length)
010d7020
JB
667 // We need to clean up the resources after our test
668 await pool.destroy()
669 })
670
a6f7f1b4 671 it('Verify FAIR_SHARE strategy internals are resets after setting it', async () => {
594bfb84 672 const workerChoiceStrategy = WorkerChoiceStrategies.FAIR_SHARE
f0829c53 673 let pool = new FixedThreadPool(
caeb9817
JB
674 max,
675 './tests/worker-files/thread/testWorker.js'
676 )
677 expect(
95c83464 678 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 679 workerChoiceStrategy
b0d6ed8f 680 ).workersVirtualTaskEndTimestamp
08f3f44c
JB
681 ).toBeInstanceOf(Array)
682 expect(
683 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
684 workerChoiceStrategy
b0d6ed8f 685 ).workersVirtualTaskEndTimestamp.length
08f3f44c 686 ).toBe(0)
2b4fddb8
JB
687 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
688 workerChoiceStrategy
b0d6ed8f 689 ).workersVirtualTaskEndTimestamp[0] = performance.now()
2b4fddb8
JB
690 expect(
691 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
692 workerChoiceStrategy
b0d6ed8f 693 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 694 ).toBe(1)
594bfb84 695 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
08f3f44c
JB
696 expect(
697 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
698 workerChoiceStrategy
b0d6ed8f 699 ).workersVirtualTaskEndTimestamp
08f3f44c 700 ).toBeInstanceOf(Array)
08f3f44c
JB
701 expect(
702 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
703 workerChoiceStrategy
b0d6ed8f 704 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 705 ).toBe(0)
f0829c53
JB
706 await pool.destroy()
707 pool = new DynamicThreadPool(
708 min,
709 max,
710 './tests/worker-files/thread/testWorker.js'
711 )
712 expect(
95c83464 713 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 714 workerChoiceStrategy
b0d6ed8f 715 ).workersVirtualTaskEndTimestamp
08f3f44c 716 ).toBeInstanceOf(Array)
2b4fddb8
JB
717 expect(
718 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
719 workerChoiceStrategy
b0d6ed8f 720 ).workersVirtualTaskEndTimestamp.length
2b4fddb8 721 ).toBe(0)
08f3f44c
JB
722 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
723 workerChoiceStrategy
b0d6ed8f 724 ).workersVirtualTaskEndTimestamp[0] = performance.now()
08f3f44c
JB
725 expect(
726 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
727 workerChoiceStrategy
b0d6ed8f 728 ).workersVirtualTaskEndTimestamp.length
08f3f44c 729 ).toBe(1)
594bfb84 730 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
08f3f44c
JB
731 expect(
732 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
733 workerChoiceStrategy
b0d6ed8f 734 ).workersVirtualTaskEndTimestamp
08f3f44c
JB
735 ).toBeInstanceOf(Array)
736 expect(
737 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
738 workerChoiceStrategy
b0d6ed8f 739 ).workersVirtualTaskEndTimestamp.length
08f3f44c 740 ).toBe(0)
caeb9817
JB
741 // We need to clean up the resources after our test
742 await pool.destroy()
743 })
744
10fcfaf4 745 it('Verify WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
594bfb84 746 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
10fcfaf4
JB
747 let pool = new FixedThreadPool(
748 max,
d710242d 749 './tests/worker-files/thread/testWorker.js',
594bfb84 750 { workerChoiceStrategy }
10fcfaf4 751 )
b6b32453 752 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
753 runTime: true,
754 avgRunTime: true,
755 medRunTime: false,
756 waitTime: false,
757 avgWaitTime: false,
d44d5953
JB
758 medWaitTime: false,
759 elu: false
86bf340d 760 })
fd7ebd49 761 await pool.destroy()
10fcfaf4
JB
762 pool = new DynamicThreadPool(
763 min,
764 max,
d710242d 765 './tests/worker-files/thread/testWorker.js',
594bfb84 766 { workerChoiceStrategy }
10fcfaf4 767 )
b6b32453 768 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
86bf340d
JB
769 runTime: true,
770 avgRunTime: true,
771 medRunTime: false,
772 waitTime: false,
773 avgWaitTime: false,
d44d5953
JB
774 medWaitTime: false,
775 elu: false
86bf340d 776 })
10fcfaf4
JB
777 // We need to clean up the resources after our test
778 await pool.destroy()
779 })
780
b3432a63 781 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
b3432a63
JB
782 const pool = new FixedThreadPool(
783 max,
784 './tests/worker-files/thread/testWorker.js',
785 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
786 )
787 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
ee9f5295 788 const promises = new Set()
a20f0ba5
JB
789 const maxMultiplier = 2
790 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 791 promises.add(pool.execute())
b3432a63 792 }
e211bc18 793 await Promise.all(promises)
138d29a8 794 for (const workerNode of pool.workerNodes) {
86bf340d 795 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 796 ran: expect.any(Number),
86bf340d
JB
797 running: 0,
798 runTime: expect.any(Number),
799 runTimeHistory: expect.any(CircularArray),
800 avgRunTime: expect.any(Number),
801 medRunTime: 0,
802 waitTime: 0,
803 waitTimeHistory: expect.any(CircularArray),
804 avgWaitTime: 0,
805 medWaitTime: 0,
d44d5953
JB
806 error: 0,
807 elu: undefined
86bf340d 808 })
1ab50fe5
JB
809 expect(workerNode.tasksUsage.ran).toBeGreaterThanOrEqual(0)
810 expect(workerNode.tasksUsage.ran).toBeLessThanOrEqual(max * maxMultiplier)
ee9f5295 811 expect(workerNode.tasksUsage.runTime).toBeGreaterThanOrEqual(0)
138d29a8 812 expect(workerNode.tasksUsage.avgRunTime).toBeGreaterThanOrEqual(0)
138d29a8 813 }
97a2abc3 814 expect(
95c83464 815 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 816 pool.workerChoiceStrategyContext.workerChoiceStrategy
08f3f44c
JB
817 ).defaultWorkerWeight
818 ).toBeGreaterThan(0)
819 expect(
820 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
821 pool.workerChoiceStrategyContext.workerChoiceStrategy
822 ).workerVirtualTaskRunTime
823 ).toBeGreaterThanOrEqual(0)
b3432a63
JB
824 // We need to clean up the resources after our test
825 await pool.destroy()
826 })
827
828 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
b3432a63
JB
829 const pool = new DynamicThreadPool(
830 min,
831 max,
832 './tests/worker-files/thread/testWorker.js',
833 { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
834 )
835 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
ee9f5295 836 const promises = new Set()
138d29a8 837 const maxMultiplier = 2
5502c07c 838 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 839 promises.add(pool.execute())
b3432a63 840 }
e211bc18 841 await Promise.all(promises)
138d29a8 842 for (const workerNode of pool.workerNodes) {
86bf340d 843 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 844 ran: expect.any(Number),
86bf340d
JB
845 running: 0,
846 runTime: expect.any(Number),
847 runTimeHistory: expect.any(CircularArray),
848 avgRunTime: expect.any(Number),
849 medRunTime: 0,
850 waitTime: 0,
851 waitTimeHistory: expect.any(CircularArray),
852 avgWaitTime: 0,
853 medWaitTime: 0,
d44d5953
JB
854 error: 0,
855 elu: undefined
86bf340d 856 })
1ab50fe5
JB
857 expect(workerNode.tasksUsage.ran).toBeGreaterThan(0)
858 expect(workerNode.tasksUsage.ran).toBeLessThanOrEqual(max * maxMultiplier)
e211bc18
JB
859 expect(workerNode.tasksUsage.runTime).toBeGreaterThan(0)
860 expect(workerNode.tasksUsage.avgRunTime).toBeGreaterThan(0)
138d29a8 861 }
2b4fddb8
JB
862 expect(
863 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
864 pool.workerChoiceStrategyContext.workerChoiceStrategy
865 ).defaultWorkerWeight
866 ).toBeGreaterThan(0)
867 expect(
868 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
869 pool.workerChoiceStrategyContext.workerChoiceStrategy
870 ).workerVirtualTaskRunTime
871 ).toBeGreaterThanOrEqual(0)
b3432a63
JB
872 // We need to clean up the resources after our test
873 await pool.destroy()
874 })
875
9e775f96 876 it('Verify WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool with median runtime statistic', async () => {
010d7020
JB
877 const pool = new DynamicThreadPool(
878 min,
879 max,
880 './tests/worker-files/thread/testWorker.js',
881 {
882 workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN,
883 workerChoiceStrategyOptions: {
884 medRunTime: true
885 }
886 }
887 )
888 // TODO: Create a better test to cover `WeightedRoundRobinWorkerChoiceStrategy#choose`
ee9f5295 889 const promises = new Set()
010d7020
JB
890 const maxMultiplier = 2
891 for (let i = 0; i < max * maxMultiplier; i++) {
ee9f5295 892 promises.add(pool.execute())
010d7020 893 }
e211bc18 894 await Promise.all(promises)
010d7020 895 for (const workerNode of pool.workerNodes) {
86bf340d 896 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 897 ran: expect.any(Number),
86bf340d
JB
898 running: 0,
899 runTime: expect.any(Number),
900 runTimeHistory: expect.any(CircularArray),
901 avgRunTime: 0,
902 medRunTime: expect.any(Number),
903 waitTime: 0,
904 waitTimeHistory: expect.any(CircularArray),
905 avgWaitTime: 0,
906 medWaitTime: 0,
d44d5953
JB
907 error: 0,
908 elu: undefined
86bf340d 909 })
1ab50fe5
JB
910 expect(workerNode.tasksUsage.ran).toBeGreaterThan(0)
911 expect(workerNode.tasksUsage.ran).toBeLessThanOrEqual(max * maxMultiplier)
e211bc18
JB
912 expect(workerNode.tasksUsage.runTime).toBeGreaterThan(0)
913 expect(workerNode.tasksUsage.medRunTime).toBeGreaterThan(0)
010d7020 914 }
08f3f44c
JB
915 expect(
916 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
917 pool.workerChoiceStrategyContext.workerChoiceStrategy
918 ).defaultWorkerWeight
919 ).toBeGreaterThan(0)
920 expect(
921 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
922 pool.workerChoiceStrategyContext.workerChoiceStrategy
923 ).workerVirtualTaskRunTime
924 ).toBeGreaterThanOrEqual(0)
010d7020
JB
925 // We need to clean up the resources after our test
926 await pool.destroy()
927 })
928
a6f7f1b4 929 it('Verify WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
594bfb84 930 const workerChoiceStrategy = WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
f0829c53 931 let pool = new FixedThreadPool(
caeb9817
JB
932 max,
933 './tests/worker-files/thread/testWorker.js'
934 )
38f6e859 935 expect(
95c83464 936 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 937 workerChoiceStrategy
f06e48d8 938 ).currentWorkerNodeId
b529c323 939 ).toBeDefined()
38f6e859 940 expect(
95c83464 941 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 942 workerChoiceStrategy
b529c323
JB
943 ).defaultWorkerWeight
944 ).toBeDefined()
caeb9817 945 expect(
95c83464 946 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 947 workerChoiceStrategy
08f3f44c 948 ).workerVirtualTaskRunTime
b529c323 949 ).toBeDefined()
594bfb84 950 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 951 expect(
95c83464 952 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 953 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 954 ).currentWorkerNodeId
a6f7f1b4
JB
955 ).toBe(0)
956 expect(
95c83464 957 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 958 pool.workerChoiceStrategyContext.workerChoiceStrategy
95c83464 959 ).defaultWorkerWeight
a6f7f1b4 960 ).toBeGreaterThan(0)
08f3f44c
JB
961 expect(
962 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
963 workerChoiceStrategy
964 ).workerVirtualTaskRunTime
965 ).toBe(0)
f0829c53
JB
966 await pool.destroy()
967 pool = new DynamicThreadPool(
968 min,
969 max,
970 './tests/worker-files/thread/testWorker.js'
971 )
38f6e859 972 expect(
95c83464 973 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 974 workerChoiceStrategy
f06e48d8 975 ).currentWorkerNodeId
b529c323 976 ).toBeDefined()
38f6e859 977 expect(
95c83464 978 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 979 workerChoiceStrategy
b529c323
JB
980 ).defaultWorkerWeight
981 ).toBeDefined()
f0829c53 982 expect(
95c83464 983 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
594bfb84 984 workerChoiceStrategy
08f3f44c 985 ).workerVirtualTaskRunTime
b529c323 986 ).toBeDefined()
594bfb84 987 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
a6f7f1b4 988 expect(
95c83464 989 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 990 pool.workerChoiceStrategyContext.workerChoiceStrategy
f06e48d8 991 ).currentWorkerNodeId
a6f7f1b4
JB
992 ).toBe(0)
993 expect(
95c83464 994 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
d710242d 995 pool.workerChoiceStrategyContext.workerChoiceStrategy
95c83464 996 ).defaultWorkerWeight
a6f7f1b4 997 ).toBeGreaterThan(0)
08f3f44c
JB
998 expect(
999 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1000 workerChoiceStrategy
1001 ).workerVirtualTaskRunTime
1002 ).toBe(0)
caeb9817
JB
1003 // We need to clean up the resources after our test
1004 await pool.destroy()
1005 })
1006
e52fb978
JB
1007 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy default tasks usage statistics requirements', async () => {
1008 const workerChoiceStrategy =
1009 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1010 let pool = new FixedThreadPool(
1011 max,
1012 './tests/worker-files/thread/testWorker.js',
1013 { workerChoiceStrategy }
1014 )
b6b32453 1015 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
e52fb978
JB
1016 runTime: false,
1017 avgRunTime: false,
1018 medRunTime: false,
1019 waitTime: false,
1020 avgWaitTime: false,
d44d5953
JB
1021 medWaitTime: false,
1022 elu: false
e52fb978
JB
1023 })
1024 await pool.destroy()
1025 pool = new DynamicThreadPool(
1026 min,
1027 max,
1028 './tests/worker-files/thread/testWorker.js',
1029 { workerChoiceStrategy }
1030 )
b6b32453 1031 expect(pool.workerChoiceStrategyContext.getTaskStatistics()).toStrictEqual({
e52fb978
JB
1032 runTime: false,
1033 avgRunTime: false,
1034 medRunTime: false,
1035 waitTime: false,
1036 avgWaitTime: false,
d44d5953
JB
1037 medWaitTime: false,
1038 elu: false
e52fb978
JB
1039 })
1040 // We need to clean up the resources after our test
1041 await pool.destroy()
1042 })
1043
e62e7646
JB
1044 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a fixed pool', async () => {
1045 const pool = new FixedThreadPool(
1046 max,
1047 './tests/worker-files/thread/testWorker.js',
1048 {
1049 workerChoiceStrategy:
1050 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1051 }
1052 )
1053 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1054 const promises = new Set()
1055 const maxMultiplier = 2
1056 for (let i = 0; i < max * maxMultiplier; i++) {
1057 promises.add(pool.execute())
1058 }
1059 await Promise.all(promises)
1060 for (const workerNode of pool.workerNodes) {
1061 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 1062 ran: maxMultiplier,
e62e7646
JB
1063 running: 0,
1064 runTime: 0,
1065 runTimeHistory: expect.any(CircularArray),
1066 avgRunTime: 0,
1067 medRunTime: 0,
1068 waitTime: 0,
1069 waitTimeHistory: expect.any(CircularArray),
1070 avgWaitTime: 0,
1071 medWaitTime: 0,
d44d5953
JB
1072 error: 0,
1073 elu: undefined
e62e7646
JB
1074 })
1075 }
1076 expect(
1077 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1078 pool.workerChoiceStrategyContext.workerChoiceStrategy
1079 ).defaultWorkerWeight
1080 ).toBeGreaterThan(0)
1081 expect(
1082 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1083 pool.workerChoiceStrategyContext.workerChoiceStrategy
1084 ).currentRoundId
1085 ).toBe(0)
1086 expect(
1087 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1088 pool.workerChoiceStrategyContext.workerChoiceStrategy
1089 ).currentWorkerNodeId
1090 ).toBe(0)
1091 expect(
1092 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1093 pool.workerChoiceStrategyContext.workerChoiceStrategy
1094 ).roundWeights
1095 ).toStrictEqual([
1096 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1097 pool.workerChoiceStrategyContext.workerChoiceStrategy
1098 ).defaultWorkerWeight
1099 ])
1100 // We need to clean up the resources after our test
1101 await pool.destroy()
1102 })
1103
1104 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
1105 const pool = new DynamicThreadPool(
1106 min,
1107 max,
1108 './tests/worker-files/thread/testWorker.js',
1109 {
1110 workerChoiceStrategy:
1111 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1112 }
1113 )
1114 // TODO: Create a better test to cover `InterleavedWeightedRoundRobinWorkerChoiceStrategy#choose`
1115 const promises = new Set()
1116 const maxMultiplier = 2
1117 for (let i = 0; i < max * maxMultiplier; i++) {
1118 promises.add(pool.execute())
1119 }
1120 await Promise.all(promises)
1121 for (const workerNode of pool.workerNodes) {
1122 expect(workerNode.tasksUsage).toStrictEqual({
1ab50fe5 1123 ran: maxMultiplier,
e62e7646
JB
1124 running: 0,
1125 runTime: 0,
1126 runTimeHistory: expect.any(CircularArray),
1127 avgRunTime: 0,
1128 medRunTime: 0,
1129 waitTime: 0,
1130 waitTimeHistory: expect.any(CircularArray),
1131 avgWaitTime: 0,
1132 medWaitTime: 0,
d44d5953
JB
1133 error: 0,
1134 elu: undefined
e62e7646
JB
1135 })
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 ).currentRoundId
1146 ).toBe(0)
1147 expect(
1148 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1149 pool.workerChoiceStrategyContext.workerChoiceStrategy
1150 ).currentWorkerNodeId
1151 ).toBe(0)
1152 expect(
1153 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1154 pool.workerChoiceStrategyContext.workerChoiceStrategy
1155 ).roundWeights
1156 ).toStrictEqual([
1157 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1158 pool.workerChoiceStrategyContext.workerChoiceStrategy
1159 ).defaultWorkerWeight
1160 ])
1161 // We need to clean up the resources after our test
1162 await pool.destroy()
1163 })
1164
8c3ec188
JB
1165 it('Verify INTERLEAVED_WEIGHTED_ROUND_ROBIN strategy internals are resets after setting it', async () => {
1166 const workerChoiceStrategy =
1167 WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
1168 let pool = new FixedThreadPool(
1169 max,
1170 './tests/worker-files/thread/testWorker.js'
1171 )
1172 expect(
1173 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1174 workerChoiceStrategy
1175 ).currentRoundId
1176 ).toBeDefined()
1177 expect(
1178 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1179 workerChoiceStrategy
1180 ).currentWorkerNodeId
1181 ).toBeDefined()
1182 expect(
1183 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1184 workerChoiceStrategy
1185 ).defaultWorkerWeight
1186 ).toBeDefined()
1187 expect(
1188 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1189 workerChoiceStrategy
1190 ).roundWeights
1191 ).toBeDefined()
1192 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1193 expect(
1194 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1195 workerChoiceStrategy
1196 ).currentRoundId
1197 ).toBe(0)
1198 expect(
1199 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1200 pool.workerChoiceStrategyContext.workerChoiceStrategy
1201 ).currentWorkerNodeId
1202 ).toBe(0)
1203 expect(
1204 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1205 pool.workerChoiceStrategyContext.workerChoiceStrategy
1206 ).defaultWorkerWeight
1207 ).toBeGreaterThan(0)
1208 expect(
1209 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1210 workerChoiceStrategy
1211 ).roundWeights
1212 ).toStrictEqual([
1213 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1214 pool.workerChoiceStrategyContext.workerChoiceStrategy
1215 ).defaultWorkerWeight
1216 ])
1217 await pool.destroy()
1218 pool = new DynamicThreadPool(
1219 min,
1220 max,
1221 './tests/worker-files/thread/testWorker.js'
1222 )
1223 expect(
1224 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1225 workerChoiceStrategy
1226 ).currentRoundId
1227 ).toBeDefined()
1228 expect(
1229 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1230 workerChoiceStrategy
1231 ).currentWorkerNodeId
1232 ).toBeDefined()
1233 expect(
1234 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1235 workerChoiceStrategy
1236 ).defaultWorkerWeight
1237 ).toBeDefined()
1238 expect(
1239 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1240 workerChoiceStrategy
1241 ).roundWeights
1242 ).toBeDefined()
1243 pool.setWorkerChoiceStrategy(workerChoiceStrategy)
1244 expect(
1245 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1246 pool.workerChoiceStrategyContext.workerChoiceStrategy
1247 ).currentWorkerNodeId
1248 ).toBe(0)
1249 expect(
1250 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1251 pool.workerChoiceStrategyContext.workerChoiceStrategy
1252 ).defaultWorkerWeight
1253 ).toBeGreaterThan(0)
1254 expect(
1255 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1256 workerChoiceStrategy
1257 ).roundWeights
1258 ).toStrictEqual([
1259 pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
1260 pool.workerChoiceStrategyContext.workerChoiceStrategy
1261 ).defaultWorkerWeight
1262 ])
1263 // We need to clean up the resources after our test
1264 await pool.destroy()
1265 })
1266
89b09b26 1267 it('Verify unknown strategy throw error', () => {
a35560ba
S
1268 expect(
1269 () =>
1270 new DynamicThreadPool(
1271 min,
1272 max,
1273 './tests/worker-files/thread/testWorker.js',
1927ee67 1274 { workerChoiceStrategy: 'UNKNOWN_STRATEGY' }
a35560ba 1275 )
d4aeae5a 1276 ).toThrowError("Invalid worker choice strategy 'UNKNOWN_STRATEGY'")
a35560ba
S
1277 })
1278})