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 maxMultiplier
= 10
93 const promises
= new Set()
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
.tasksQueue
.size
).toBe(0)
118 it('Verify that is possible to have a worker that return undefined', async () => {
119 const result
= await emptyPool
.execute()
120 expect(result
).toBeUndefined()
123 it('Verify that data are sent to the worker correctly', async () => {
124 const data
= { f
: 10 }
125 const result
= await echoPool
.execute(data
)
126 expect(result
).toStrictEqual(data
)
129 it('Verify that error handling is working properly:sync', async () => {
130 const data
= { f
: 10 }
133 await errorPool
.execute(data
)
137 expect(inError
).toBeDefined()
138 expect(typeof inError
=== 'string').toBe(true)
139 expect(inError
).toBe('Error Message from ClusterWorker')
141 errorPool
.workerNodes
.some(
142 workerNode
=> workerNode
.tasksUsage
.error
=== 1
147 it('Verify that error handling is working properly:async', async () => {
148 const data
= { f
: 10 }
151 await asyncErrorPool
.execute(data
)
155 expect(inError
).toBeDefined()
156 expect(typeof inError
=== 'string').toBe(true)
157 expect(inError
).toBe('Error Message from ClusterWorker:async')
159 asyncErrorPool
.workerNodes
.some(
160 workerNode
=> workerNode
.tasksUsage
.error
=== 1
165 it('Verify that async function is working properly', async () => {
166 const data
= { f
: 10 }
167 const startTime
= performance
.now()
168 const result
= await asyncPool
.execute(data
)
169 const usedTime
= performance
.now() - startTime
170 expect(result
).toStrictEqual(data
)
171 expect(usedTime
).toBeGreaterThanOrEqual(2000)
174 it('Shutdown test', async () => {
175 const exitPromise
= TestUtils
.waitExits(pool
, numberOfWorkers
)
177 const numberOfExitEvents
= await exitPromise
178 expect(numberOfExitEvents
).toBe(numberOfWorkers
)
181 it('Verify that cluster pool options are checked', async () => {
182 const workerFilePath
= './tests/worker-files/cluster/testWorker.js'
183 let pool1
= new FixedClusterPool(numberOfWorkers
, workerFilePath
)
184 expect(pool1
.opts
.env
).toBeUndefined()
185 expect(pool1
.opts
.settings
).toBeUndefined()
186 await pool1
.destroy()
187 pool1
= new FixedClusterPool(numberOfWorkers
, workerFilePath
, {
188 env
: { TEST
: 'test' },
189 settings
: { args
: ['--use', 'http'], silent
: true }
191 expect(pool1
.opts
.env
).toStrictEqual({ TEST
: 'test' })
192 expect(pool1
.opts
.settings
).toStrictEqual({
193 args
: ['--use', 'http'],
196 expect({ ...pool1
.opts
.settings
, exec
: workerFilePath
}).toStrictEqual({
197 args
: ['--use', 'http'],
201 await pool1
.destroy()
204 it('Should work even without opts in input', async () => {
205 const pool1
= new FixedClusterPool(
207 './tests/worker-files/cluster/testWorker.js'
209 const res
= await pool1
.execute()
210 expect(res
).toBe(false)
211 // We need to clean up the resources after our test
212 await pool1
.destroy()
215 it('Verify that a pool with zero worker fails', async () => {
218 new FixedClusterPool(0, './tests/worker-files/cluster/testWorker.js')
219 ).toThrowError('Cannot instantiate a fixed pool with no worker')