-/**
- * Generate a cryptographically secure random number in the [0,1[ range
- *
- * @returns A number in the [0,1[ range
- */
-export const secureRandom = (): number => {
- return crypto.getRandomValues(new Uint32Array(1))[0] / 0x100000000
+const clone = <T extends object>(object: T): T => {
+ return JSON.parse(JSON.stringify(object)) as T
+}
+
+export const buildInternalWorkerChoiceStrategyOptions = (
+ poolMaxSize: number,
+ opts?: InternalWorkerChoiceStrategyOptions
+): InternalWorkerChoiceStrategyOptions => {
+ opts = clone(opts ?? {})
+ if (opts?.weights == null) {
+ opts.weights = getDefaultWeights(poolMaxSize)
+ }
+ return {
+ ...getDefaultInternalWorkerChoiceStrategyOptions(
+ poolMaxSize + Object.keys(opts.weights).length
+ ),
+ ...opts
+ }
+}
+
+const getDefaultWeights = (
+ poolMaxSize: number,
+ defaultWorkerWeight?: number
+): Record<number, number> => {
+ defaultWorkerWeight = defaultWorkerWeight ?? getDefaultWorkerWeight()
+ const weights: Record<number, number> = {}
+ for (let workerNodeKey = 0; workerNodeKey < poolMaxSize; workerNodeKey++) {
+ weights[workerNodeKey] = defaultWorkerWeight
+ }
+ return weights
+}
+
+const getDefaultWorkerWeight = (): number => {
+ const cpuSpeed = randomInt(500, 2500)
+ let cpusCycleTimeWeight = 0
+ for (const cpu of cpus()) {
+ if (cpu.speed == null || cpu.speed === 0) {
+ cpu.speed =
+ cpus().find(cpu => cpu.speed != null && cpu.speed !== 0)?.speed ??
+ cpuSpeed
+ }
+ // CPU estimated cycle time
+ const numberOfDigits = cpu.speed.toString().length - 1
+ const cpuCycleTime = 1 / (cpu.speed / Math.pow(10, numberOfDigits))
+ cpusCycleTimeWeight += cpuCycleTime * Math.pow(10, numberOfDigits)
+ }
+ return Math.round(cpusCycleTimeWeight / cpus().length)