## [Unreleased]
+### Added
+
+- Switch pool event emitter to `EventEmitterAsyncResource`.
+
+### Changed
+
+- Renamed worker choice strategy `LESS_BUSY` to `LEAST_BUSY` and `LESS_USED` to `LEAST_USED`.
+
## [2.4.14] - 2023-05-09
### Fixed
- `workerChoiceStrategy` (optional) - The worker choice strategy to use in this pool:
- `WorkerChoiceStrategies.ROUND_ROBIN`: Submit tasks to worker in a round robbin fashion
- - `WorkerChoiceStrategies.LESS_USED`: Submit tasks to the less used worker
- - `WorkerChoiceStrategies.LESS_BUSY`: Submit tasks to the less busy worker
+ - `WorkerChoiceStrategies.LEAST_USED`: Submit tasks to the least used worker
+ - `WorkerChoiceStrategies.LEAST_BUSY`: Submit tasks to the least busy worker
- `WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN`: Submit tasks to worker using a weighted round robin scheduling algorithm based on tasks execution time
- `WorkerChoiceStrategies.FAIR_SHARE`: Submit tasks to worker using a fair share tasks scheduling algorithm based on tasks execution time
const workerChoiceStrategyRoundRobinPoolOption = {
workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN
}
-const workerChoiceStrategyLessUsedPoolOption = {
- workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED
+const workerChoiceStrategyLeastUsedPoolOption = {
+ workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED
}
-const workerChoiceStrategyLessBusyPoolOption = {
- workerChoiceStrategy: WorkerChoiceStrategies.LESS_BUSY
+const workerChoiceStrategyLeastBusyPoolOption = {
+ workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY
}
const workerChoiceStrategyWeightedRoundRobinPoolOption = {
workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
{ ...workerChoiceStrategyRoundRobinPoolOption, ...tasksQueuePoolOption }
)
-const fixedThreadPoolLessUsed = buildPool(
+const fixedThreadPoolLeastUsed = buildPool(
WorkerTypes.THREAD,
PoolTypes.FIXED,
poolSize,
- workerChoiceStrategyLessUsedPoolOption
+ workerChoiceStrategyLeastUsedPoolOption
)
-const fixedThreadPoolLessBusy = buildPool(
+const fixedThreadPoolLeastBusy = buildPool(
WorkerTypes.THREAD,
PoolTypes.FIXED,
poolSize,
- workerChoiceStrategyLessBusyPoolOption
+ workerChoiceStrategyLeastBusyPoolOption
)
const fixedThreadPoolWeightedRoundRobin = buildPool(
workerChoiceStrategyRoundRobinPoolOption
)
-const dynamicThreadPoolLessUsed = buildPool(
+const dynamicThreadPoolLeastUsed = buildPool(
WorkerTypes.THREAD,
PoolTypes.DYNAMIC,
poolSize,
- workerChoiceStrategyLessUsedPoolOption
+ workerChoiceStrategyLeastUsedPoolOption
)
-const dynamicThreadPoolLessBusy = buildPool(
+const dynamicThreadPoolLeastBusy = buildPool(
WorkerTypes.THREAD,
PoolTypes.DYNAMIC,
poolSize,
- workerChoiceStrategyLessBusyPoolOption
+ workerChoiceStrategyLeastBusyPoolOption
)
const dynamicThreadPoolWeightedRoundRobin = buildPool(
{ ...workerChoiceStrategyRoundRobinPoolOption, ...tasksQueuePoolOption }
)
-const fixedClusterPoolLessUsed = buildPool(
+const fixedClusterPoolLeastUsed = buildPool(
WorkerTypes.CLUSTER,
PoolTypes.FIXED,
poolSize,
- workerChoiceStrategyLessUsedPoolOption
+ workerChoiceStrategyLeastUsedPoolOption
)
-const fixedClusterPoolLessBusy = buildPool(
+const fixedClusterPoolLeastBusy = buildPool(
WorkerTypes.CLUSTER,
PoolTypes.FIXED,
poolSize,
- workerChoiceStrategyLessBusyPoolOption
+ workerChoiceStrategyLeastBusyPoolOption
)
const fixedClusterPoolWeightedRoundRobin = buildPool(
workerChoiceStrategyRoundRobinPoolOption
)
-const dynamicClusterPoolLessUsed = buildPool(
+const dynamicClusterPoolLeastUsed = buildPool(
WorkerTypes.CLUSTER,
PoolTypes.DYNAMIC,
poolSize,
- workerChoiceStrategyLessUsedPoolOption
+ workerChoiceStrategyLeastUsedPoolOption
)
-const dynamicClusterPoolLessBusy = buildPool(
+const dynamicClusterPoolLeastBusy = buildPool(
WorkerTypes.CLUSTER,
PoolTypes.DYNAMIC,
poolSize,
- workerChoiceStrategyLessBusyPoolOption
+ workerChoiceStrategyLeastBusyPoolOption
)
const dynamicClusterPoolWeightedRoundRobin = buildPool(
})
}
),
- Benchmark.add('Fixed:ThreadPool:LessUsed', async () => {
- await runTest(fixedThreadPoolLessUsed, {
+ Benchmark.add('Fixed:ThreadPool:LeastUsed', async () => {
+ await runTest(fixedThreadPoolLeastUsed, {
taskExecutions,
workerData
})
}),
- Benchmark.add('Fixed:ThreadPool:LessBusy', async () => {
- await runTest(fixedThreadPoolLessBusy, {
+ Benchmark.add('Fixed:ThreadPool:LeastBusy', async () => {
+ await runTest(fixedThreadPoolLeastBusy, {
taskExecutions,
workerData
})
workerData
})
}),
- Benchmark.add('Dynamic:ThreadPool:LessUsed', async () => {
- await runTest(dynamicThreadPoolLessUsed, {
+ Benchmark.add('Dynamic:ThreadPool:LeastUsed', async () => {
+ await runTest(dynamicThreadPoolLeastUsed, {
taskExecutions,
workerData
})
}),
- Benchmark.add('Dynamic:ThreadPool:LessBusy', async () => {
- await runTest(dynamicThreadPoolLessBusy, {
+ Benchmark.add('Dynamic:ThreadPool:LeastBusy', async () => {
+ await runTest(dynamicThreadPoolLeastBusy, {
taskExecutions,
workerData
})
})
}
),
- Benchmark.add('Fixed:ClusterPool:LessUsed', async () => {
- await runTest(fixedClusterPoolLessUsed, {
+ Benchmark.add('Fixed:ClusterPool:LeastUsed', async () => {
+ await runTest(fixedClusterPoolLeastUsed, {
taskExecutions,
workerData
})
}),
- Benchmark.add('Fixed:ClusterPool:LessBusy', async () => {
- await runTest(fixedClusterPoolLessBusy, {
+ Benchmark.add('Fixed:ClusterPool:LeastBusy', async () => {
+ await runTest(fixedClusterPoolLeastBusy, {
taskExecutions,
workerData
})
workerData
})
}),
- Benchmark.add('Dynamic:ClusterPool:LessUsed', async () => {
- await runTest(dynamicClusterPoolLessUsed, {
+ Benchmark.add('Dynamic:ClusterPool:LeastUsed', async () => {
+ await runTest(dynamicClusterPoolLeastUsed, {
taskExecutions,
workerData
})
}),
- Benchmark.add('Dynamic:ClusterPool:LessBusy', async () => {
- await runTest(dynamicClusterPoolLessBusy, {
+ Benchmark.add('Dynamic:ClusterPool:LeastBusy', async () => {
+ await runTest(dynamicClusterPoolLeastBusy, {
taskExecutions,
workerData
})
}
Benchmark.suite(
- 'Less used worker tasks distribution',
+ 'Least used worker tasks distribution',
Benchmark.add('Loop select', () => {
loopSelect(tasksMap)
}),
} from './selection-strategies-types'
/**
- * Selects the less busy worker.
+ * Selects the least busy worker.
*
* @typeParam Worker - Type of worker which manages the strategy.
* @typeParam Data - Type of data sent to the worker. This can only be serializable data.
* @typeParam Response - Type of execution response. This can only be serializable data.
*/
-export class LessBusyWorkerChoiceStrategy<
+export class LeastBusyWorkerChoiceStrategy<
Worker extends IWorker,
Data = unknown,
Response = unknown
return freeWorkerNodeKey
}
let minRunTime = Infinity
- let lessBusyWorkerNodeKey!: number
+ let leastBusyWorkerNodeKey!: number
for (const [workerNodeKey, workerNode] of this.pool.workerNodes.entries()) {
const workerRunTime = workerNode.tasksUsage.runTime
if (workerRunTime === 0) {
return workerNodeKey
} else if (workerRunTime < minRunTime) {
minRunTime = workerRunTime
- lessBusyWorkerNodeKey = workerNodeKey
+ leastBusyWorkerNodeKey = workerNodeKey
}
}
- return lessBusyWorkerNodeKey
+ return leastBusyWorkerNodeKey
}
/** @inheritDoc */
} from './selection-strategies-types'
/**
- * Selects the less used worker.
+ * Selects the least used worker.
*
* @typeParam Worker - Type of worker which manages the strategy.
* @typeParam Data - Type of data sent to the worker. This can only be serializable data.
* @typeParam Response - Type of execution response. This can only be serializable data.
*/
-export class LessUsedWorkerChoiceStrategy<
+export class LeastUsedWorkerChoiceStrategy<
Worker extends IWorker,
Data = unknown,
Response = unknown
return freeWorkerNodeKey
}
let minNumberOfTasks = Infinity
- let lessUsedWorkerNodeKey!: number
+ let leastUsedWorkerNodeKey!: number
for (const [workerNodeKey, workerNode] of this.pool.workerNodes.entries()) {
const tasksUsage = workerNode.tasksUsage
const workerTasks = tasksUsage.run + tasksUsage.running
return workerNodeKey
} else if (workerTasks < minNumberOfTasks) {
minNumberOfTasks = workerTasks
- lessUsedWorkerNodeKey = workerNodeKey
+ leastUsedWorkerNodeKey = workerNodeKey
}
}
- return lessUsedWorkerNodeKey
+ return leastUsedWorkerNodeKey
}
/** @inheritDoc */
*/
ROUND_ROBIN: 'ROUND_ROBIN',
/**
- * Less used worker selection strategy.
+ * Least used worker selection strategy.
*/
- LESS_USED: 'LESS_USED',
+ LEAST_USED: 'LEAST_USED',
/**
- * Less busy worker selection strategy.
+ * Least busy worker selection strategy.
*/
- LESS_BUSY: 'LESS_BUSY',
+ LEAST_BUSY: 'LEAST_BUSY',
/**
* Fair share worker selection strategy.
*/
import type { IPool } from '../pool'
import type { IWorker } from '../worker'
import { FairShareWorkerChoiceStrategy } from './fair-share-worker-choice-strategy'
-import { LessBusyWorkerChoiceStrategy } from './less-busy-worker-choice-strategy'
-import { LessUsedWorkerChoiceStrategy } from './less-used-worker-choice-strategy'
+import { LeastBusyWorkerChoiceStrategy } from './least-busy-worker-choice-strategy'
+import { LeastUsedWorkerChoiceStrategy } from './least-used-worker-choice-strategy'
import { RoundRobinWorkerChoiceStrategy } from './round-robin-worker-choice-strategy'
import type {
IWorkerChoiceStrategy,
)
],
[
- WorkerChoiceStrategies.LESS_USED,
- new (LessUsedWorkerChoiceStrategy.bind(this))<Worker, Data, Response>(
+ WorkerChoiceStrategies.LEAST_USED,
+ new (LeastUsedWorkerChoiceStrategy.bind(this))<Worker, Data, Response>(
pool,
opts
)
],
[
- WorkerChoiceStrategies.LESS_BUSY,
- new (LessBusyWorkerChoiceStrategy.bind(this))<Worker, Data, Response>(
+ WorkerChoiceStrategies.LEAST_BUSY,
+ new (LeastBusyWorkerChoiceStrategy.bind(this))<Worker, Data, Response>(
pool,
opts
)
numberOfWorkers,
'./tests/worker-files/thread/testWorker.js',
{
- workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED,
+ workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED,
workerChoiceStrategyOptions: {
medRunTime: true,
weights: { 0: 300 }
expect(pool.opts.enableTasksQueue).toBe(true)
expect(pool.opts.tasksQueueOptions).toStrictEqual({ concurrency: 2 })
expect(pool.opts.workerChoiceStrategy).toBe(
- WorkerChoiceStrategies.LESS_USED
+ WorkerChoiceStrategies.LEAST_USED
)
expect(pool.opts.workerChoiceStrategyOptions).toStrictEqual({
medRunTime: true,
it('Verify that WorkerChoiceStrategies enumeration provides string values', () => {
expect(WorkerChoiceStrategies.ROUND_ROBIN).toBe('ROUND_ROBIN')
- expect(WorkerChoiceStrategies.LESS_USED).toBe('LESS_USED')
- expect(WorkerChoiceStrategies.LESS_BUSY).toBe('LESS_BUSY')
+ expect(WorkerChoiceStrategies.LEAST_USED).toBe('LEAST_USED')
+ expect(WorkerChoiceStrategies.LEAST_BUSY).toBe('LEAST_BUSY')
expect(WorkerChoiceStrategies.FAIR_SHARE).toBe('FAIR_SHARE')
expect(WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN).toBe(
'WEIGHTED_ROUND_ROBIN'
await pool.destroy()
})
- it('Verify LESS_USED strategy default tasks usage statistics requirements', async () => {
- const workerChoiceStrategy = WorkerChoiceStrategies.LESS_USED
+ it('Verify LEAST_USED strategy default tasks usage statistics requirements', async () => {
+ const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
let pool = new FixedThreadPool(
max,
'./tests/worker-files/thread/testWorker.js',
await pool.destroy()
})
- it('Verify LESS_USED strategy can be run in a fixed pool', async () => {
+ it('Verify LEAST_USED strategy can be run in a fixed pool', async () => {
const pool = new FixedThreadPool(
max,
'./tests/worker-files/thread/testWorker.js',
- { workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED }
+ { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
)
- // TODO: Create a better test to cover `LessUsedWorkerChoiceStrategy#choose`
+ // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
const maxMultiplier = 2
for (let i = 0; i < max * maxMultiplier; i++) {
await pool.execute()
await pool.destroy()
})
- it('Verify LESS_USED strategy can be run in a dynamic pool', async () => {
+ it('Verify LEAST_USED strategy can be run in a dynamic pool', async () => {
const pool = new DynamicThreadPool(
min,
max,
'./tests/worker-files/thread/testWorker.js',
- { workerChoiceStrategy: WorkerChoiceStrategies.LESS_USED }
+ { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_USED }
)
- // TODO: Create a better test to cover `LessUsedWorkerChoiceStrategy#choose`
+ // TODO: Create a better test to cover `LeastUsedWorkerChoiceStrategy#choose`
const maxMultiplier = 2
for (let i = 0; i < max * maxMultiplier; i++) {
await pool.execute()
await pool.destroy()
})
- it('Verify LESS_BUSY strategy default tasks usage statistics requirements', async () => {
- const workerChoiceStrategy = WorkerChoiceStrategies.LESS_BUSY
+ it('Verify LEAST_BUSY strategy default tasks usage statistics requirements', async () => {
+ const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
let pool = new FixedThreadPool(
max,
'./tests/worker-files/thread/testWorker.js',
await pool.destroy()
})
- it('Verify LESS_BUSY strategy can be run in a fixed pool', async () => {
+ it('Verify LEAST_BUSY strategy can be run in a fixed pool', async () => {
const pool = new FixedThreadPool(
max,
'./tests/worker-files/thread/testWorker.js',
- { workerChoiceStrategy: WorkerChoiceStrategies.LESS_BUSY }
+ { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
)
- // TODO: Create a better test to cover `LessBusyWorkerChoiceStrategy#choose`
+ // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
const maxMultiplier = 2
for (let i = 0; i < max * maxMultiplier; i++) {
await pool.execute()
await pool.destroy()
})
- it('Verify LESS_BUSY strategy can be run in a dynamic pool', async () => {
+ it('Verify LEAST_BUSY strategy can be run in a dynamic pool', async () => {
const pool = new DynamicThreadPool(
min,
max,
'./tests/worker-files/thread/testWorker.js',
- { workerChoiceStrategy: WorkerChoiceStrategies.LESS_BUSY }
+ { workerChoiceStrategy: WorkerChoiceStrategies.LEAST_BUSY }
)
- // TODO: Create a better test to cover `LessBusyWorkerChoiceStrategy#choose`
+ // TODO: Create a better test to cover `LeastBusyWorkerChoiceStrategy#choose`
const maxMultiplier = 2
for (let i = 0; i < max * maxMultiplier; i++) {
await pool.execute()
RoundRobinWorkerChoiceStrategy
} = require('../../../lib/pools/selection-strategies/round-robin-worker-choice-strategy')
const {
- LessUsedWorkerChoiceStrategy
-} = require('../../../lib/pools/selection-strategies/less-used-worker-choice-strategy')
+ LeastUsedWorkerChoiceStrategy
+} = require('../../../lib/pools/selection-strategies/least-used-worker-choice-strategy')
const {
- LessBusyWorkerChoiceStrategy
-} = require('../../../lib/pools/selection-strategies/less-busy-worker-choice-strategy')
+ LeastBusyWorkerChoiceStrategy
+} = require('../../../lib/pools/selection-strategies/least-busy-worker-choice-strategy')
const {
FairShareWorkerChoiceStrategy
} = require('../../../lib/pools/selection-strategies/fair-share-worker-choice-strategy')
)
})
- it('Verify that setWorkerChoiceStrategy() works with LESS_USED and fixed pool', () => {
- const workerChoiceStrategy = WorkerChoiceStrategies.LESS_USED
+ it('Verify that setWorkerChoiceStrategy() works with LEAST_USED and fixed pool', () => {
+ const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
fixedPool
)
workerChoiceStrategyContext.workerChoiceStrategies.get(
workerChoiceStrategy
)
- ).toBeInstanceOf(LessUsedWorkerChoiceStrategy)
+ ).toBeInstanceOf(LeastUsedWorkerChoiceStrategy)
expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
workerChoiceStrategy
)
})
- it('Verify that setWorkerChoiceStrategy() works with LESS_USED and dynamic pool', () => {
- const workerChoiceStrategy = WorkerChoiceStrategies.LESS_USED
+ it('Verify that setWorkerChoiceStrategy() works with LEAST_USED and dynamic pool', () => {
+ const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_USED
const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
dynamicPool
)
workerChoiceStrategyContext.workerChoiceStrategies.get(
workerChoiceStrategy
)
- ).toBeInstanceOf(LessUsedWorkerChoiceStrategy)
+ ).toBeInstanceOf(LeastUsedWorkerChoiceStrategy)
expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
workerChoiceStrategy
)
})
- it('Verify that setWorkerChoiceStrategy() works with LESS_BUSY and fixed pool', () => {
- const workerChoiceStrategy = WorkerChoiceStrategies.LESS_BUSY
+ it('Verify that setWorkerChoiceStrategy() works with LEAST_BUSY and fixed pool', () => {
+ const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
fixedPool
)
workerChoiceStrategyContext.workerChoiceStrategies.get(
workerChoiceStrategy
)
- ).toBeInstanceOf(LessBusyWorkerChoiceStrategy)
+ ).toBeInstanceOf(LeastBusyWorkerChoiceStrategy)
expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
workerChoiceStrategy
)
})
- it('Verify that setWorkerChoiceStrategy() works with LESS_BUSY and dynamic pool', () => {
- const workerChoiceStrategy = WorkerChoiceStrategies.LESS_BUSY
+ it('Verify that setWorkerChoiceStrategy() works with LEAST_BUSY and dynamic pool', () => {
+ const workerChoiceStrategy = WorkerChoiceStrategies.LEAST_BUSY
const workerChoiceStrategyContext = new WorkerChoiceStrategyContext(
dynamicPool
)
workerChoiceStrategyContext.workerChoiceStrategies.get(
workerChoiceStrategy
)
- ).toBeInstanceOf(LessBusyWorkerChoiceStrategy)
+ ).toBeInstanceOf(LeastBusyWorkerChoiceStrategy)
expect(workerChoiceStrategyContext.workerChoiceStrategy).toBe(
workerChoiceStrategy
)