runTimeHistory: new CircularArray(),
avgRunTime: 0,
medRunTime: 0,
+ waitTime: 0,
+ waitTimeHistory: new CircularArray(),
+ avgWaitTime: 0,
+ medWaitTime: 0,
error: 0
})
}
/** @inheritDoc */
public async execute (data?: Data, name?: string): Promise<Response> {
- const [workerNodeKey, workerNode] = this.chooseWorkerNode()
+ const submissionTimestamp = performance.now()
+ const workerNodeKey = this.chooseWorkerNode()
const submittedTask: Task<Data> = {
name,
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
data: data ?? ({} as Data),
+ submissionTimestamp,
id: crypto.randomUUID()
}
const res = new Promise<Response>((resolve, reject) => {
this.promiseResponseMap.set(submittedTask.id as string, {
resolve,
reject,
- worker: workerNode.worker
+ worker: this.workerNodes[workerNodeKey].worker
})
})
if (
worker: Worker,
message: MessageValue<Response>
): void {
- const workerNodeKey = this.getWorkerNodeKey(worker)
- const workerTasksUsage = this.workerNodes[workerNodeKey].tasksUsage
+ const workerTasksUsage =
+ this.workerNodes[this.getWorkerNodeKey(worker)].tasksUsage
--workerTasksUsage.running
++workerTasksUsage.run
if (message.error != null) {
++workerTasksUsage.error
}
+ this.updateRunTimeTasksUsage(workerTasksUsage, message)
+ this.updateWaitTasksUsage(workerTasksUsage, message)
+ }
+
+ private updateRunTimeTasksUsage (
+ workerTasksUsage: TasksUsage,
+ message: MessageValue<Response>
+ ): void {
if (this.workerChoiceStrategyContext.getRequiredStatistics().runTime) {
workerTasksUsage.runTime += message.runTime ?? 0
if (
}
}
+ private updateWaitTasksUsage (
+ workerTasksUsage: TasksUsage,
+ message: MessageValue<Response>
+ ): void {
+ if (this.workerChoiceStrategyContext.getRequiredStatistics().waitTime) {
+ workerTasksUsage.waitTime += message.waitTime ?? 0
+ if (
+ this.workerChoiceStrategyContext.getRequiredStatistics().avgWaitTime &&
+ workerTasksUsage.run !== 0
+ ) {
+ workerTasksUsage.avgWaitTime =
+ workerTasksUsage.waitTime / workerTasksUsage.run
+ }
+ if (
+ this.workerChoiceStrategyContext.getRequiredStatistics().medWaitTime &&
+ message.waitTime != null
+ ) {
+ workerTasksUsage.waitTimeHistory.push(message.waitTime)
+ workerTasksUsage.medWaitTime = median(workerTasksUsage.waitTimeHistory)
+ }
+ }
+ }
+
/**
* Chooses a worker node for the next task.
*
- * The default uses a round robin algorithm to distribute the load.
+ * The default worker choice strategy uses a round robin algorithm to distribute the load.
*
- * @returns [worker node key, worker node].
+ * @returns The worker node key
*/
- protected chooseWorkerNode (): [number, WorkerNode<Worker, Data>] {
+ protected chooseWorkerNode (): number {
let workerNodeKey: number
if (this.type === PoolType.DYNAMIC && !this.full && this.internalBusy()) {
const workerCreated = this.createAndSetupWorker()
} else {
workerNodeKey = this.workerChoiceStrategyContext.execute()
}
- return [workerNodeKey, this.workerNodes[workerNodeKey]]
+ return workerNodeKey
}
/**
runTimeHistory: new CircularArray(),
avgRunTime: 0,
medRunTime: 0,
+ waitTime: 0,
+ waitTimeHistory: new CircularArray(),
+ avgWaitTime: 0,
+ medWaitTime: 0,
error: 0
},
tasksQueue: new Queue<Task<Data>>()