1 const { expect
} = require('expect')
2 const { FixedClusterPool
, PoolEvents
} = require('../../../lib')
3 const { WorkerFunctions
} = require('../../test-types')
4 const TestUtils
= require('../../test-utils')
6 describe('Fixed cluster pool test suite', () => {
7 const numberOfWorkers
= 6
8 const pool
= new FixedClusterPool(
10 './tests/worker-files/cluster/testWorker.js',
12 errorHandler
: e
=> console
.error(e
)
15 const queuePool
= new FixedClusterPool(
17 './tests/worker-files/cluster/testWorker.js',
19 enableTasksQueue
: true,
23 errorHandler
: e
=> console
.error(e
)
26 const emptyPool
= new FixedClusterPool(
28 './tests/worker-files/cluster/emptyWorker.js',
29 { exitHandler
: () => console
.log('empty pool worker exited') }
31 const echoPool
= new FixedClusterPool(
33 './tests/worker-files/cluster/echoWorker.js'
35 const errorPool
= new FixedClusterPool(
37 './tests/worker-files/cluster/errorWorker.js',
39 errorHandler
: e
=> console
.error(e
)
42 const asyncErrorPool
= new FixedClusterPool(
44 './tests/worker-files/cluster/asyncErrorWorker.js',
46 errorHandler
: e
=> console
.error(e
)
49 const asyncPool
= new FixedClusterPool(
51 './tests/worker-files/cluster/asyncWorker.js'
54 after('Destroy all pools', async () => {
55 // We need to clean up the resources after our test
56 await echoPool
.destroy()
57 await asyncPool
.destroy()
58 await errorPool
.destroy()
59 await asyncErrorPool
.destroy()
60 await emptyPool
.destroy()
61 await queuePool
.destroy()
64 it('Verify that the function is executed in a worker cluster', async () => {
65 let result
= await pool
.execute({
66 function: WorkerFunctions
.fibonacci
68 expect(result
).toBe(121393)
69 result
= await pool
.execute({
70 function: WorkerFunctions
.factorial
72 expect(result
).toBe(9.33262154439441e157
)
75 it('Verify that is possible to invoke the execute() method without input', async () => {
76 const result
= await pool
.execute()
77 expect(result
).toBe(false)
80 it("Verify that 'busy' event is emitted", async () => {
82 pool
.emitter
.on(PoolEvents
.busy
, () => ++poolBusy
)
83 for (let i
= 0; i
< numberOfWorkers
* 2; i
++) {
86 // The `busy` event is triggered when the number of submitted tasks at once reach the number of fixed pool workers.
87 // So in total numberOfWorkers + 1 times for a loop submitting up to numberOfWorkers * 2 tasks to the fixed pool.
88 expect(poolBusy
).toBe(numberOfWorkers
+ 1)
91 it('Verify that tasks queuing is working', async () => {
92 const promises
= new Set()
93 const maxMultiplier
= 2
94 for (let i
= 0; i
< numberOfWorkers
* maxMultiplier
; i
++) {
95 promises
.add(queuePool
.execute())
97 expect(promises
.size
).toBe(numberOfWorkers
* maxMultiplier
)
98 for (const workerNode
of queuePool
.workerNodes
) {
99 expect(workerNode
.tasksUsage
.running
).toBeLessThanOrEqual(
100 queuePool
.opts
.tasksQueueOptions
.concurrency
102 expect(workerNode
.tasksUsage
.run
).toBe(0)
103 expect(workerNode
.tasksQueue
.size
).toBeGreaterThan(0)
105 expect(queuePool
.numberOfRunningTasks
).toBe(numberOfWorkers
)
106 expect(queuePool
.numberOfQueuedTasks
).toBe(
107 numberOfWorkers
* maxMultiplier
- numberOfWorkers
109 await Promise
.all(promises
)
110 for (const workerNode
of queuePool
.workerNodes
) {
111 expect(workerNode
.tasksUsage
.running
).toBe(0)
112 expect(workerNode
.tasksUsage
.run
).toBeGreaterThan(0)
113 expect(workerNode
.tasksUsage
.run
).toBeLessThanOrEqual(maxMultiplier
)
114 expect(workerNode
.tasksQueue
.size
).toBe(0)
119 it('Verify that is possible to have a worker that return undefined', async () => {
120 const result
= await emptyPool
.execute()
121 expect(result
).toBeUndefined()
124 it('Verify that data are sent to the worker correctly', async () => {
125 const data
= { f
: 10 }
126 const result
= await echoPool
.execute(data
)
127 expect(result
).toStrictEqual(data
)
130 it('Verify that error handling is working properly:sync', async () => {
131 const data
= { f
: 10 }
134 await errorPool
.execute(data
)
138 expect(inError
).toBeDefined()
139 expect(typeof inError
=== 'string').toBe(true)
140 expect(inError
).toBe('Error Message from ClusterWorker')
142 errorPool
.workerNodes
.some(
143 workerNode
=> workerNode
.tasksUsage
.error
=== 1
148 it('Verify that error handling is working properly:async', async () => {
149 const data
= { f
: 10 }
152 await asyncErrorPool
.execute(data
)
156 expect(inError
).toBeDefined()
157 expect(typeof inError
=== 'string').toBe(true)
158 expect(inError
).toBe('Error Message from ClusterWorker:async')
160 asyncErrorPool
.workerNodes
.some(
161 workerNode
=> workerNode
.tasksUsage
.error
=== 1
166 it('Verify that async function is working properly', async () => {
167 const data
= { f
: 10 }
168 const startTime
= performance
.now()
169 const result
= await asyncPool
.execute(data
)
170 const usedTime
= performance
.now() - startTime
171 expect(result
).toStrictEqual(data
)
172 expect(usedTime
).toBeGreaterThanOrEqual(2000)
175 it('Shutdown test', async () => {
176 const exitPromise
= TestUtils
.waitExits(pool
, numberOfWorkers
)
178 const numberOfExitEvents
= await exitPromise
179 expect(numberOfExitEvents
).toBe(numberOfWorkers
)
182 it('Verify that cluster pool options are checked', async () => {
183 const workerFilePath
= './tests/worker-files/cluster/testWorker.js'
184 let pool1
= new FixedClusterPool(numberOfWorkers
, workerFilePath
)
185 expect(pool1
.opts
.env
).toBeUndefined()
186 expect(pool1
.opts
.settings
).toBeUndefined()
187 await pool1
.destroy()
188 pool1
= new FixedClusterPool(numberOfWorkers
, workerFilePath
, {
189 env
: { TEST
: 'test' },
190 settings
: { args
: ['--use', 'http'], silent
: true }
192 expect(pool1
.opts
.env
).toStrictEqual({ TEST
: 'test' })
193 expect(pool1
.opts
.settings
).toStrictEqual({
194 args
: ['--use', 'http'],
197 expect({ ...pool1
.opts
.settings
, exec
: workerFilePath
}).toStrictEqual({
198 args
: ['--use', 'http'],
202 await pool1
.destroy()
205 it('Should work even without opts in input', async () => {
206 const pool1
= new FixedClusterPool(
208 './tests/worker-files/cluster/testWorker.js'
210 const res
= await pool1
.execute()
211 expect(res
).toBe(false)
212 // We need to clean up the resources after our test
213 await pool1
.destroy()
216 it('Verify that a pool with zero worker fails', async () => {
219 new FixedClusterPool(0, './tests/worker-files/cluster/testWorker.js')
220 ).toThrowError('Cannot instantiate a fixed pool with no worker')