## [Unreleased]
+### Changed
+
+- Optimize worker choice strategies implementation.
+
## [2.6.40] - 2023-09-01
### Fixed
}
const workerNodeKey = promiseResponse.workerNodeKey
this.afterTaskExecutionHook(workerNodeKey, message)
+ this.workerChoiceStrategyContext.update(workerNodeKey)
this.promiseResponseMap.delete(taskId as string)
if (
this.opts.enableTasksQueue === true &&
this.dequeueTask(workerNodeKey) as Task<Data>
)
}
- this.workerChoiceStrategyContext.update(workerNodeKey)
}
}
}
/**
- * Gets the worker task runtime.
+ * Gets the worker node task runtime.
* If the task statistics require the average runtime, the average runtime is returned.
* If the task statistics require the median runtime , the median runtime is returned.
*
* @param workerNodeKey - The worker node key.
- * @returns The worker task runtime.
+ * @returns The worker node task runtime.
*/
- protected getWorkerTaskRunTime (workerNodeKey: number): number {
+ protected getWorkerNodeTaskRunTime (workerNodeKey: number): number {
return this.taskStatisticsRequirements.runTime.median
- ? this.pool.workerNodes[workerNodeKey].usage.runTime?.median ?? 0
- : this.pool.workerNodes[workerNodeKey].usage.runTime?.average ?? 0
+ ? this.pool.workerNodes[workerNodeKey]?.usage?.runTime?.median ?? 0
+ : this.pool.workerNodes[workerNodeKey]?.usage?.runTime?.average ?? 0
}
/**
- * Gets the worker task wait time.
+ * Gets the worker node task wait time.
* If the task statistics require the average wait time, the average wait time is returned.
* If the task statistics require the median wait time, the median wait time is returned.
*
* @param workerNodeKey - The worker node key.
- * @returns The worker task wait time.
+ * @returns The worker node task wait time.
*/
- protected getWorkerTaskWaitTime (workerNodeKey: number): number {
+ protected getWorkerNodeTaskWaitTime (workerNodeKey: number): number {
return this.taskStatisticsRequirements.waitTime.median
- ? this.pool.workerNodes[workerNodeKey].usage.waitTime?.median ?? 0
- : this.pool.workerNodes[workerNodeKey].usage.waitTime?.average ?? 0
+ ? this.pool.workerNodes[workerNodeKey]?.usage?.waitTime?.median ?? 0
+ : this.pool.workerNodes[workerNodeKey]?.usage?.waitTime?.average ?? 0
}
/**
- * Gets the worker task ELU.
+ * Gets the worker node task ELU.
* If the task statistics require the average ELU, the average ELU is returned.
* If the task statistics require the median ELU, the median ELU is returned.
*
* @param workerNodeKey - The worker node key.
- * @returns The worker task ELU.
+ * @returns The worker node task ELU.
*/
- protected getWorkerTaskElu (workerNodeKey: number): number {
+ protected getWorkerNodeTaskElu (workerNodeKey: number): number {
return this.taskStatisticsRequirements.elu.median
- ? this.pool.workerNodes[workerNodeKey].usage.elu.active?.median ?? 0
- : this.pool.workerNodes[workerNodeKey].usage.elu.active?.average ?? 0
+ ? this.pool.workerNodes[workerNodeKey]?.usage?.elu?.active?.median ?? 0
+ : this.pool.workerNodes[workerNodeKey]?.usage?.elu?.active?.average ?? 0
}
/**
DEFAULT_WORKER_CHOICE_STRATEGY_OPTIONS
} from '../../utils'
import type { IPool } from '../pool'
-import type { IWorker } from '../worker'
+import type { IWorker, StrategyData } from '../worker'
import { AbstractWorkerChoiceStrategy } from './abstract-worker-choice-strategy'
import {
type IWorkerChoiceStrategy,
}
}
- /**
- * Workers' virtual task end execution timestamp.
- */
- private workersVirtualTaskEndTimestamp: number[] = []
-
/** @inheritDoc */
public constructor (
pool: IPool<Worker, Data, Response>,
/** @inheritDoc */
public reset (): boolean {
- this.workersVirtualTaskEndTimestamp = []
+ for (const workerNode of this.pool.workerNodes) {
+ delete workerNode.strategyData?.virtualTaskEndTimestamp
+ }
return true
}
/** @inheritDoc */
public update (workerNodeKey: number): boolean {
- this.computeWorkerVirtualTaskEndTimestamp(workerNodeKey)
+ this.pool.workerNodes[workerNodeKey].strategyData = {
+ virtualTaskEndTimestamp:
+ this.computeWorkerNodeVirtualTaskEndTimestamp(workerNodeKey)
+ }
return true
}
}
/** @inheritDoc */
- public remove (workerNodeKey: number): boolean {
- this.workersVirtualTaskEndTimestamp.splice(workerNodeKey, 1)
+ public remove (): boolean {
return true
}
private fairShareNextWorkerNodeKey (): number | undefined {
- let chosenWorkerNodeKey: number | undefined
- let minWorkerVirtualTaskEndTimestamp = Infinity
- for (const [workerNodeKey] of this.pool.workerNodes.entries()) {
- if (this.workersVirtualTaskEndTimestamp[workerNodeKey] == null) {
- this.computeWorkerVirtualTaskEndTimestamp(workerNodeKey)
- }
- const workerVirtualTaskEndTimestamp =
- this.workersVirtualTaskEndTimestamp[workerNodeKey]
- if (workerVirtualTaskEndTimestamp < minWorkerVirtualTaskEndTimestamp) {
- minWorkerVirtualTaskEndTimestamp = workerVirtualTaskEndTimestamp
- chosenWorkerNodeKey = workerNodeKey
- }
- }
- return chosenWorkerNodeKey
+ return this.pool.workerNodes.reduce(
+ (minWorkerNodeKey, workerNode, workerNodeKey, workerNodes) => {
+ if (workerNode.strategyData?.virtualTaskEndTimestamp == null) {
+ workerNode.strategyData = {
+ virtualTaskEndTimestamp:
+ this.computeWorkerNodeVirtualTaskEndTimestamp(workerNodeKey)
+ }
+ }
+ return (workerNode.strategyData.virtualTaskEndTimestamp as number) <
+ ((workerNodes[minWorkerNodeKey].strategyData as StrategyData)
+ .virtualTaskEndTimestamp as number)
+ ? workerNodeKey
+ : minWorkerNodeKey
+ },
+ 0
+ )
}
/**
* Computes the worker node key virtual task end timestamp.
*
* @param workerNodeKey - The worker node key.
+ * @returns The worker node key virtual task end timestamp.
*/
- private computeWorkerVirtualTaskEndTimestamp (workerNodeKey: number): void {
- this.workersVirtualTaskEndTimestamp[workerNodeKey] =
- this.getWorkerVirtualTaskEndTimestamp(
- workerNodeKey,
- this.getWorkerVirtualTaskStartTimestamp(workerNodeKey)
- )
+ private computeWorkerNodeVirtualTaskEndTimestamp (
+ workerNodeKey: number
+ ): number {
+ return this.getWorkerNodeVirtualTaskEndTimestamp(
+ workerNodeKey,
+ this.getWorkerNodeVirtualTaskStartTimestamp(workerNodeKey)
+ )
}
- private getWorkerVirtualTaskEndTimestamp (
+ private getWorkerNodeVirtualTaskEndTimestamp (
workerNodeKey: number,
- workerVirtualTaskStartTimestamp: number
+ workerNodeVirtualTaskStartTimestamp: number
): number {
- const workerTaskRunTime =
+ const workerNodeTaskRunTime =
this.opts.measurement === Measurements.elu
- ? this.getWorkerTaskElu(workerNodeKey)
- : this.getWorkerTaskRunTime(workerNodeKey)
- return workerVirtualTaskStartTimestamp + workerTaskRunTime
+ ? this.getWorkerNodeTaskElu(workerNodeKey)
+ : this.getWorkerNodeTaskRunTime(workerNodeKey)
+ return workerNodeVirtualTaskStartTimestamp + workerNodeTaskRunTime
}
- private getWorkerVirtualTaskStartTimestamp (workerNodeKey: number): number {
- return Math.max(
- performance.now(),
- this.workersVirtualTaskEndTimestamp[workerNodeKey] ?? -Infinity
- )
+ private getWorkerNodeVirtualTaskStartTimestamp (
+ workerNodeKey: number
+ ): number {
+ const now = performance.now()
+ return now <
+ (this.pool.workerNodes[workerNodeKey]?.strategyData
+ ?.virtualTaskEndTimestamp ?? -Infinity)
+ ? (this.pool.workerNodes[workerNodeKey]?.strategyData
+ ?.virtualTaskEndTimestamp as number)
+ : now
}
}
*/
private workerNodeId: number = 0
/**
- * Worker virtual task runtime.
+ * Worker node virtual task runtime.
*/
- private workerVirtualTaskRunTime: number = 0
+ private workerNodeVirtualTaskRunTime: number = 0
/** @inheritDoc */
public constructor (
this.resetWorkerNodeKeyProperties()
this.roundId = 0
this.workerNodeId = 0
- this.workerVirtualTaskRunTime = 0
+ this.workerNodeVirtualTaskRunTime = 0
return true
}
this.workerNodeId = workerNodeKey
if (
this.workerNodeId !== this.nextWorkerNodeKey &&
- this.workerVirtualTaskRunTime !== 0
+ this.workerNodeVirtualTaskRunTime !== 0
) {
- this.workerVirtualTaskRunTime = 0
+ this.workerNodeVirtualTaskRunTime = 0
}
const workerWeight =
this.opts.weights?.[workerNodeKey] ?? this.defaultWorkerWeight
if (
workerWeight >= this.roundWeights[roundIndex] &&
- this.workerVirtualTaskRunTime < workerWeight
+ this.workerNodeVirtualTaskRunTime < workerWeight
) {
- this.workerVirtualTaskRunTime =
- this.workerVirtualTaskRunTime +
- this.getWorkerTaskRunTime(workerNodeKey)
+ this.workerNodeVirtualTaskRunTime =
+ this.workerNodeVirtualTaskRunTime +
+ this.getWorkerNodeTaskRunTime(workerNodeKey)
this.setPreviousWorkerNodeKey(this.nextWorkerNodeKey)
this.nextWorkerNodeKey = workerNodeKey
return this.nextWorkerNodeKey
}
private leastBusyNextWorkerNodeKey (): number | undefined {
- let chosenWorkerNodeKey: number | undefined
- let minTime = Infinity
- for (const [workerNodeKey, workerNode] of this.pool.workerNodes.entries()) {
- const workerTime =
- (workerNode.usage.runTime?.aggregate ?? 0) +
- (workerNode.usage.waitTime?.aggregate ?? 0)
- if (workerTime === 0) {
- chosenWorkerNodeKey = workerNodeKey
- break
- } else if (workerTime < minTime) {
- minTime = workerTime
- chosenWorkerNodeKey = workerNodeKey
- }
- }
- return chosenWorkerNodeKey
+ return this.pool.workerNodes.reduce(
+ (minWorkerNodeKey, workerNode, workerNodeKey, workerNodes) => {
+ return (workerNode.usage.runTime?.aggregate ?? 0) +
+ (workerNode.usage.waitTime?.aggregate ?? 0) <
+ (workerNodes[minWorkerNodeKey].usage.runTime?.aggregate ?? 0) +
+ (workerNodes[minWorkerNodeKey].usage.waitTime?.aggregate ?? 0)
+ ? workerNodeKey
+ : minWorkerNodeKey
+ },
+ 0
+ )
}
}
}
private leastEluNextWorkerNodeKey (): number | undefined {
- let chosenWorkerNodeKey: number | undefined
- let minWorkerElu = Infinity
- for (const [workerNodeKey, workerNode] of this.pool.workerNodes.entries()) {
- const workerUsage = workerNode.usage
- const workerElu = workerUsage.elu?.active?.aggregate ?? 0
- if (workerElu === 0) {
- chosenWorkerNodeKey = workerNodeKey
- break
- } else if (workerElu < minWorkerElu) {
- minWorkerElu = workerElu
- chosenWorkerNodeKey = workerNodeKey
- }
- }
- return chosenWorkerNodeKey
+ return this.pool.workerNodes.reduce(
+ (minWorkerNodeKey, workerNode, workerNodeKey, workerNodes) => {
+ return (workerNode.usage.elu?.active?.aggregate ?? 0) <
+ (workerNodes[minWorkerNodeKey].usage.elu?.active?.aggregate ?? 0)
+ ? workerNodeKey
+ : minWorkerNodeKey
+ },
+ 0
+ )
}
}
}
private leastUsedNextWorkerNodeKey (): number | undefined {
- let chosenWorkerNodeKey: number | undefined
- let minNumberOfTasks = Infinity
- for (const [workerNodeKey, workerNode] of this.pool.workerNodes.entries()) {
- const workerTaskStatistics = workerNode.usage.tasks
- const workerTasks =
- workerTaskStatistics.executed +
- workerTaskStatistics.executing +
- workerTaskStatistics.queued
- if (workerTasks === 0) {
- chosenWorkerNodeKey = workerNodeKey
- break
- } else if (workerTasks < minNumberOfTasks) {
- minNumberOfTasks = workerTasks
- chosenWorkerNodeKey = workerNodeKey
- }
- }
- return chosenWorkerNodeKey
+ return this.pool.workerNodes.reduce(
+ (minWorkerNodeKey, workerNode, workerNodeKey, workerNodes) => {
+ return workerNode.usage.tasks.executed +
+ workerNode.usage.tasks.executing +
+ workerNode.usage.tasks.queued <
+ workerNodes[minWorkerNodeKey].usage.tasks.executed +
+ workerNodes[minWorkerNodeKey].usage.tasks.executing +
+ workerNodes[minWorkerNodeKey].usage.tasks.queued
+ ? workerNodeKey
+ : minWorkerNodeKey
+ },
+ 0
+ )
}
}
*/
private readonly defaultWorkerWeight: number
/**
- * Worker virtual task runtime.
+ * Worker node virtual task runtime.
*/
- private workerVirtualTaskRunTime: number = 0
+ private workerNodeVirtualTaskRunTime: number = 0
/** @inheritDoc */
public constructor (
/** @inheritDoc */
public reset (): boolean {
this.resetWorkerNodeKeyProperties()
- this.workerVirtualTaskRunTime = 0
+ this.workerNodeVirtualTaskRunTime = 0
return true
}
this.reset()
}
if (this.nextWorkerNodeKey === workerNodeKey) {
- this.workerVirtualTaskRunTime = 0
+ this.workerNodeVirtualTaskRunTime = 0
if (this.nextWorkerNodeKey > this.pool.workerNodes.length - 1) {
this.nextWorkerNodeKey = this.pool.workerNodes.length - 1
}
this.opts.weights?.[
this.nextWorkerNodeKey ?? this.previousWorkerNodeKey
] ?? this.defaultWorkerWeight
- if (this.workerVirtualTaskRunTime < workerWeight) {
- this.workerVirtualTaskRunTime =
- this.workerVirtualTaskRunTime +
- this.getWorkerTaskRunTime(
+ if (this.workerNodeVirtualTaskRunTime < workerWeight) {
+ this.workerNodeVirtualTaskRunTime =
+ this.workerNodeVirtualTaskRunTime +
+ this.getWorkerNodeTaskRunTime(
this.nextWorkerNodeKey ?? this.previousWorkerNodeKey
)
} else {
this.nextWorkerNodeKey === this.pool.workerNodes.length - 1
? 0
: (this.nextWorkerNodeKey ?? this.previousWorkerNodeKey) + 1
- this.workerVirtualTaskRunTime = 0
+ this.workerNodeVirtualTaskRunTime = 0
}
return this.nextWorkerNodeKey
}
import {
type IWorker,
type IWorkerNode,
+ type StrategyData,
type WorkerInfo,
type WorkerNodeEventCallback,
type WorkerType,
/** @inheritdoc */
public usage: WorkerUsage
/** @inheritdoc */
+ public strategyData?: StrategyData
+ /** @inheritdoc */
public messageChannel?: MessageChannel
/** @inheritdoc */
public tasksQueueBackPressureSize: number
readonly elu: EventLoopUtilizationMeasurementStatistics
}
+/**
+ * Worker strategy data.
+ */
+export interface StrategyData {
+ virtualTaskEndTimestamp?: number
+}
+
/**
* Worker interface.
*/
* Worker usage statistics.
*/
readonly usage: WorkerUsage
+ /**
+ * Worker strategy data.
+ * This is used to store data that is specific to the worker choice strategy.
+ */
+ strategyData?: StrategyData
/**
* Message channel (worker_threads only).
*/
workerChoiceStrategy
).previousWorkerNodeKey
).toBe(0)
- if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) {
- expect(
- pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
- workerChoiceStrategy
- ).workersVirtualTaskEndTimestamp
- ).toStrictEqual([])
- } else if (
+ if (
workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
) {
expect(
expect(
pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
workerChoiceStrategy
- ).workerVirtualTaskRunTime
+ ).workerNodeVirtualTaskRunTime
).toBe(0)
} else if (
workerChoiceStrategy ===
expect(
pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
workerChoiceStrategy
- ).workerVirtualTaskRunTime
+ ).workerNodeVirtualTaskRunTime
).toBe(0)
expect(
pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
pool.workerChoiceStrategyContext.workerChoiceStrategy
).previousWorkerNodeKey
).toEqual(expect.any(Number))
- expect(
- pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
- pool.workerChoiceStrategyContext.workerChoiceStrategy
- ).workersVirtualTaskEndTimestamp.length
- ).toBe(pool.workerNodes.length)
// We need to clean up the resources after our test
await pool.destroy()
})
pool.workerChoiceStrategyContext.workerChoiceStrategy
).previousWorkerNodeKey
).toEqual(expect.any(Number))
- expect(
- pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
- pool.workerChoiceStrategyContext.workerChoiceStrategy
- ).workersVirtualTaskEndTimestamp.length
- ).toBe(pool.workerNodes.length)
// We need to clean up the resources after our test
await pool.destroy()
})
pool.workerChoiceStrategyContext.workerChoiceStrategy
).previousWorkerNodeKey
).toEqual(expect.any(Number))
- expect(
- pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
- pool.workerChoiceStrategyContext.workerChoiceStrategy
- ).workersVirtualTaskEndTimestamp.length
- ).toBe(pool.workerNodes.length)
// We need to clean up the resources after our test
await pool.destroy()
})
max,
'./tests/worker-files/thread/testWorker.js'
)
- expect(
- pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
- workerChoiceStrategy
- ).workersVirtualTaskEndTimestamp
- ).toBeInstanceOf(Array)
- expect(
- pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
- workerChoiceStrategy
- ).workersVirtualTaskEndTimestamp.length
- ).toBe(0)
- pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
- workerChoiceStrategy
- ).workersVirtualTaskEndTimestamp[0] = performance.now()
- expect(
- pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
- workerChoiceStrategy
- ).workersVirtualTaskEndTimestamp.length
- ).toBe(1)
+ for (const workerNode of pool.workerNodes) {
+ workerNode.strategyData = {
+ virtualTaskEndTimestamp: performance.now()
+ }
+ }
pool.setWorkerChoiceStrategy(workerChoiceStrategy)
- expect(
- pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
- pool.workerChoiceStrategyContext.workerChoiceStrategy
- ).workersVirtualTaskEndTimestamp
- ).toBeInstanceOf(Array)
- expect(
- pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
- pool.workerChoiceStrategyContext.workerChoiceStrategy
- ).workersVirtualTaskEndTimestamp.length
- ).toBe(0)
+ for (const workerNode of pool.workerNodes) {
+ expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeUndefined()
+ }
await pool.destroy()
pool = new DynamicThreadPool(
min,
max,
'./tests/worker-files/thread/testWorker.js'
)
- expect(
- pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
- workerChoiceStrategy
- ).workersVirtualTaskEndTimestamp
- ).toBeInstanceOf(Array)
- expect(
- pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
- workerChoiceStrategy
- ).workersVirtualTaskEndTimestamp.length
- ).toBe(0)
- pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
- workerChoiceStrategy
- ).workersVirtualTaskEndTimestamp[0] = performance.now()
- expect(
- pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
- workerChoiceStrategy
- ).workersVirtualTaskEndTimestamp.length
- ).toBe(1)
+ for (const workerNode of pool.workerNodes) {
+ workerNode.strategyData = {
+ virtualTaskEndTimestamp: performance.now()
+ }
+ }
pool.setWorkerChoiceStrategy(workerChoiceStrategy)
- expect(
- pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
- pool.workerChoiceStrategyContext.workerChoiceStrategy
- ).workersVirtualTaskEndTimestamp
- ).toBeInstanceOf(Array)
- expect(
- pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
- pool.workerChoiceStrategyContext.workerChoiceStrategy
- ).workersVirtualTaskEndTimestamp.length
- ).toBe(0)
+ for (const workerNode of pool.workerNodes) {
+ expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeUndefined()
+ }
// We need to clean up the resources after our test
await pool.destroy()
})
expect(
pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
pool.workerChoiceStrategyContext.workerChoiceStrategy
- ).workerVirtualTaskRunTime
+ ).workerNodeVirtualTaskRunTime
).toBeGreaterThanOrEqual(0)
// We need to clean up the resources after our test
await pool.destroy()
expect(
pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
pool.workerChoiceStrategyContext.workerChoiceStrategy
- ).workerVirtualTaskRunTime
+ ).workerNodeVirtualTaskRunTime
).toBeGreaterThanOrEqual(0)
// We need to clean up the resources after our test
await pool.destroy()
expect(
pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
pool.workerChoiceStrategyContext.workerChoiceStrategy
- ).workerVirtualTaskRunTime
+ ).workerNodeVirtualTaskRunTime
).toBeGreaterThanOrEqual(0)
// We need to clean up the resources after our test
await pool.destroy()
expect(
pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
workerChoiceStrategy
- ).workerVirtualTaskRunTime
+ ).workerNodeVirtualTaskRunTime
).toBeDefined()
pool.setWorkerChoiceStrategy(workerChoiceStrategy)
expect(
expect(
pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
pool.workerChoiceStrategyContext.workerChoiceStrategy
- ).workerVirtualTaskRunTime
+ ).workerNodeVirtualTaskRunTime
).toBe(0)
await pool.destroy()
pool = new DynamicThreadPool(
expect(
pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
workerChoiceStrategy
- ).workerVirtualTaskRunTime
+ ).workerNodeVirtualTaskRunTime
).toBeDefined()
pool.setWorkerChoiceStrategy(workerChoiceStrategy)
expect(
expect(
pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
pool.workerChoiceStrategyContext.workerChoiceStrategy
- ).workerVirtualTaskRunTime
+ ).workerNodeVirtualTaskRunTime
).toBe(0)
// We need to clean up the resources after our test
await pool.destroy()
expect(strategy.reset()).toBe(true)
expect(strategy.nextWorkerNodeKey).toBe(0)
expect(strategy.previousWorkerNodeKey).toBe(0)
- expect(strategy.workerVirtualTaskRunTime).toBe(0)
+ expect(strategy.workerNodeVirtualTaskRunTime).toBe(0)
})
})
{
"$schema": "https://typedoc.org/schema.json",
- "tsconfig": "tsconfig.production.json",
+ "tsconfig": "./tsconfig.production.json",
"entryPoints": ["./src"],
"out": "./docs",
"readme": "none",