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 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) => {
*
* @param workerNodeKey - The worker node key.
*/
- protected beforeTaskExecutionHook (workerNodeKey: number): void {
- ++this.workerNodes[workerNodeKey].tasksUsage.running
+ protected beforeTaskExecutionHook (
+ workerNodeKey: number,
+ task: Task<Data>
+ ): void {
+ const workerTasksUsage = this.workerNodes[workerNodeKey].tasksUsage
+ ++workerTasksUsage.running
+ if (this.workerChoiceStrategyContext.getRequiredStatistics().waitTime) {
+ const waitTime = performance.now() - (task.submissionTimestamp ?? 0)
+ workerTasksUsage.waitTime += waitTime
+ if (
+ this.workerChoiceStrategyContext.getRequiredStatistics().medWaitTime
+ ) {
+ workerTasksUsage.waitTimeHistory.push(waitTime)
+ workerTasksUsage.medWaitTime = median(workerTasksUsage.waitTimeHistory)
+ }
+ }
}
/**
workerTasksUsage.medRunTime = median(workerTasksUsage.runTimeHistory)
}
}
+ if (
+ this.workerChoiceStrategyContext.getRequiredStatistics().waitTime &&
+ this.workerChoiceStrategyContext.getRequiredStatistics().avgWaitTime &&
+ workerTasksUsage.run !== 0
+ ) {
+ workerTasksUsage.avgWaitTime =
+ workerTasksUsage.waitTime / workerTasksUsage.run
+ }
}
/**
runTimeHistory: new CircularArray(),
avgRunTime: 0,
medRunTime: 0,
+ waitTime: 0,
+ waitTimeHistory: new CircularArray(),
+ avgWaitTime: 0,
+ medWaitTime: 0,
error: 0
},
tasksQueue: new Queue<Task<Data>>()
}
private executeTask (workerNodeKey: number, task: Task<Data>): void {
- this.beforeTaskExecutionHook(workerNodeKey)
+ this.beforeTaskExecutionHook(workerNodeKey, task)
this.sendToWorker(this.workerNodes[workerNodeKey].worker, task)
}
public readonly requiredStatistics: RequiredStatistics = {
runTime: false,
avgRunTime: false,
- medRunTime: false
+ medRunTime: false,
+ waitTime: false,
+ avgWaitTime: false,
+ medWaitTime: false
}
/**
this.requiredStatistics.avgRunTime = true
this.requiredStatistics.medRunTime = opts.medRunTime as boolean
}
+ if (this.requiredStatistics.avgWaitTime && opts.medWaitTime === true) {
+ this.requiredStatistics.avgWaitTime = false
+ this.requiredStatistics.medWaitTime = opts.medWaitTime as boolean
+ }
+ if (this.requiredStatistics.medWaitTime && opts.medWaitTime === false) {
+ this.requiredStatistics.avgWaitTime = true
+ this.requiredStatistics.medWaitTime = opts.medWaitTime as boolean
+ }
}
/** @inheritDoc */
* Task input data that will be passed to the worker.
*/
readonly data?: Data
+ /**
+ * Submission timestamp.
+ */
+ readonly submissionTimestamp?: number
/**
* Message UUID.
*/
* Median tasks runtime.
*/
medRunTime: number
+ /**
+ * Tasks wait time.
+ */
+ waitTime: number
+ /**
+ * Tasks wait time history.
+ */
+ waitTimeHistory: CircularArray<number>
+ /**
+ * Average tasks wait time.
+ */
+ avgWaitTime: number
+ /**
+ * Median tasks wait time.
+ */
+ medWaitTime: number
/**
* Number of tasks errored.
*/