feat: untangle worker choice strategies tasks distribution and dynamic worker creatio...
[poolifier.git] / tests / pools / thread / dynamic.test.js
CommitLineData
a61a0724 1const { expect } = require('expect')
cdace0e5 2const { DynamicThreadPool, PoolEvents } = require('../../../lib')
dbca3be9 3const { TaskFunctions } = require('../../test-types')
bac873bd 4const { sleep, waitWorkerEvents } = require('../../test-utils')
506c2a14 5
a35560ba 6describe('Dynamic thread pool test suite', () => {
e1ffb94f
JB
7 const min = 1
8 const max = 3
9 const pool = new DynamicThreadPool(
10 min,
11 max,
12 './tests/worker-files/thread/testWorker.js',
13 {
8ebe6c30 14 errorHandler: (e) => console.error(e)
e1ffb94f
JB
15 }
16 )
17
506c2a14 18 it('Verify that the function is executed in a worker thread', async () => {
6db75ad9 19 let result = await pool.execute({
dbca3be9 20 function: TaskFunctions.fibonacci
6db75ad9 21 })
024daf59 22 expect(result).toBe(75025)
6db75ad9 23 result = await pool.execute({
dbca3be9 24 function: TaskFunctions.factorial
6db75ad9 25 })
70a4f5ea 26 expect(result).toBe(9.33262154439441e157)
506c2a14 27 })
28
29 it('Verify that new workers are created when required, max size is not exceeded and that after a while new workers will die', async () => {
7c0ba920 30 let poolBusy = 0
aee46736 31 pool.emitter.on(PoolEvents.busy, () => ++poolBusy)
cf9aa6c3 32 for (let i = 0; i < max * 2; i++) {
8cbb82eb 33 pool.execute()
506c2a14 34 }
f06e48d8
JB
35 expect(pool.workerNodes.length).toBeLessThanOrEqual(max)
36 expect(pool.workerNodes.length).toBeGreaterThan(min)
94407def 37 expect(poolBusy).toBe(1)
bac873bd 38 const numberOfExitEvents = await waitWorkerEvents(pool, 'exit', max - min)
bdacc2d2 39 expect(numberOfExitEvents).toBe(max - min)
506c2a14 40 })
41
bcf04003 42 it('Verify scale thread up and down is working', async () => {
f06e48d8 43 expect(pool.workerNodes.length).toBe(min)
e211bc18 44 for (let i = 0; i < max * 2; i++) {
6db75ad9 45 pool.execute()
bcf04003 46 }
f06e48d8 47 expect(pool.workerNodes.length).toBe(max)
bac873bd 48 await waitWorkerEvents(pool, 'exit', max - min)
f06e48d8 49 expect(pool.workerNodes.length).toBe(min)
e211bc18 50 for (let i = 0; i < max * 2; i++) {
6db75ad9 51 pool.execute()
bcf04003 52 }
f06e48d8 53 expect(pool.workerNodes.length).toBe(max)
bac873bd 54 await waitWorkerEvents(pool, 'exit', max - min)
f06e48d8 55 expect(pool.workerNodes.length).toBe(min)
bcf04003 56 })
c01733f1 57
506c2a14 58 it('Shutdown test', async () => {
bac873bd 59 const exitPromise = waitWorkerEvents(pool, 'exit', min)
ef3891a3
JB
60 let poolDestroy = 0
61 pool.emitter.on(PoolEvents.destroy, () => ++poolDestroy)
1f9a5a44 62 await pool.destroy()
cf597bc5
JB
63 const numberOfExitEvents = await exitPromise
64 expect(numberOfExitEvents).toBe(min)
ef3891a3 65 expect(poolDestroy).toBe(1)
506c2a14 66 })
67
8d3782fa
JB
68 it('Validation of inputs test', () => {
69 expect(() => new DynamicThreadPool(min)).toThrowError(
d4aeae5a 70 'Please specify a file with a worker implementation'
85a3f8a7 71 )
506c2a14 72 })
73
74 it('Should work even without opts in input', async () => {
325f50bc 75 const pool1 = new DynamicThreadPool(
e1ffb94f
JB
76 min,
77 max,
76b1e974 78 './tests/worker-files/thread/testWorker.js'
325f50bc 79 )
6db75ad9 80 const res = await pool1.execute()
30b963d4 81 expect(res).toStrictEqual({ ok: 1 })
0e2503fc
JB
82 // We need to clean up the resources after our test
83 await pool1.destroy()
506c2a14 84 })
c01733f1 85
1c6fe997 86 it('Verify scale thread up and down is working when long executing task is used:hard', async () => {
c01733f1 87 const longRunningPool = new DynamicThreadPool(
88 min,
89 max,
85a3f8a7 90 './tests/worker-files/thread/longRunningWorkerHardBehavior.js',
4c35177b 91 {
8ebe6c30 92 errorHandler: (e) => console.error(e),
73bfd59d
JB
93 onlineHandler: () => console.info('long executing worker is online'),
94 exitHandler: () => console.info('long executing worker exited')
4c35177b 95 }
96 )
f06e48d8 97 expect(longRunningPool.workerNodes.length).toBe(min)
e211bc18 98 for (let i = 0; i < max * 2; i++) {
6db75ad9 99 longRunningPool.execute()
4c35177b 100 }
f06e48d8 101 expect(longRunningPool.workerNodes.length).toBe(max)
bac873bd 102 await waitWorkerEvents(longRunningPool, 'exit', max - min)
f06e48d8 103 expect(longRunningPool.workerNodes.length).toBe(min)
d710242d
JB
104 expect(
105 longRunningPool.workerChoiceStrategyContext.workerChoiceStrategies.get(
106 longRunningPool.workerChoiceStrategyContext.workerChoiceStrategy
9b106837 107 ).nextWorkerNodeKey
d710242d 108 ).toBeLessThan(longRunningPool.workerNodes.length)
0e2503fc
JB
109 // We need to clean up the resources after our test
110 await longRunningPool.destroy()
4c35177b 111 })
112
1c6fe997 113 it('Verify scale thread up and down is working when long executing task is used:soft', async () => {
4c35177b 114 const longRunningPool = new DynamicThreadPool(
115 min,
116 max,
85a3f8a7 117 './tests/worker-files/thread/longRunningWorkerSoftBehavior.js',
c01733f1 118 {
8ebe6c30 119 errorHandler: (e) => console.error(e),
73bfd59d
JB
120 onlineHandler: () => console.info('long executing worker is online'),
121 exitHandler: () => console.info('long executing worker exited')
c01733f1 122 }
123 )
f06e48d8 124 expect(longRunningPool.workerNodes.length).toBe(min)
e211bc18 125 for (let i = 0; i < max * 2; i++) {
6db75ad9 126 longRunningPool.execute()
c01733f1 127 }
f06e48d8 128 expect(longRunningPool.workerNodes.length).toBe(max)
920278a2 129 await sleep(1000)
1c6fe997 130 // Here we expect the workerNodes to be at the max size since the task is still executing
f06e48d8 131 expect(longRunningPool.workerNodes.length).toBe(max)
0e2503fc
JB
132 // We need to clean up the resources after our test
133 await longRunningPool.destroy()
c01733f1 134 })
8d3782fa
JB
135
136 it('Verify that a pool with zero worker can be instantiated', async () => {
137 const pool = new DynamicThreadPool(
138 0,
139 max,
140 './tests/worker-files/thread/testWorker.js'
141 )
142 expect(pool).toBeInstanceOf(DynamicThreadPool)
143 // We need to clean up the resources after our test
144 await pool.destroy()
145 })
506c2a14 146})