From 39618ede0e08d380c1ac82005bcc2ab1f3c227b6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Sun, 31 Dec 2023 14:35:46 +0100 Subject: [PATCH] refactor: remove unneeded worker choice strategy storage in intermediate object MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- src/index.ts | 1 - src/pools/abstract-pool.ts | 1 - .../abstract-worker-choice-strategy.ts | 26 +++---- .../fair-share-worker-choice-strategy.ts | 9 +-- ...hted-round-robin-worker-choice-strategy.ts | 12 ++-- .../least-busy-worker-choice-strategy.ts | 6 +- .../least-elu-worker-choice-strategy.ts | 6 +- .../least-used-worker-choice-strategy.ts | 4 +- .../round-robin-worker-choice-strategy.ts | 4 +- .../selection-strategies-types.ts | 17 +---- ...hted-round-robin-worker-choice-strategy.ts | 8 +-- .../worker-choice-strategy-context.ts | 50 ++++++------- src/utils.ts | 60 ++++++++-------- tests/pools/abstract-pool.test.mjs | 72 ------------------- .../selection-strategies.test.mjs | 26 ------- .../worker-choice-strategy-context.test.mjs | 25 ++++--- tests/utils.test.mjs | 38 +++++++--- 17 files changed, 135 insertions(+), 230 deletions(-) diff --git a/src/index.ts b/src/index.ts index 0a9ab8f1..a18223e8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -35,7 +35,6 @@ export { } from './pools/selection-strategies/selection-strategies-types.js' export type { IWorkerChoiceStrategy, - InternalWorkerChoiceStrategyOptions, Measurement, MeasurementOptions, MeasurementStatisticsRequirements, diff --git a/src/pools/abstract-pool.ts b/src/pools/abstract-pool.ts index 31e73db1..b6f3a5d0 100644 --- a/src/pools/abstract-pool.ts +++ b/src/pools/abstract-pool.ts @@ -544,7 +544,6 @@ export abstract class AbstractPool< this.opts.workerChoiceStrategyOptions = workerChoiceStrategyOptions } this.workerChoiceStrategyContext.setOptions( - this, this.opts.workerChoiceStrategyOptions ) } diff --git a/src/pools/selection-strategies/abstract-worker-choice-strategy.ts b/src/pools/selection-strategies/abstract-worker-choice-strategy.ts index daed6b70..234eada7 100644 --- a/src/pools/selection-strategies/abstract-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/abstract-worker-choice-strategy.ts @@ -1,15 +1,15 @@ import { DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS, - buildInternalWorkerChoiceStrategyOptions + buildWorkerChoiceStrategyOptions } from '../../utils.js' import type { IPool } from '../pool.js' import type { IWorker } from '../worker.js' import type { IWorkerChoiceStrategy, - InternalWorkerChoiceStrategyOptions, MeasurementStatisticsRequirements, StrategyPolicy, - TaskStatisticsRequirements + TaskStatisticsRequirements, + WorkerChoiceStrategyOptions } from './selection-strategies-types.js' /** @@ -55,10 +55,10 @@ export abstract class AbstractWorkerChoiceStrategy< */ public constructor ( protected readonly pool: IPool, - protected opts: InternalWorkerChoiceStrategyOptions + protected opts?: WorkerChoiceStrategyOptions ) { - this.opts = buildInternalWorkerChoiceStrategyOptions( - this.pool.info.maxSize, + this.opts = buildWorkerChoiceStrategyOptions( + this.pool, this.opts ) this.setTaskStatisticsRequirements(this.opts) @@ -66,22 +66,22 @@ export abstract class AbstractWorkerChoiceStrategy< } protected setTaskStatisticsRequirements ( - opts: InternalWorkerChoiceStrategyOptions + opts: WorkerChoiceStrategyOptions | undefined ): void { this.toggleMedianMeasurementStatisticsRequirements( this.taskStatisticsRequirements.runTime, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - opts.runTime!.median + opts!.runTime!.median ) this.toggleMedianMeasurementStatisticsRequirements( this.taskStatisticsRequirements.waitTime, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - opts.waitTime!.median + opts!.waitTime!.median ) this.toggleMedianMeasurementStatisticsRequirements( this.taskStatisticsRequirements.elu, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - opts.elu!.median + opts!.elu!.median ) } @@ -117,9 +117,9 @@ export abstract class AbstractWorkerChoiceStrategy< public abstract remove (workerNodeKey: number): boolean /** @inheritDoc */ - public setOptions (opts: InternalWorkerChoiceStrategyOptions): void { - this.opts = buildInternalWorkerChoiceStrategyOptions( - this.pool.info.maxSize, + public setOptions (opts: WorkerChoiceStrategyOptions | undefined): void { + this.opts = buildWorkerChoiceStrategyOptions( + this.pool, opts ) this.setTaskStatisticsRequirements(this.opts) diff --git a/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts b/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts index e8f9cc61..58982f19 100644 --- a/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/fair-share-worker-choice-strategy.ts @@ -4,9 +4,9 @@ import type { IWorker } from '../worker.js' import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy.js' import { type IWorkerChoiceStrategy, - type InternalWorkerChoiceStrategyOptions, Measurements, - type TaskStatisticsRequirements + type TaskStatisticsRequirements, + type WorkerChoiceStrategyOptions } from './selection-strategies-types.js' /** @@ -42,7 +42,7 @@ export class FairShareWorkerChoiceStrategy< /** @inheritDoc */ public constructor ( pool: IPool, - opts: InternalWorkerChoiceStrategyOptions + opts?: WorkerChoiceStrategyOptions ) { super(pool, opts) this.setTaskStatisticsRequirements(this.opts) @@ -118,7 +118,8 @@ export class FairShareWorkerChoiceStrategy< workerNodeVirtualTaskStartTimestamp: number ): number { const workerNodeTaskRunTime = - this.opts.measurement === Measurements.elu + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.opts!.measurement === Measurements.elu ? this.getWorkerNodeTaskElu(workerNodeKey) : this.getWorkerNodeTaskRunTime(workerNodeKey) return workerNodeVirtualTaskStartTimestamp + workerNodeTaskRunTime diff --git a/src/pools/selection-strategies/interleaved-weighted-round-robin-worker-choice-strategy.ts b/src/pools/selection-strategies/interleaved-weighted-round-robin-worker-choice-strategy.ts index fe4b4883..3942bb6e 100644 --- a/src/pools/selection-strategies/interleaved-weighted-round-robin-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/interleaved-weighted-round-robin-worker-choice-strategy.ts @@ -4,8 +4,8 @@ import { DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS } from '../../utils.js' import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy.js' import type { IWorkerChoiceStrategy, - InternalWorkerChoiceStrategyOptions, - TaskStatisticsRequirements + TaskStatisticsRequirements, + WorkerChoiceStrategyOptions } from './selection-strategies-types.js' /** @@ -53,7 +53,7 @@ export class InterleavedWeightedRoundRobinWorkerChoiceStrategy< /** @inheritDoc */ public constructor ( pool: IPool, - opts: InternalWorkerChoiceStrategyOptions + opts?: WorkerChoiceStrategyOptions ) { super(pool, opts) this.setTaskStatisticsRequirements(this.opts) @@ -95,7 +95,7 @@ export class InterleavedWeightedRoundRobinWorkerChoiceStrategy< this.workerNodeVirtualTaskRunTime = 0 } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const workerWeight = this.opts.weights![workerNodeKey]! + const workerWeight = this.opts!.weights![workerNodeKey]! if ( this.isWorkerNodeReady(workerNodeKey) && workerWeight >= this.roundWeights[roundIndex] && @@ -149,7 +149,7 @@ export class InterleavedWeightedRoundRobinWorkerChoiceStrategy< } /** @inheritDoc */ - public setOptions (opts: InternalWorkerChoiceStrategyOptions): void { + public setOptions (opts: WorkerChoiceStrategyOptions | undefined): void { super.setOptions(opts) this.roundWeights = this.getRoundWeights() } @@ -158,7 +158,7 @@ export class InterleavedWeightedRoundRobinWorkerChoiceStrategy< return [ ...new Set( // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - Object.values(this.opts.weights!) + Object.values(this.opts!.weights!) .slice() .sort((a, b) => a - b) ) diff --git a/src/pools/selection-strategies/least-busy-worker-choice-strategy.ts b/src/pools/selection-strategies/least-busy-worker-choice-strategy.ts index d800c383..0f2e1239 100644 --- a/src/pools/selection-strategies/least-busy-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/least-busy-worker-choice-strategy.ts @@ -4,8 +4,8 @@ import type { IWorker } from '../worker.js' import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy.js' import type { IWorkerChoiceStrategy, - InternalWorkerChoiceStrategyOptions, - TaskStatisticsRequirements + TaskStatisticsRequirements, + WorkerChoiceStrategyOptions } from './selection-strategies-types.js' /** @@ -40,7 +40,7 @@ export class LeastBusyWorkerChoiceStrategy< /** @inheritDoc */ public constructor ( pool: IPool, - opts: InternalWorkerChoiceStrategyOptions + opts?: WorkerChoiceStrategyOptions ) { super(pool, opts) this.setTaskStatisticsRequirements(this.opts) diff --git a/src/pools/selection-strategies/least-elu-worker-choice-strategy.ts b/src/pools/selection-strategies/least-elu-worker-choice-strategy.ts index 81d108a3..588c75d9 100644 --- a/src/pools/selection-strategies/least-elu-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/least-elu-worker-choice-strategy.ts @@ -4,8 +4,8 @@ import type { IWorker } from '../worker.js' import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy.js' import type { IWorkerChoiceStrategy, - InternalWorkerChoiceStrategyOptions, - TaskStatisticsRequirements + TaskStatisticsRequirements, + WorkerChoiceStrategyOptions } from './selection-strategies-types.js' /** @@ -36,7 +36,7 @@ export class LeastEluWorkerChoiceStrategy< /** @inheritDoc */ public constructor ( pool: IPool, - opts: InternalWorkerChoiceStrategyOptions + opts?: WorkerChoiceStrategyOptions ) { super(pool, opts) this.setTaskStatisticsRequirements(this.opts) diff --git a/src/pools/selection-strategies/least-used-worker-choice-strategy.ts b/src/pools/selection-strategies/least-used-worker-choice-strategy.ts index c1a4a6ac..5e8a09b4 100644 --- a/src/pools/selection-strategies/least-used-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/least-used-worker-choice-strategy.ts @@ -3,7 +3,7 @@ import type { IWorker } from '../worker.js' import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy.js' import type { IWorkerChoiceStrategy, - InternalWorkerChoiceStrategyOptions + WorkerChoiceStrategyOptions } from './selection-strategies-types.js' /** @@ -23,7 +23,7 @@ export class LeastUsedWorkerChoiceStrategy< /** @inheritDoc */ public constructor ( pool: IPool, - opts: InternalWorkerChoiceStrategyOptions + opts?: WorkerChoiceStrategyOptions ) { super(pool, opts) } diff --git a/src/pools/selection-strategies/round-robin-worker-choice-strategy.ts b/src/pools/selection-strategies/round-robin-worker-choice-strategy.ts index 34c4f596..41326a78 100644 --- a/src/pools/selection-strategies/round-robin-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/round-robin-worker-choice-strategy.ts @@ -3,7 +3,7 @@ import type { IWorker } from '../worker.js' import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy.js' import type { IWorkerChoiceStrategy, - InternalWorkerChoiceStrategyOptions + WorkerChoiceStrategyOptions } from './selection-strategies-types.js' /** @@ -23,7 +23,7 @@ export class RoundRobinWorkerChoiceStrategy< /** @inheritDoc */ public constructor ( pool: IPool, - opts: InternalWorkerChoiceStrategyOptions + opts?: WorkerChoiceStrategyOptions ) { super(pool, opts) } diff --git a/src/pools/selection-strategies/selection-strategies-types.ts b/src/pools/selection-strategies/selection-strategies-types.ts index 1467ab4f..d30f9eeb 100644 --- a/src/pools/selection-strategies/selection-strategies-types.ts +++ b/src/pools/selection-strategies/selection-strategies-types.ts @@ -98,21 +98,6 @@ export interface WorkerChoiceStrategyOptions { weights?: Record } -/** - * Worker choice strategy internal options. - * - * @internal - */ -export interface InternalWorkerChoiceStrategyOptions - extends WorkerChoiceStrategyOptions { - /** - * Number of worker choice retries to perform if no worker is eligible. - * - * @defaultValue pool maximum size - */ - readonly retries?: number -} - /** * Measurement statistics requirements. * @@ -216,7 +201,7 @@ export interface IWorkerChoiceStrategy { * * @param opts - The worker choice strategy options. */ - readonly setOptions: (opts: WorkerChoiceStrategyOptions) => void + readonly setOptions: (opts: WorkerChoiceStrategyOptions | undefined) => void /** * Whether the pool has worker nodes ready or not. * diff --git a/src/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.ts b/src/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.ts index 5ccc9c32..6bbbbaf6 100644 --- a/src/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.ts +++ b/src/pools/selection-strategies/weighted-round-robin-worker-choice-strategy.ts @@ -4,8 +4,8 @@ import { DEFAULT_MEASUREMENT_STATISTICS_REQUIREMENTS } from '../../utils.js' import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy.js' import type { IWorkerChoiceStrategy, - InternalWorkerChoiceStrategyOptions, - TaskStatisticsRequirements + TaskStatisticsRequirements, + WorkerChoiceStrategyOptions } from './selection-strategies-types.js' /** @@ -42,7 +42,7 @@ export class WeightedRoundRobinWorkerChoiceStrategy< /** @inheritDoc */ public constructor ( pool: IPool, - opts: InternalWorkerChoiceStrategyOptions + opts?: WorkerChoiceStrategyOptions ) { super(pool, opts) this.setTaskStatisticsRequirements(this.opts) @@ -91,7 +91,7 @@ export class WeightedRoundRobinWorkerChoiceStrategy< private weightedRoundRobinNextWorkerNodeKey (): number | undefined { const workerWeight = // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.opts.weights![this.nextWorkerNodeKey ?? this.previousWorkerNodeKey]! + this.opts!.weights![this.nextWorkerNodeKey ?? this.previousWorkerNodeKey]! if (this.workerNodeVirtualTaskRunTime < workerWeight) { this.workerNodeVirtualTaskRunTime = this.workerNodeVirtualTaskRunTime + diff --git a/src/pools/selection-strategies/worker-choice-strategy-context.ts b/src/pools/selection-strategies/worker-choice-strategy-context.ts index 330e584d..d3e7f03e 100644 --- a/src/pools/selection-strategies/worker-choice-strategy-context.ts +++ b/src/pools/selection-strategies/worker-choice-strategy-context.ts @@ -1,6 +1,6 @@ -import { buildInternalWorkerChoiceStrategyOptions } from '../../utils.js' import type { IPool } from '../pool.js' import type { IWorker } from '../worker.js' +import { getWorkerChoiceStrategyRetries } from '../../utils.js' import { FairShareWorkerChoiceStrategy } from './fair-share-worker-choice-strategy.js' import { InterleavedWeightedRoundRobinWorkerChoiceStrategy } from './interleaved-weighted-round-robin-worker-choice-strategy.js' import { LeastBusyWorkerChoiceStrategy } from './least-busy-worker-choice-strategy.js' @@ -9,10 +9,10 @@ import { LeastEluWorkerChoiceStrategy } from './least-elu-worker-choice-strategy import { RoundRobinWorkerChoiceStrategy } from './round-robin-worker-choice-strategy.js' import type { IWorkerChoiceStrategy, - InternalWorkerChoiceStrategyOptions, StrategyPolicy, TaskStatisticsRequirements, - WorkerChoiceStrategy + WorkerChoiceStrategy, + WorkerChoiceStrategyOptions } from './selection-strategies-types.js' import { WorkerChoiceStrategies } from './selection-strategies-types.js' import { WeightedRoundRobinWorkerChoiceStrategy } from './weighted-round-robin-worker-choice-strategy.js' @@ -29,11 +29,19 @@ export class WorkerChoiceStrategyContext< Data = unknown, Response = unknown > { + /** + * The worker choice strategies registered in the context. + */ private readonly workerChoiceStrategies: Map< WorkerChoiceStrategy, IWorkerChoiceStrategy > + /** + * The number of worker choice strategy execution retries. + */ + private readonly retries: number + /** * Worker choice strategy context constructor. * @@ -44,12 +52,8 @@ export class WorkerChoiceStrategyContext< public constructor ( pool: IPool, private workerChoiceStrategy: WorkerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN, - private opts?: InternalWorkerChoiceStrategyOptions + opts?: WorkerChoiceStrategyOptions ) { - this.opts = buildInternalWorkerChoiceStrategyOptions( - pool.info.maxSize, - this.opts - ) this.execute = this.execute.bind(this) this.workerChoiceStrategies = new Map< WorkerChoiceStrategy, @@ -59,35 +63,35 @@ export class WorkerChoiceStrategyContext< WorkerChoiceStrategies.ROUND_ROBIN, new (RoundRobinWorkerChoiceStrategy.bind(this))( pool, - this.opts + opts ) ], [ WorkerChoiceStrategies.LEAST_USED, new (LeastUsedWorkerChoiceStrategy.bind(this))( pool, - this.opts + opts ) ], [ WorkerChoiceStrategies.LEAST_BUSY, new (LeastBusyWorkerChoiceStrategy.bind(this))( pool, - this.opts + opts ) ], [ WorkerChoiceStrategies.LEAST_ELU, new (LeastEluWorkerChoiceStrategy.bind(this))( pool, - this.opts + opts ) ], [ WorkerChoiceStrategies.FAIR_SHARE, new (FairShareWorkerChoiceStrategy.bind(this))( pool, - this.opts + opts ) ], [ @@ -96,7 +100,7 @@ export class WorkerChoiceStrategyContext< Worker, Data, Response - >(pool, this.opts) + >(pool, opts) ], [ WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN, @@ -104,9 +108,10 @@ export class WorkerChoiceStrategyContext< Worker, Data, Response - >(pool, this.opts) + >(pool, opts) ] ]) + this.retries = getWorkerChoiceStrategyRetries(pool, opts) } /** @@ -191,8 +196,7 @@ export class WorkerChoiceStrategyContext< retriesCount++ } chooseCount++ - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - } while (workerNodeKey == null && retriesCount < this.opts!.retries!) + } while (workerNodeKey == null && retriesCount < this.retries) if (workerNodeKey == null) { throw new Error( `Worker node key chosen is null or undefined after ${retriesCount} retries` @@ -217,19 +221,11 @@ export class WorkerChoiceStrategyContext< /** * Sets the worker choice strategies in the context options. * - * @param pool - The pool instance. * @param opts - The worker choice strategy options. */ - public setOptions ( - pool: IPool, - opts?: InternalWorkerChoiceStrategyOptions - ): void { - this.opts = buildInternalWorkerChoiceStrategyOptions( - pool.info.maxSize, - opts - ) + public setOptions (opts: WorkerChoiceStrategyOptions | undefined): void { for (const workerChoiceStrategy of this.workerChoiceStrategies.values()) { - workerChoiceStrategy.setOptions(this.opts) + workerChoiceStrategy.setOptions(opts) } } } diff --git a/src/utils.ts b/src/utils.ts index c8aed442..a7cb55f9 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -4,11 +4,12 @@ import { Worker as ClusterWorker } from 'node:cluster' import { Worker as ThreadWorker } from 'node:worker_threads' import { cpus } from 'node:os' import type { - InternalWorkerChoiceStrategyOptions, - MeasurementStatisticsRequirements + MeasurementStatisticsRequirements, + WorkerChoiceStrategyOptions } from './pools/selection-strategies/selection-strategies-types.js' import type { KillBehavior } from './worker/worker-options.js' import { type IWorker, type WorkerType, WorkerTypes } from './pools/worker.js' +import type { IPool } from './pools/pool.js' /** * Default task name. @@ -22,23 +23,6 @@ export const EMPTY_FUNCTION: () => void = Object.freeze(() => { /* Intentionally empty */ }) -/** - * Gets default worker choice strategy options. - * - * @param retries - The number of worker choice retries. - * @returns The default worker choice strategy options. - */ -const getDefaultInternalWorkerChoiceStrategyOptions = ( - retries: number -): InternalWorkerChoiceStrategyOptions => { - return { - retries, - runTime: { median: false }, - waitTime: { median: false }, - elu: { median: false } - } -} - /** * Default measurement statistics requirements. */ @@ -282,22 +266,40 @@ export const once = ( } } +export const getWorkerChoiceStrategyRetries = < + Worker extends IWorker, + Data, + Response +>( + pool: IPool, + opts?: WorkerChoiceStrategyOptions + ): number => { + return ( + pool.info.maxSize + + Object.keys(opts?.weights ?? getDefaultWeights(pool.info.maxSize)).length + ) +} + const clone = (object: T): T => { return structuredClone(object) } -export const buildInternalWorkerChoiceStrategyOptions = ( - poolMaxSize: number, - opts?: InternalWorkerChoiceStrategyOptions -): InternalWorkerChoiceStrategyOptions => { +export const buildWorkerChoiceStrategyOptions = < + Worker extends IWorker, + Data, + Response +>( + pool: IPool, + opts?: WorkerChoiceStrategyOptions + ): WorkerChoiceStrategyOptions => { opts = clone(opts ?? {}) - if (opts?.weights == null) { - opts.weights = getDefaultWeights(poolMaxSize) - } + opts.weights = opts?.weights ?? getDefaultWeights(pool.info.maxSize) return { - ...getDefaultInternalWorkerChoiceStrategyOptions( - poolMaxSize + Object.keys(opts.weights).length - ), + ...{ + runTime: { median: false }, + waitTime: { median: false }, + elu: { median: false } + }, ...opts } } diff --git a/tests/pools/abstract-pool.test.mjs b/tests/pools/abstract-pool.test.mjs index a1022261..ccd24231 100644 --- a/tests/pools/abstract-pool.test.mjs +++ b/tests/pools/abstract-pool.test.mjs @@ -228,24 +228,9 @@ describe('Abstract pool test suite', () => { enableTasksQueue: false, workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }) - expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(pool.workerChoiceStrategyContext.opts.weights).length, - runTime: { median: false }, - waitTime: { median: false }, - elu: { median: false }, - weights: expect.objectContaining({ - 0: expect.any(Number), - [pool.info.maxSize - 1]: expect.any(Number) - }) - }) for (const [, workerChoiceStrategy] of pool.workerChoiceStrategyContext .workerChoiceStrategies) { expect(workerChoiceStrategy.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(workerChoiceStrategy.opts.weights).length, runTime: { median: false }, waitTime: { median: false }, elu: { median: false }, @@ -299,21 +284,9 @@ describe('Abstract pool test suite', () => { errorHandler: testHandler, exitHandler: testHandler }) - expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(pool.opts.workerChoiceStrategyOptions.weights).length, - runTime: { median: true }, - waitTime: { median: false }, - elu: { median: false }, - weights: { 0: 300, 1: 200 } - }) for (const [, workerChoiceStrategy] of pool.workerChoiceStrategyContext .workerChoiceStrategies) { expect(workerChoiceStrategy.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(pool.opts.workerChoiceStrategyOptions.weights).length, runTime: { median: true }, waitTime: { median: false }, elu: { median: false }, @@ -470,24 +443,9 @@ describe('Abstract pool test suite', () => { { workerChoiceStrategy: WorkerChoiceStrategies.FAIR_SHARE } ) expect(pool.opts.workerChoiceStrategyOptions).toBeUndefined() - expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(pool.workerChoiceStrategyContext.opts.weights).length, - runTime: { median: false }, - waitTime: { median: false }, - elu: { median: false }, - weights: expect.objectContaining({ - 0: expect.any(Number), - [pool.info.maxSize - 1]: expect.any(Number) - }) - }) for (const [, workerChoiceStrategy] of pool.workerChoiceStrategyContext .workerChoiceStrategies) { expect(workerChoiceStrategy.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(workerChoiceStrategy.opts.weights).length, runTime: { median: false }, waitTime: { median: false }, elu: { median: false }, @@ -524,24 +482,9 @@ describe('Abstract pool test suite', () => { runTime: { median: true }, elu: { median: true } }) - expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(pool.workerChoiceStrategyContext.opts.weights).length, - runTime: { median: true }, - waitTime: { median: false }, - elu: { median: true }, - weights: expect.objectContaining({ - 0: expect.any(Number), - [pool.info.maxSize - 1]: expect.any(Number) - }) - }) for (const [, workerChoiceStrategy] of pool.workerChoiceStrategyContext .workerChoiceStrategies) { expect(workerChoiceStrategy.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(workerChoiceStrategy.opts.weights).length, runTime: { median: true }, waitTime: { median: false }, elu: { median: true }, @@ -578,24 +521,9 @@ describe('Abstract pool test suite', () => { runTime: { median: false }, elu: { median: false } }) - expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(pool.workerChoiceStrategyContext.opts.weights).length, - runTime: { median: false }, - waitTime: { median: false }, - elu: { median: false }, - weights: expect.objectContaining({ - 0: expect.any(Number), - [pool.info.maxSize - 1]: expect.any(Number) - }) - }) for (const [, workerChoiceStrategy] of pool.workerChoiceStrategyContext .workerChoiceStrategies) { expect(workerChoiceStrategy.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(workerChoiceStrategy.opts.weights).length, runTime: { median: false }, waitTime: { median: false }, elu: { median: false }, diff --git a/tests/pools/selection-strategies/selection-strategies.test.mjs b/tests/pools/selection-strategies/selection-strategies.test.mjs index 39a2ccc3..8dc06262 100644 --- a/tests/pools/selection-strategies/selection-strategies.test.mjs +++ b/tests/pools/selection-strategies/selection-strategies.test.mjs @@ -66,19 +66,6 @@ describe('Selection strategies test suite', () => { expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe( workerChoiceStrategy ) - expect(pool.opts.workerChoiceStrategyOptions).toBeUndefined() - expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(pool.workerChoiceStrategyContext.opts.weights).length, - runTime: { median: false }, - waitTime: { median: false }, - elu: { median: false }, - weights: expect.objectContaining({ - 0: expect.any(Number), - [pool.info.maxSize - 1]: expect.any(Number) - }) - }) await pool.destroy() } for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) { @@ -92,19 +79,6 @@ describe('Selection strategies test suite', () => { expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe( workerChoiceStrategy ) - expect(pool.opts.workerChoiceStrategyOptions).toBeUndefined() - expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({ - retries: - pool.info.maxSize + - Object.keys(pool.workerChoiceStrategyContext.opts.weights).length, - runTime: { median: false }, - waitTime: { median: false }, - elu: { median: false }, - weights: expect.objectContaining({ - 0: expect.any(Number), - [pool.info.maxSize - 1]: expect.any(Number) - }) - }) await pool.destroy() } }) diff --git a/tests/pools/selection-strategies/worker-choice-strategy-context.test.mjs b/tests/pools/selection-strategies/worker-choice-strategy-context.test.mjs index 6615b8c4..85ec4263 100644 --- a/tests/pools/selection-strategies/worker-choice-strategy-context.test.mjs +++ b/tests/pools/selection-strategies/worker-choice-strategy-context.test.mjs @@ -41,14 +41,25 @@ describe('Worker choice strategy context test suite', () => { }) it('Verify that constructor() initializes the context with all the available worker choice strategies', () => { - const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( - fixedPool + let workerChoiceStrategyContext = new WorkerChoiceStrategyContext(fixedPool) + expect(workerChoiceStrategyContext.workerChoiceStrategies.size).toBe( + Object.keys(WorkerChoiceStrategies).length ) + workerChoiceStrategyContext = new WorkerChoiceStrategyContext(dynamicPool) expect(workerChoiceStrategyContext.workerChoiceStrategies.size).toBe( Object.keys(WorkerChoiceStrategies).length ) }) + it('Verify that constructor() initializes the context with retries attribute properly set', () => { + let workerChoiceStrategyContext = new WorkerChoiceStrategyContext(fixedPool) + expect(workerChoiceStrategyContext.retries).toBe(fixedPool.info.maxSize * 2) + workerChoiceStrategyContext = new WorkerChoiceStrategyContext(dynamicPool) + expect(workerChoiceStrategyContext.retries).toBe( + dynamicPool.info.maxSize * 2 + ) + }) + it('Verify that execute() return the worker node key chosen by the strategy with fixed pool', () => { const workerChoiceStrategyContext = new WorkerChoiceStrategyContext( fixedPool @@ -96,10 +107,7 @@ describe('Worker choice strategy context test suite', () => { ) expect(() => workerChoiceStrategyContext.execute()).toThrow( new Error( - `Worker node key chosen is null or undefined after ${ - fixedPool.info.maxSize + - Object.keys(workerChoiceStrategyContext.opts.weights).length - } retries` + `Worker node key chosen is null or undefined after ${workerChoiceStrategyContext.retries} retries` ) ) const workerChoiceStrategyNullStub = createStubInstance( @@ -115,10 +123,7 @@ describe('Worker choice strategy context test suite', () => { ) expect(() => workerChoiceStrategyContext.execute()).toThrow( new Error( - `Worker node key chosen is null or undefined after ${ - fixedPool.info.maxSize + - Object.keys(workerChoiceStrategyContext.opts.weights).length - } retries` + `Worker node key chosen is null or undefined after ${workerChoiceStrategyContext.retries} retries` ) ) }) diff --git a/tests/utils.test.mjs b/tests/utils.test.mjs index 2d1ee9e6..5e089e29 100644 --- a/tests/utils.test.mjs +++ b/tests/utils.test.mjs @@ -9,8 +9,9 @@ import { EMPTY_FUNCTION, availableParallelism, average, - buildInternalWorkerChoiceStrategyOptions, + buildWorkerChoiceStrategyOptions, exponentialDelay, + getWorkerChoiceStrategyRetries, getWorkerId, getWorkerType, isAsyncFunction, @@ -24,7 +25,12 @@ import { secureRandom, sleep } from '../lib/utils.cjs' -import { KillBehaviors, WorkerTypes } from '../lib/index.cjs' +import { + FixedClusterPool, + FixedThreadPool, + KillBehaviors, + WorkerTypes +} from '../lib/index.cjs' describe('Utils test suite', () => { it('Verify DEFAULT_TASK_NAME value', () => { @@ -231,22 +237,32 @@ describe('Utils test suite', () => { expect(max(1, 1)).toBe(1) }) - it('Verify buildInternalWorkerChoiceStrategyOptions() behavior', () => { - const poolMaxSize = 10 - const internalWorkerChoiceStrategyOptions = - buildInternalWorkerChoiceStrategyOptions(poolMaxSize) - expect(internalWorkerChoiceStrategyOptions).toStrictEqual({ - retries: - poolMaxSize + - Object.keys(internalWorkerChoiceStrategyOptions.weights).length, + it('Verify getWorkerChoiceStrategyRetries() behavior', async () => { + const numberOfThreads = 4 + const pool = new FixedThreadPool( + numberOfThreads, + './tests/worker-files/thread/testWorker.mjs' + ) + expect(getWorkerChoiceStrategyRetries(pool)).toBe(pool.info.maxSize * 2) + await pool.destroy() + }) + + it('Verify buildWorkerChoiceStrategyOptions() behavior', async () => { + const numberOfWorkers = 4 + const pool = new FixedClusterPool( + numberOfWorkers, + './tests/worker-files/cluster/testWorker.cjs' + ) + expect(buildWorkerChoiceStrategyOptions(pool)).toStrictEqual({ runTime: { median: false }, waitTime: { median: false }, elu: { median: false }, weights: expect.objectContaining({ 0: expect.any(Number), - [poolMaxSize - 1]: expect.any(Number) + [pool.info.maxSize - 1]: expect.any(Number) }) }) + await pool.destroy() }) // it('Verify once()', () => { -- 2.34.1