Merge dependabot/npm_and_yarn/examples/typescript/http-server-pool/fastify-worker_thr...
[poolifier.git] / tests / pools / selection-strategies / selection-strategies.test.js
index 6b5dfdb567e5e220b63afafed22b91702dc699b9..3329e1dc718f3565202e1344479248013a6171c8 100644 (file)
@@ -113,41 +113,62 @@ describe('Selection strategies test suite', () => {
       './tests/worker-files/thread/testWorker.js'
     )
     for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
-      if (workerChoiceStrategy === WorkerChoiceStrategies.ROUND_ROBIN) {
+      expect(
+        pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+          workerChoiceStrategy
+        ).nextWorkerNodeKey
+      ).toBe(0)
+      expect(
+        pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+          workerChoiceStrategy
+        ).previousWorkerNodeKey
+      ).toBe(0)
+      if (
+        workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
+      ) {
+        expect(
+          pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+            workerChoiceStrategy
+          ).defaultWorkerWeight
+        ).toBeGreaterThan(0)
         expect(
           pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
             workerChoiceStrategy
-          ).nextWorkerNodeKey
+          ).workerNodeVirtualTaskRunTime
         ).toBe(0)
-      } else if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) {
+      } else if (
+        workerChoiceStrategy ===
+        WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
+      ) {
         expect(
           pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
             workerChoiceStrategy
-          ).workersVirtualTaskEndTimestamp
-        ).toBeInstanceOf(Array)
+          ).defaultWorkerWeight
+        ).toBeGreaterThan(0)
         expect(
           pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
             workerChoiceStrategy
-          ).workersVirtualTaskEndTimestamp.length
+          ).workerNodeVirtualTaskRunTime
         ).toBe(0)
-      } else if (
-        workerChoiceStrategy === WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN
-      ) {
         expect(
           pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
             workerChoiceStrategy
-          ).nextWorkerNodeKey
+          ).roundId
         ).toBe(0)
         expect(
           pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
             workerChoiceStrategy
-          ).defaultWorkerWeight
-        ).toBeGreaterThan(0)
+          ).workerNodeId
+        ).toBe(0)
         expect(
           pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
             workerChoiceStrategy
-          ).workerVirtualTaskRunTime
-        ).toBe(0)
+          ).roundWeights
+        ).toStrictEqual([
+          pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+            workerChoiceStrategy
+          ).defaultWorkerWeight
+        ])
       }
     }
     await pool.destroy()
@@ -236,10 +257,11 @@ describe('Selection strategies test suite', () => {
   })
 
   it('Verify ROUND_ROBIN strategy can be run in a fixed pool', async () => {
+    const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
     const pool = new FixedThreadPool(
       max,
       './tests/worker-files/thread/testWorker.js',
-      { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
+      { workerChoiceStrategy }
     )
     // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
     const promises = new Set()
@@ -259,36 +281,42 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        WorkerChoiceStrategies.ROUND_ROBIN
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(pool.workerNodes.length - 1)
     // We need to clean up the resources after our test
     await pool.destroy()
   })
 
   it('Verify ROUND_ROBIN strategy can be run in a dynamic pool', async () => {
+    const workerChoiceStrategy = WorkerChoiceStrategies.ROUND_ROBIN
     const pool = new DynamicThreadPool(
       min,
       max,
       './tests/worker-files/thread/testWorker.js',
-      { workerChoiceStrategy: WorkerChoiceStrategies.ROUND_ROBIN }
+      { workerChoiceStrategy }
     )
     // TODO: Create a better test to cover `RoundRobinWorkerChoiceStrategy#choose`
     const promises = new Set()
@@ -308,17 +336,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
@@ -329,9 +357,14 @@ describe('Selection strategies test suite', () => {
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        WorkerChoiceStrategies.ROUND_ROBIN
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(pool.workerNodes.length - 1)
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -371,15 +404,25 @@ describe('Selection strategies test suite', () => {
     )
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBeDefined()
     pool.setWorkerChoiceStrategy(workerChoiceStrategy)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     await pool.destroy()
     pool = new DynamicThreadPool(
       min,
@@ -389,15 +432,25 @@ describe('Selection strategies test suite', () => {
     )
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBeDefined()
     pool.setWorkerChoiceStrategy(workerChoiceStrategy)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -508,17 +561,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
@@ -527,6 +580,16 @@ describe('Selection strategies test suite', () => {
         max * maxMultiplier
       )
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -556,17 +619,17 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
@@ -575,6 +638,16 @@ describe('Selection strategies test suite', () => {
         max * maxMultiplier
       )
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -675,7 +748,7 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.usage).toMatchObject({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
@@ -684,18 +757,18 @@ describe('Selection strategies test suite', () => {
           stolen: 0,
           failed: 0
         },
-        runTime: {
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
-        waitTime: {
+        }),
+        waitTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
@@ -714,6 +787,16 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
       }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -733,7 +816,7 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.usage).toMatchObject({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
@@ -742,18 +825,18 @@ describe('Selection strategies test suite', () => {
           stolen: 0,
           failed: 0
         },
-        runTime: {
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
-        waitTime: {
+        }),
+        waitTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
@@ -772,6 +855,16 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
       }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -872,7 +965,7 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.usage).toMatchObject({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
@@ -882,19 +975,19 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
-        elu: {
-          idle: {
+        elu: expect.objectContaining({
+          idle: expect.objectContaining({
             history: expect.any(CircularArray)
-          },
-          active: {
+          }),
+          active: expect.objectContaining({
             history: expect.any(CircularArray)
-          }
-        }
+          })
+        })
       })
       expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
       expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
@@ -917,6 +1010,16 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
       }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -936,7 +1039,7 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.usage).toMatchObject({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
@@ -946,19 +1049,19 @@ describe('Selection strategies test suite', () => {
           failed: 0
         },
         runTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
-        elu: {
-          idle: {
+        elu: expect.objectContaining({
+          idle: expect.objectContaining({
             history: expect.any(CircularArray)
-          },
-          active: {
+          }),
+          active: expect.objectContaining({
             history: expect.any(CircularArray)
-          }
-        }
+          })
+        })
       })
       expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
       expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
@@ -981,6 +1084,16 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
       }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -1081,7 +1194,7 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.usage).toMatchObject({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
@@ -1090,20 +1203,20 @@ describe('Selection strategies test suite', () => {
           stolen: 0,
           failed: 0
         },
-        runTime: {
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
-        elu: {
-          idle: {
+        elu: expect.objectContaining({
+          idle: expect.objectContaining({
             history: expect.any(CircularArray)
-          },
-          active: {
+          }),
+          active: expect.objectContaining({
             history: expect.any(CircularArray)
-          }
-        }
+          })
+        })
       })
       expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
       expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
@@ -1135,12 +1248,18 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
         expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
       }
+      expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
-      ).workersVirtualTaskEndTimestamp.length
-    ).toBe(pool.workerNodes.length)
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -1160,7 +1279,7 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.usage).toMatchObject({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
@@ -1169,20 +1288,20 @@ describe('Selection strategies test suite', () => {
           stolen: 0,
           failed: 0
         },
-        runTime: {
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
-        elu: {
-          idle: {
+        elu: expect.objectContaining({
+          idle: expect.objectContaining({
             history: expect.any(CircularArray)
-          },
-          active: {
+          }),
+          active: expect.objectContaining({
             history: expect.any(CircularArray)
-          }
-        }
+          })
+        })
       })
       expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
       expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
@@ -1214,12 +1333,18 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
         expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
       }
+      expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
-      ).workersVirtualTaskEndTimestamp.length
-    ).toBe(pool.workerNodes.length)
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -1244,7 +1369,7 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.usage).toMatchObject({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
@@ -1253,20 +1378,20 @@ describe('Selection strategies test suite', () => {
           stolen: 0,
           failed: 0
         },
-        runTime: {
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
-        elu: {
-          idle: {
+        elu: expect.objectContaining({
+          idle: expect.objectContaining({
             history: expect.any(CircularArray)
-          },
-          active: {
+          }),
+          active: expect.objectContaining({
             history: expect.any(CircularArray)
-          }
-        }
+          })
+        })
       })
       expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
       expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
@@ -1298,12 +1423,18 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
         expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
       }
+      expect(workerNode.strategyData.virtualTaskEndTimestamp).toBeGreaterThan(0)
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
-      ).workersVirtualTaskEndTimestamp.length
-    ).toBe(pool.workerNodes.length)
+      ).nextWorkerNodeKey
+    ).toEqual(expect.any(Number))
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -1314,70 +1445,30 @@ describe('Selection strategies test suite', () => {
       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(
-        workerChoiceStrategy
-      ).workersVirtualTaskEndTimestamp
-    ).toBeInstanceOf(Array)
-    expect(
-      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        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(
-        workerChoiceStrategy
-      ).workersVirtualTaskEndTimestamp
-    ).toBeInstanceOf(Array)
-    expect(
-      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        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()
   })
@@ -1491,14 +1582,14 @@ describe('Selection strategies test suite', () => {
           history: expect.any(CircularArray)
         }),
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
@@ -1517,6 +1608,16 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
       }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1525,7 +1626,7 @@ describe('Selection strategies test suite', () => {
     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()
@@ -1559,14 +1660,14 @@ describe('Selection strategies test suite', () => {
           history: expect.any(CircularArray)
         }),
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
@@ -1585,6 +1686,16 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
       }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1593,7 +1704,7 @@ describe('Selection strategies test suite', () => {
     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()
@@ -1632,14 +1743,14 @@ describe('Selection strategies test suite', () => {
           history: expect.any(CircularArray)
         }),
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
@@ -1658,6 +1769,16 @@ describe('Selection strategies test suite', () => {
         expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
       }
     }
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1666,7 +1787,7 @@ describe('Selection strategies test suite', () => {
     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()
@@ -1683,6 +1804,11 @@ describe('Selection strategies test suite', () => {
         workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
@@ -1691,7 +1817,7 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
-      ).workerVirtualTaskRunTime
+      ).workerNodeVirtualTaskRunTime
     ).toBeDefined()
     pool.setWorkerChoiceStrategy(workerChoiceStrategy)
     expect(
@@ -1699,6 +1825,11 @@ describe('Selection strategies test suite', () => {
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1706,8 +1837,8 @@ describe('Selection strategies test suite', () => {
     ).toBeGreaterThan(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
-      ).workerVirtualTaskRunTime
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).workerNodeVirtualTaskRunTime
     ).toBe(0)
     await pool.destroy()
     pool = new DynamicThreadPool(
@@ -1720,6 +1851,11 @@ describe('Selection strategies test suite', () => {
         workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
@@ -1728,7 +1864,7 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
-      ).workerVirtualTaskRunTime
+      ).workerNodeVirtualTaskRunTime
     ).toBeDefined()
     pool.setWorkerChoiceStrategy(workerChoiceStrategy)
     expect(
@@ -1736,6 +1872,11 @@ describe('Selection strategies test suite', () => {
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1743,8 +1884,8 @@ describe('Selection strategies test suite', () => {
     ).toBeGreaterThan(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
-      ).workerVirtualTaskRunTime
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).workerNodeVirtualTaskRunTime
     ).toBe(0)
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -1789,8 +1930,8 @@ describe('Selection strategies test suite', () => {
       pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
     ).toStrictEqual({
       runTime: {
-        aggregate: false,
-        average: false,
+        aggregate: true,
+        average: true,
         median: false
       },
       waitTime: {
@@ -1815,8 +1956,8 @@ describe('Selection strategies test suite', () => {
       pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
     ).toStrictEqual({
       runTime: {
-        aggregate: false,
-        average: false,
+        aggregate: true,
+        average: true,
         median: false
       },
       waitTime: {
@@ -1853,28 +1994,32 @@ describe('Selection strategies test suite', () => {
     for (const workerNode of pool.workerNodes) {
       expect(workerNode.usage).toStrictEqual({
         tasks: {
-          executed: maxMultiplier,
+          executed: expect.any(Number),
           executing: 0,
           queued: 0,
           maxQueued: 0,
           stolen: 0,
           failed: 0
         },
-        runTime: {
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
+        max * maxMultiplier
+      )
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1886,11 +2031,21 @@ describe('Selection strategies test suite', () => {
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).roundId
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).workerNodeId
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1931,18 +2086,18 @@ describe('Selection strategies test suite', () => {
           stolen: 0,
           failed: 0
         },
-        runTime: {
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           }
         }
       })
@@ -1961,11 +2116,21 @@ describe('Selection strategies test suite', () => {
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).roundId
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).workerNodeId
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1991,11 +2156,21 @@ describe('Selection strategies test suite', () => {
         workerChoiceStrategy
       ).roundId
     ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).workerNodeId
+    ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
@@ -2009,14 +2184,24 @@ describe('Selection strategies test suite', () => {
     pool.setWorkerChoiceStrategy(workerChoiceStrategy)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).roundId
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).workerNodeId
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -2024,7 +2209,7 @@ describe('Selection strategies test suite', () => {
     ).toBeGreaterThan(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).roundWeights
     ).toStrictEqual([
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -2042,11 +2227,21 @@ describe('Selection strategies test suite', () => {
         workerChoiceStrategy
       ).roundId
     ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).workerNodeId
+    ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
@@ -2058,11 +2253,26 @@ describe('Selection strategies test suite', () => {
       ).roundWeights
     ).toBeDefined()
     pool.setWorkerChoiceStrategy(workerChoiceStrategy)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).roundId
+    ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).workerNodeId
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -2070,7 +2280,7 @@ describe('Selection strategies test suite', () => {
     ).toBeGreaterThan(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).roundWeights
     ).toStrictEqual([
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(