1 const { expect
} = require('expect')
9 WorkerChoiceStrategies
,
11 } = require('../../../lib')
12 const { CircularArray
} = require('../../../lib/circular-array')
13 const { Queue
} = require('../../../lib/queue')
14 const { version
} = require('../../../package.json')
15 const { waitPoolEvents
} = require('../../test-utils')
17 describe('Abstract pool test suite', () => {
18 const numberOfWorkers
= 2
19 class StubPoolWithIsMain
extends FixedThreadPool
{
25 it('Simulate pool creation from a non main thread/process', () => {
28 new StubPoolWithIsMain(
30 './tests/worker-files/thread/testWorker.js',
32 errorHandler
: (e
) => console
.error(e
)
36 'Cannot start a pool from a worker with the same type as the pool'
40 it('Verify that filePath is checked', () => {
41 const expectedError
= new Error(
42 'Please specify a file with a worker implementation'
44 expect(() => new FixedThreadPool(numberOfWorkers
)).toThrowError(
47 expect(() => new FixedThreadPool(numberOfWorkers
, '')).toThrowError(
50 expect(() => new FixedThreadPool(numberOfWorkers
, 0)).toThrowError(
53 expect(() => new FixedThreadPool(numberOfWorkers
, true)).toThrowError(
57 () => new FixedThreadPool(numberOfWorkers
, './dummyWorker.ts')
58 ).toThrowError(new Error("Cannot find the worker file './dummyWorker.ts'"))
61 it('Verify that numberOfWorkers is checked', () => {
62 expect(() => new FixedThreadPool()).toThrowError(
63 'Cannot instantiate a pool without specifying the number of workers'
67 it('Verify that a negative number of workers is checked', () => {
70 new FixedClusterPool(-1, './tests/worker-files/cluster/testWorker.js')
73 'Cannot instantiate a pool with a negative number of workers'
78 it('Verify that a non integer number of workers is checked', () => {
81 new FixedThreadPool(0.25, './tests/worker-files/thread/testWorker.js')
84 'Cannot instantiate a pool with a non safe integer number of workers'
89 it('Verify that dynamic pool sizing is checked', () => {
92 new DynamicClusterPool(
95 './tests/worker-files/cluster/testWorker.js'
99 'Cannot instantiate a dynamic pool without specifying the maximum pool size'
104 new DynamicThreadPool(
107 './tests/worker-files/thread/testWorker.js'
111 'Cannot instantiate a pool with a non safe integer number of workers'
116 new DynamicClusterPool(
119 './tests/worker-files/cluster/testWorker.js'
123 'Cannot instantiate a dynamic pool with a non safe integer maximum pool size'
128 new DynamicThreadPool(2, 1, './tests/worker-files/thread/testWorker.js')
131 'Cannot instantiate a dynamic pool with a maximum pool size inferior to the minimum pool size'
136 new DynamicClusterPool(
139 './tests/worker-files/cluster/testWorker.js'
143 'Cannot instantiate a dynamic pool with a minimum pool size equal to the maximum pool size. Use a fixed pool instead'
148 new DynamicThreadPool(0, 0, './tests/worker-files/thread/testWorker.js')
151 'Cannot instantiate a dynamic pool with a maximum pool size equal to zero'
156 it('Verify that pool options are checked', async () => {
157 let pool
= new FixedThreadPool(
159 './tests/worker-files/thread/testWorker.js'
161 expect(pool
.emitter
).toBeDefined()
162 expect(pool
.opts
.enableEvents
).toBe(true)
163 expect(pool
.opts
.restartWorkerOnError
).toBe(true)
164 expect(pool
.opts
.enableTasksQueue
).toBe(false)
165 expect(pool
.opts
.tasksQueueOptions
).toBeUndefined()
166 expect(pool
.opts
.workerChoiceStrategy
).toBe(
167 WorkerChoiceStrategies
.ROUND_ROBIN
169 expect(pool
.opts
.workerChoiceStrategyOptions
).toStrictEqual({
171 runTime
: { median
: false },
172 waitTime
: { median
: false },
173 elu
: { median
: false }
175 expect(pool
.workerChoiceStrategyContext
.opts
).toStrictEqual({
177 runTime
: { median
: false },
178 waitTime
: { median
: false },
179 elu
: { median
: false }
181 expect(pool
.opts
.messageHandler
).toBeUndefined()
182 expect(pool
.opts
.errorHandler
).toBeUndefined()
183 expect(pool
.opts
.onlineHandler
).toBeUndefined()
184 expect(pool
.opts
.exitHandler
).toBeUndefined()
186 const testHandler
= () => console
.info('test handler executed')
187 pool
= new FixedThreadPool(
189 './tests/worker-files/thread/testWorker.js',
191 workerChoiceStrategy
: WorkerChoiceStrategies
.LEAST_USED
,
192 workerChoiceStrategyOptions
: {
193 runTime
: { median
: true },
194 weights
: { 0: 300, 1: 200 }
197 restartWorkerOnError
: false,
198 enableTasksQueue
: true,
199 tasksQueueOptions
: { concurrency
: 2 },
200 messageHandler
: testHandler
,
201 errorHandler
: testHandler
,
202 onlineHandler
: testHandler
,
203 exitHandler
: testHandler
206 expect(pool
.emitter
).toBeUndefined()
207 expect(pool
.opts
.enableEvents
).toBe(false)
208 expect(pool
.opts
.restartWorkerOnError
).toBe(false)
209 expect(pool
.opts
.enableTasksQueue
).toBe(true)
210 expect(pool
.opts
.tasksQueueOptions
).toStrictEqual({ concurrency
: 2 })
211 expect(pool
.opts
.workerChoiceStrategy
).toBe(
212 WorkerChoiceStrategies
.LEAST_USED
214 expect(pool
.opts
.workerChoiceStrategyOptions
).toStrictEqual({
216 runTime
: { median
: true },
217 waitTime
: { median
: false },
218 elu
: { median
: false },
219 weights
: { 0: 300, 1: 200 }
221 expect(pool
.workerChoiceStrategyContext
.opts
).toStrictEqual({
223 runTime
: { median
: true },
224 waitTime
: { median
: false },
225 elu
: { median
: false },
226 weights
: { 0: 300, 1: 200 }
228 expect(pool
.opts
.messageHandler
).toStrictEqual(testHandler
)
229 expect(pool
.opts
.errorHandler
).toStrictEqual(testHandler
)
230 expect(pool
.opts
.onlineHandler
).toStrictEqual(testHandler
)
231 expect(pool
.opts
.exitHandler
).toStrictEqual(testHandler
)
235 it('Verify that pool options are validated', async () => {
240 './tests/worker-files/thread/testWorker.js',
242 workerChoiceStrategy
: 'invalidStrategy'
245 ).toThrowError("Invalid worker choice strategy 'invalidStrategy'")
250 './tests/worker-files/thread/testWorker.js',
252 workerChoiceStrategyOptions
: { weights
: {} }
256 'Invalid worker choice strategy options: must have a weight for each worker node'
262 './tests/worker-files/thread/testWorker.js',
264 workerChoiceStrategyOptions
: { measurement
: 'invalidMeasurement' }
268 "Invalid worker choice strategy options: invalid measurement 'invalidMeasurement'"
274 './tests/worker-files/thread/testWorker.js',
276 enableTasksQueue
: true,
277 tasksQueueOptions
: { concurrency
: 0 }
280 ).toThrowError("Invalid worker tasks concurrency '0'")
285 './tests/worker-files/thread/testWorker.js',
287 enableTasksQueue
: true,
288 tasksQueueOptions
: 'invalidTasksQueueOptions'
291 ).toThrowError('Invalid tasks queue options: must be a plain object')
296 './tests/worker-files/thread/testWorker.js',
298 enableTasksQueue
: true,
299 tasksQueueOptions
: { concurrency
: 0.2 }
302 ).toThrowError('Invalid worker tasks concurrency: must be an integer')
305 it('Verify that pool worker choice strategy options can be set', async () => {
306 const pool
= new FixedThreadPool(
308 './tests/worker-files/thread/testWorker.js',
309 { workerChoiceStrategy
: WorkerChoiceStrategies
.FAIR_SHARE
}
311 expect(pool
.opts
.workerChoiceStrategyOptions
).toStrictEqual({
313 runTime
: { median
: false },
314 waitTime
: { median
: false },
315 elu
: { median
: false }
317 expect(pool
.workerChoiceStrategyContext
.opts
).toStrictEqual({
319 runTime
: { median
: false },
320 waitTime
: { median
: false },
321 elu
: { median
: false }
323 for (const [, workerChoiceStrategy
] of pool
.workerChoiceStrategyContext
324 .workerChoiceStrategies
) {
325 expect(workerChoiceStrategy
.opts
).toStrictEqual({
327 runTime
: { median
: false },
328 waitTime
: { median
: false },
329 elu
: { median
: false }
333 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
351 pool
.setWorkerChoiceStrategyOptions({
352 runTime
: { median
: true },
353 elu
: { median
: true }
355 expect(pool
.opts
.workerChoiceStrategyOptions
).toStrictEqual({
357 runTime
: { median
: true },
358 waitTime
: { median
: false },
359 elu
: { median
: true }
361 expect(pool
.workerChoiceStrategyContext
.opts
).toStrictEqual({
363 runTime
: { median
: true },
364 waitTime
: { median
: false },
365 elu
: { median
: true }
367 for (const [, workerChoiceStrategy
] of pool
.workerChoiceStrategyContext
368 .workerChoiceStrategies
) {
369 expect(workerChoiceStrategy
.opts
).toStrictEqual({
371 runTime
: { median
: true },
372 waitTime
: { median
: false },
373 elu
: { median
: true }
377 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
395 pool
.setWorkerChoiceStrategyOptions({
396 runTime
: { median
: false },
397 elu
: { median
: false }
399 expect(pool
.opts
.workerChoiceStrategyOptions
).toStrictEqual({
401 runTime
: { median
: false },
402 waitTime
: { median
: false },
403 elu
: { median
: false }
405 expect(pool
.workerChoiceStrategyContext
.opts
).toStrictEqual({
407 runTime
: { median
: false },
408 waitTime
: { median
: false },
409 elu
: { median
: false }
411 for (const [, workerChoiceStrategy
] of pool
.workerChoiceStrategyContext
412 .workerChoiceStrategies
) {
413 expect(workerChoiceStrategy
.opts
).toStrictEqual({
415 runTime
: { median
: false },
416 waitTime
: { median
: false },
417 elu
: { median
: false }
421 pool
.workerChoiceStrategyContext
.getTaskStatisticsRequirements()
440 pool
.setWorkerChoiceStrategyOptions('invalidWorkerChoiceStrategyOptions')
442 'Invalid worker choice strategy options: must be a plain object'
445 pool
.setWorkerChoiceStrategyOptions({ weights
: {} })
447 'Invalid worker choice strategy options: must have a weight for each worker node'
450 pool
.setWorkerChoiceStrategyOptions({ measurement
: 'invalidMeasurement' })
452 "Invalid worker choice strategy options: invalid measurement 'invalidMeasurement'"
457 it('Verify that pool tasks queue can be enabled/disabled', async () => {
458 const pool
= new FixedThreadPool(
460 './tests/worker-files/thread/testWorker.js'
462 expect(pool
.opts
.enableTasksQueue
).toBe(false)
463 expect(pool
.opts
.tasksQueueOptions
).toBeUndefined()
464 pool
.enableTasksQueue(true)
465 expect(pool
.opts
.enableTasksQueue
).toBe(true)
466 expect(pool
.opts
.tasksQueueOptions
).toStrictEqual({ concurrency
: 1 })
467 pool
.enableTasksQueue(true, { concurrency
: 2 })
468 expect(pool
.opts
.enableTasksQueue
).toBe(true)
469 expect(pool
.opts
.tasksQueueOptions
).toStrictEqual({ concurrency
: 2 })
470 pool
.enableTasksQueue(false)
471 expect(pool
.opts
.enableTasksQueue
).toBe(false)
472 expect(pool
.opts
.tasksQueueOptions
).toBeUndefined()
476 it('Verify that pool tasks queue options can be set', async () => {
477 const pool
= new FixedThreadPool(
479 './tests/worker-files/thread/testWorker.js',
480 { enableTasksQueue
: true }
482 expect(pool
.opts
.tasksQueueOptions
).toStrictEqual({ concurrency
: 1 })
483 pool
.setTasksQueueOptions({ concurrency
: 2 })
484 expect(pool
.opts
.tasksQueueOptions
).toStrictEqual({ concurrency
: 2 })
486 pool
.setTasksQueueOptions('invalidTasksQueueOptions')
487 ).toThrowError('Invalid tasks queue options: must be a plain object')
488 expect(() => pool
.setTasksQueueOptions({ concurrency
: 0 })).toThrowError(
489 "Invalid worker tasks concurrency '0'"
491 expect(() => pool
.setTasksQueueOptions({ concurrency
: 0.2 })).toThrowError(
492 'Invalid worker tasks concurrency: must be an integer'
497 it('Verify that pool info is set', async () => {
498 let pool
= new FixedThreadPool(
500 './tests/worker-files/thread/testWorker.js'
502 expect(pool
.info
).toStrictEqual({
504 type
: PoolTypes
.fixed
,
505 worker
: WorkerTypes
.thread
,
507 strategy
: WorkerChoiceStrategies
.ROUND_ROBIN
,
508 minSize
: numberOfWorkers
,
509 maxSize
: numberOfWorkers
,
510 workerNodes
: numberOfWorkers
,
511 idleWorkerNodes
: numberOfWorkers
,
518 pool
= new DynamicClusterPool(
519 Math
.floor(numberOfWorkers
/ 2),
521 './tests/worker-files/cluster/testWorker.js'
523 expect(pool
.info
).toStrictEqual({
525 type
: PoolTypes
.dynamic
,
526 worker
: WorkerTypes
.cluster
,
528 strategy
: WorkerChoiceStrategies
.ROUND_ROBIN
,
529 minSize
: Math
.floor(numberOfWorkers
/ 2),
530 maxSize
: numberOfWorkers
,
531 workerNodes
: Math
.floor(numberOfWorkers
/ 2),
532 idleWorkerNodes
: Math
.floor(numberOfWorkers
/ 2),
541 it('Verify that pool worker tasks usage are initialized', async () => {
542 const pool
= new FixedClusterPool(
544 './tests/worker-files/cluster/testWorker.js'
546 for (const workerNode
of pool
.workerNodes
) {
547 expect(workerNode
.usage
).toStrictEqual({
556 history
: expect
.any(CircularArray
)
559 history
: expect
.any(CircularArray
)
563 history
: expect
.any(CircularArray
)
566 history
: expect
.any(CircularArray
)
574 it('Verify that pool worker tasks queue are initialized', async () => {
575 let pool
= new FixedClusterPool(
577 './tests/worker-files/cluster/testWorker.js'
579 for (const workerNode
of pool
.workerNodes
) {
580 expect(workerNode
.tasksQueue
).toBeDefined()
581 expect(workerNode
.tasksQueue
).toBeInstanceOf(Queue
)
582 expect(workerNode
.tasksQueue
.size
).toBe(0)
583 expect(workerNode
.tasksQueue
.maxSize
).toBe(0)
586 pool
= new DynamicThreadPool(
587 Math
.floor(numberOfWorkers
/ 2),
589 './tests/worker-files/thread/testWorker.js'
591 for (const workerNode
of pool
.workerNodes
) {
592 expect(workerNode
.tasksQueue
).toBeDefined()
593 expect(workerNode
.tasksQueue
).toBeInstanceOf(Queue
)
594 expect(workerNode
.tasksQueue
.size
).toBe(0)
595 expect(workerNode
.tasksQueue
.maxSize
).toBe(0)
599 it('Verify that pool worker info are initialized', async () => {
600 let pool
= new FixedClusterPool(
602 './tests/worker-files/cluster/testWorker.js'
604 for (const workerNode
of pool
.workerNodes
) {
605 expect(workerNode
.info
).toStrictEqual({
606 id
: expect
.any(Number
),
607 type
: WorkerTypes
.cluster
,
613 pool
= new DynamicThreadPool(
614 Math
.floor(numberOfWorkers
/ 2),
616 './tests/worker-files/thread/testWorker.js'
618 for (const workerNode
of pool
.workerNodes
) {
619 expect(workerNode
.info
).toStrictEqual({
620 id
: expect
.any(Number
),
621 type
: WorkerTypes
.thread
,
628 it('Verify that pool worker tasks usage are computed', async () => {
629 const pool
= new FixedClusterPool(
631 './tests/worker-files/cluster/testWorker.js'
633 const promises
= new Set()
634 const maxMultiplier
= 2
635 for (let i
= 0; i
< numberOfWorkers
* maxMultiplier
; i
++) {
636 promises
.add(pool
.execute())
638 for (const workerNode
of pool
.workerNodes
) {
639 expect(workerNode
.usage
).toStrictEqual({
642 executing
: maxMultiplier
,
648 history
: expect
.any(CircularArray
)
651 history
: expect
.any(CircularArray
)
655 history
: expect
.any(CircularArray
)
658 history
: expect
.any(CircularArray
)
663 await Promise
.all(promises
)
664 for (const workerNode
of pool
.workerNodes
) {
665 expect(workerNode
.usage
).toStrictEqual({
667 executed
: maxMultiplier
,
674 history
: expect
.any(CircularArray
)
677 history
: expect
.any(CircularArray
)
681 history
: expect
.any(CircularArray
)
684 history
: expect
.any(CircularArray
)
692 it('Verify that pool worker tasks usage are reset at worker choice strategy change', async () => {
693 const pool
= new DynamicThreadPool(
694 Math
.floor(numberOfWorkers
/ 2),
696 './tests/worker-files/thread/testWorker.js'
698 const promises
= new Set()
699 const maxMultiplier
= 2
700 for (let i
= 0; i
< numberOfWorkers
* maxMultiplier
; i
++) {
701 promises
.add(pool
.execute())
703 await Promise
.all(promises
)
704 for (const workerNode
of pool
.workerNodes
) {
705 expect(workerNode
.usage
).toStrictEqual({
707 executed
: expect
.any(Number
),
714 history
: expect
.any(CircularArray
)
717 history
: expect
.any(CircularArray
)
721 history
: expect
.any(CircularArray
)
724 history
: expect
.any(CircularArray
)
728 expect(workerNode
.usage
.tasks
.executed
).toBeGreaterThan(0)
729 expect(workerNode
.usage
.tasks
.executed
).toBeLessThanOrEqual(maxMultiplier
)
730 expect(workerNode
.usage
.runTime
.history
.length
).toBe(0)
731 expect(workerNode
.usage
.waitTime
.history
.length
).toBe(0)
732 expect(workerNode
.usage
.elu
.idle
.history
.length
).toBe(0)
733 expect(workerNode
.usage
.elu
.active
.history
.length
).toBe(0)
735 pool
.setWorkerChoiceStrategy(WorkerChoiceStrategies
.FAIR_SHARE
)
736 for (const workerNode
of pool
.workerNodes
) {
737 expect(workerNode
.usage
).toStrictEqual({
746 history
: expect
.any(CircularArray
)
749 history
: expect
.any(CircularArray
)
753 history
: expect
.any(CircularArray
)
756 history
: expect
.any(CircularArray
)
760 expect(workerNode
.usage
.runTime
.history
.length
).toBe(0)
761 expect(workerNode
.usage
.waitTime
.history
.length
).toBe(0)
762 expect(workerNode
.usage
.elu
.idle
.history
.length
).toBe(0)
763 expect(workerNode
.usage
.elu
.active
.history
.length
).toBe(0)
768 it("Verify that pool event emitter 'full' event can register a callback", async () => {
769 const pool
= new DynamicThreadPool(
770 Math
.floor(numberOfWorkers
/ 2),
772 './tests/worker-files/thread/testWorker.js'
774 const promises
= new Set()
777 pool
.emitter
.on(PoolEvents
.full
, (info
) => {
781 for (let i
= 0; i
< numberOfWorkers
* 2; i
++) {
782 promises
.add(pool
.execute())
784 await Promise
.all(promises
)
785 // The `full` event is triggered when the number of submitted tasks at once reach the maximum number of workers in the dynamic pool.
786 // So in total numberOfWorkers * 2 - 1 times for a loop submitting up to numberOfWorkers * 2 tasks to the dynamic pool with min = (max = numberOfWorkers) / 2.
787 expect(poolFull
).toBe(numberOfWorkers
* 2 - 1)
788 expect(poolInfo
).toStrictEqual({
790 type
: PoolTypes
.dynamic
,
791 worker
: WorkerTypes
.thread
,
792 ready
: expect
.any(Boolean
),
793 strategy
: WorkerChoiceStrategies
.ROUND_ROBIN
,
794 minSize
: expect
.any(Number
),
795 maxSize
: expect
.any(Number
),
796 workerNodes
: expect
.any(Number
),
797 idleWorkerNodes
: expect
.any(Number
),
798 busyWorkerNodes
: expect
.any(Number
),
799 executedTasks
: expect
.any(Number
),
800 executingTasks
: expect
.any(Number
),
801 failedTasks
: expect
.any(Number
)
806 it("Verify that pool event emitter 'ready' event can register a callback", async () => {
807 const pool
= new DynamicClusterPool(
808 Math
.floor(numberOfWorkers
/ 2),
810 './tests/worker-files/cluster/testWorker.js'
814 pool
.emitter
.on(PoolEvents
.ready
, (info
) => {
818 await
waitPoolEvents(pool
, PoolEvents
.ready
, 1)
819 expect(poolReady
).toBe(1)
820 expect(poolInfo
).toStrictEqual({
822 type
: PoolTypes
.dynamic
,
823 worker
: WorkerTypes
.cluster
,
825 strategy
: WorkerChoiceStrategies
.ROUND_ROBIN
,
826 minSize
: expect
.any(Number
),
827 maxSize
: expect
.any(Number
),
828 workerNodes
: expect
.any(Number
),
829 idleWorkerNodes
: expect
.any(Number
),
830 busyWorkerNodes
: expect
.any(Number
),
831 executedTasks
: expect
.any(Number
),
832 executingTasks
: expect
.any(Number
),
833 failedTasks
: expect
.any(Number
)
838 it("Verify that pool event emitter 'busy' event can register a callback", async () => {
839 const pool
= new FixedThreadPool(
841 './tests/worker-files/thread/testWorker.js'
843 const promises
= new Set()
846 pool
.emitter
.on(PoolEvents
.busy
, (info
) => {
850 for (let i
= 0; i
< numberOfWorkers
* 2; i
++) {
851 promises
.add(pool
.execute())
853 await Promise
.all(promises
)
854 // The `busy` event is triggered when the number of submitted tasks at once reach the number of fixed pool workers.
855 // So in total numberOfWorkers + 1 times for a loop submitting up to numberOfWorkers * 2 tasks to the fixed pool.
856 expect(poolBusy
).toBe(numberOfWorkers
+ 1)
857 expect(poolInfo
).toStrictEqual({
859 type
: PoolTypes
.fixed
,
860 worker
: WorkerTypes
.thread
,
861 ready
: expect
.any(Boolean
),
862 strategy
: WorkerChoiceStrategies
.ROUND_ROBIN
,
863 minSize
: expect
.any(Number
),
864 maxSize
: expect
.any(Number
),
865 workerNodes
: expect
.any(Number
),
866 idleWorkerNodes
: expect
.any(Number
),
867 busyWorkerNodes
: expect
.any(Number
),
868 executedTasks
: expect
.any(Number
),
869 executingTasks
: expect
.any(Number
),
870 failedTasks
: expect
.any(Number
)
875 it('Verify that listTaskFunctions() is working', async () => {
876 const dynamicThreadPool
= new DynamicThreadPool(
877 Math
.floor(numberOfWorkers
/ 2),
879 './tests/worker-files/thread/testMultipleTaskFunctionsWorker.js'
881 await
waitPoolEvents(dynamicThreadPool
, PoolEvents
.ready
, 1)
882 expect(dynamicThreadPool
.listTaskFunctions()).toStrictEqual([
884 'jsonIntegerSerialization',
888 const fixedClusterPool
= new FixedClusterPool(
890 './tests/worker-files/cluster/testMultipleTaskFunctionsWorker.js'
892 await
waitPoolEvents(fixedClusterPool
, PoolEvents
.ready
, 1)
893 expect(fixedClusterPool
.listTaskFunctions()).toStrictEqual([
895 'jsonIntegerSerialization',
901 it('Verify that multiple task functions worker is working', async () => {
902 const pool
= new DynamicClusterPool(
903 Math
.floor(numberOfWorkers
/ 2),
905 './tests/worker-files/cluster/testMultipleTaskFunctionsWorker.js'
907 const data
= { n
: 10 }
908 const result0
= await pool
.execute(data
)
909 expect(result0
).toStrictEqual({ ok
: 1 })
910 const result1
= await pool
.execute(data
, 'jsonIntegerSerialization')
911 expect(result1
).toStrictEqual({ ok
: 1 })
912 const result2
= await pool
.execute(data
, 'factorial')
913 expect(result2
).toBe(3628800)
914 const result3
= await pool
.execute(data
, 'fibonacci')
915 expect(result3
).toBe(55)
916 expect(pool
.info
.executingTasks
).toBe(0)
917 expect(pool
.info
.executedTasks
).toBe(4)
918 for (const workerNode
of pool
.workerNodes
) {
919 expect(workerNode
.info
.taskFunctions
).toStrictEqual([
921 'jsonIntegerSerialization',
925 expect(workerNode
.taskFunctionsUsage
.size
).toBe(3)
926 for (const name
of pool
.listTaskFunctions()) {
927 expect(workerNode
.getTaskFunctionWorkerUsage(name
)).toStrictEqual({
929 executed
: expect
.any(Number
),
930 executing
: expect
.any(Number
),
935 history
: expect
.any(CircularArray
)
938 history
: expect
.any(CircularArray
)
942 history
: expect
.any(CircularArray
)
945 history
: expect
.any(CircularArray
)
950 workerNode
.getTaskFunctionWorkerUsage(name
).tasks
.executing
951 ).toBeGreaterThanOrEqual(0)