test: improve WCS coverage
[poolifier.git] / tests / pools / selection-strategies / selection-strategies.test.js
index 0df558deb71865434c57b2d3029f21222aa28b26..1f99e086fc05d16eb064433f8584013fd44a30d7 100644 (file)
@@ -1,9 +1,10 @@
 const { expect } = require('expect')
 const {
-  WorkerChoiceStrategies,
+  DynamicClusterPool,
   DynamicThreadPool,
+  FixedClusterPool,
   FixedThreadPool,
-  FixedClusterPool
+  WorkerChoiceStrategies
 } = require('../../../lib')
 const { CircularArray } = require('../../../lib/circular-array')
 
@@ -65,6 +66,43 @@ describe('Selection strategies test suite', () => {
       expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
         workerChoiceStrategy
       )
+      expect(pool.opts.workerChoiceStrategyOptions).toStrictEqual({
+        retries: 6,
+        runTime: { median: false },
+        waitTime: { median: false },
+        elu: { median: false }
+      })
+      expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({
+        retries: 6,
+        runTime: { median: false },
+        waitTime: { median: false },
+        elu: { median: false }
+      })
+      await pool.destroy()
+    }
+    for (const workerChoiceStrategy of Object.values(WorkerChoiceStrategies)) {
+      const pool = new DynamicClusterPool(
+        min,
+        max,
+        './tests/worker-files/cluster/testWorker.js'
+      )
+      pool.setWorkerChoiceStrategy(workerChoiceStrategy, { retries: 3 })
+      expect(pool.opts.workerChoiceStrategy).toBe(workerChoiceStrategy)
+      expect(pool.workerChoiceStrategyContext.workerChoiceStrategy).toBe(
+        workerChoiceStrategy
+      )
+      expect(pool.opts.workerChoiceStrategyOptions).toStrictEqual({
+        retries: 3,
+        runTime: { median: false },
+        waitTime: { median: false },
+        elu: { median: false }
+      })
+      expect(pool.workerChoiceStrategyContext.opts).toStrictEqual({
+        retries: 3,
+        runTime: { median: false },
+        waitTime: { median: false },
+        elu: { median: false }
+      })
       await pool.destroy()
     }
   })
@@ -75,13 +113,17 @@ 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
-          ).nextWorkerNodeId
-        ).toBe(0)
-      } else if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) {
+      expect(
+        pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+          workerChoiceStrategy
+        ).nextWorkerNodeKey
+      ).toBe(0)
+      expect(
+        pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+          workerChoiceStrategy
+        ).previousWorkerNodeKey
+      ).toBe(0)
+      if (workerChoiceStrategy === WorkerChoiceStrategies.FAIR_SHARE) {
         expect(
           pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
             workerChoiceStrategy
@@ -98,8 +140,17 @@ describe('Selection strategies test suite', () => {
         expect(
           pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
             workerChoiceStrategy
-          ).currentWorkerNodeId
+          ).defaultWorkerWeight
+        ).toBeGreaterThan(0)
+        expect(
+          pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+            workerChoiceStrategy
+          ).workerVirtualTaskRunTime
         ).toBe(0)
+      } else if (
+        workerChoiceStrategy ===
+        WorkerChoiceStrategies.INTERLEAVED_WEIGHTED_ROUND_ROBIN
+      ) {
         expect(
           pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
             workerChoiceStrategy
@@ -110,6 +161,25 @@ describe('Selection strategies test suite', () => {
             workerChoiceStrategy
           ).workerVirtualTaskRunTime
         ).toBe(0)
+        expect(
+          pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+            workerChoiceStrategy
+          ).roundId
+        ).toBe(0)
+        expect(
+          pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+            workerChoiceStrategy
+          ).workerNodeId
+        ).toBe(0)
+        expect(
+          pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+            workerChoiceStrategy
+          ).roundWeights
+        ).toStrictEqual([
+          pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+            workerChoiceStrategy
+          ).defaultWorkerWeight
+        ])
       }
     }
     await pool.destroy()
@@ -123,7 +193,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: true
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     await pool.destroy()
     pool = new DynamicThreadPool(
@@ -133,7 +204,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: true
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -209,47 +281,41 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.workerUsage).toStrictEqual({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: maxMultiplier,
           executing: 0,
           queued: 0,
+          maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
         runTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
-          },
-          utilization: 0
+            history: new CircularArray()
+          }
         }
       })
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         WorkerChoiceStrategies.ROUND_ROBIN
-      ).nextWorkerNodeId
+      ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        WorkerChoiceStrategies.ROUND_ROBIN
+      ).previousWorkerNodeKey
+    ).toBe(pool.workerNodes.length - 1)
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -269,47 +335,45 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.workerUsage).toStrictEqual({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
-          executed: maxMultiplier,
+          executed: expect.any(Number),
           executing: 0,
           queued: 0,
+          maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
         runTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
-          },
-          utilization: 0
+            history: new CircularArray()
+          }
         }
       })
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
+        max * maxMultiplier
+      )
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         WorkerChoiceStrategies.ROUND_ROBIN
-      ).nextWorkerNodeId
+      ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        WorkerChoiceStrategies.ROUND_ROBIN
+      ).previousWorkerNodeKey
+    ).toBe(pool.workerNodes.length - 1)
     // We need to clean up the resources after our test
     await pool.destroy()
   })
@@ -347,16 +411,16 @@ describe('Selection strategies test suite', () => {
       './tests/worker-files/thread/testWorker.js',
       { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
     )
+    pool.setWorkerChoiceStrategy(workerChoiceStrategy)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
-      ).nextWorkerNodeId
-    ).toBeDefined()
-    pool.setWorkerChoiceStrategy(workerChoiceStrategy)
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
-      ).nextWorkerNodeId
+      ).previousWorkerNodeKey
     ).toBe(0)
     await pool.destroy()
     pool = new DynamicThreadPool(
@@ -365,16 +429,16 @@ describe('Selection strategies test suite', () => {
       './tests/worker-files/thread/testWorker.js',
       { workerChoiceStrategy: WorkerChoiceStrategies.WEIGHTED_ROUND_ROBIN }
     )
+    pool.setWorkerChoiceStrategy(workerChoiceStrategy)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
-      ).nextWorkerNodeId
-    ).toBeDefined()
-    pool.setWorkerChoiceStrategy(workerChoiceStrategy)
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
-      ).nextWorkerNodeId
+      ).previousWorkerNodeKey
     ).toBe(0)
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -388,7 +452,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: false
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     await pool.destroy()
     pool = new DynamicThreadPool(
@@ -398,7 +463,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: false
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -474,41 +540,34 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.workerUsage).toStrictEqual({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
-          executed: maxMultiplier,
+          executed: expect.any(Number),
           executing: 0,
           queued: 0,
+          maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
         runTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
-          },
-          utilization: 0
+            history: new CircularArray()
+          }
         }
       })
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
+        max * maxMultiplier
+      )
     }
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -529,41 +588,34 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.workerUsage).toStrictEqual({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
-          executed: maxMultiplier,
+          executed: expect.any(Number),
           executing: 0,
           queued: 0,
+          maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
         runTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
-          },
-          utilization: 0
+            history: new CircularArray()
+          }
         }
       })
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
+        max * maxMultiplier
+      )
     }
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -577,7 +629,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: false
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     await pool.destroy()
     pool = new DynamicThreadPool(
@@ -587,7 +640,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: false
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -663,49 +717,44 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.workerUsage).toStrictEqual({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
           queued: 0,
+          maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
-        runTime: {
-          aggregate: expect.any(Number),
-          average: 0,
-          median: 0,
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
-        waitTime: {
-          aggregate: expect.any(Number),
-          average: 0,
-          median: 0,
+        }),
+        waitTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         elu: {
           idle: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
-          },
-          utilization: 0
+            history: new CircularArray()
+          }
         }
       })
-      expect(workerNode.workerUsage.tasks.executed).toBeGreaterThan(0)
-      expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
         max * maxMultiplier
       )
-      expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThanOrEqual(0)
-      expect(workerNode.workerUsage.waitTime.aggregate).toBeGreaterThanOrEqual(
-        0
-      )
+      if (workerNode.usage.runTime.aggregate == null) {
+        expect(workerNode.usage.runTime.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.waitTime.aggregate == null) {
+        expect(workerNode.usage.waitTime.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
+      }
     }
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -726,47 +775,44 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.workerUsage).toStrictEqual({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
           queued: 0,
+          maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
-        runTime: {
-          aggregate: expect.any(Number),
-          average: 0,
-          median: 0,
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
-        waitTime: {
-          aggregate: expect.any(Number),
-          average: 0,
-          median: 0,
+        }),
+        waitTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         elu: {
           idle: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
-          },
-          utilization: 0
+            history: new CircularArray()
+          }
         }
       })
-      expect(workerNode.workerUsage.tasks.executed).toBeGreaterThan(0)
-      expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
         max * maxMultiplier
       )
-      expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
-      expect(workerNode.workerUsage.waitTime.aggregate).toBeGreaterThan(0)
+      if (workerNode.usage.runTime.aggregate == null) {
+        expect(workerNode.usage.runTime.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.waitTime.aggregate == null) {
+        expect(workerNode.usage.waitTime.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.waitTime.aggregate).toBeGreaterThan(0)
+      }
     }
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -780,7 +826,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: false
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     await pool.destroy()
     pool = new DynamicThreadPool(
@@ -790,7 +837,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: false
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -866,47 +914,50 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.workerUsage).toStrictEqual({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
           queued: 0,
+          maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
         runTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
-        elu: {
-          idle: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
+        elu: expect.objectContaining({
+          idle: expect.objectContaining({
             history: expect.any(CircularArray)
-          },
-          active: {
-            aggregate: expect.any(Number),
-            average: 0,
-            median: 0,
+          }),
+          active: expect.objectContaining({
             history: expect.any(CircularArray)
-          },
-          utilization: expect.any(Number)
-        }
+          })
+        })
       })
-      expect(workerNode.workerUsage.tasks.executed).toBeGreaterThanOrEqual(0)
-      expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
         max * maxMultiplier
       )
-      expect(workerNode.workerUsage.elu.utilization).toBeGreaterThanOrEqual(0)
-      expect(workerNode.workerUsage.elu.utilization).toBeLessThanOrEqual(1)
+      if (workerNode.usage.elu.active.aggregate == null) {
+        expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.elu.idle.aggregate == null) {
+        expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
+      }
+      if (workerNode.usage.elu.utilization == null) {
+        expect(workerNode.usage.elu.utilization).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
+        expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
+      }
     }
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -927,47 +978,50 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.workerUsage).toStrictEqual({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
           queued: 0,
+          maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
         runTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         waitTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
-        elu: {
-          idle: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
+        elu: expect.objectContaining({
+          idle: expect.objectContaining({
             history: expect.any(CircularArray)
-          },
-          active: {
-            aggregate: expect.any(Number),
-            average: 0,
-            median: 0,
+          }),
+          active: expect.objectContaining({
             history: expect.any(CircularArray)
-          },
-          utilization: expect.any(Number)
-        }
+          })
+        })
       })
-      expect(workerNode.workerUsage.tasks.executed).toBeGreaterThanOrEqual(0)
-      expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
         max * maxMultiplier
       )
-      expect(workerNode.workerUsage.elu.utilization).toBeGreaterThanOrEqual(0)
-      expect(workerNode.workerUsage.elu.utilization).toBeLessThanOrEqual(1)
+      if (workerNode.usage.elu.active.aggregate == null) {
+        expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.elu.idle.aggregate == null) {
+        expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
+      }
+      if (workerNode.usage.elu.utilization == null) {
+        expect(workerNode.usage.elu.utilization).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
+        expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
+      }
     }
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -981,7 +1035,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: false
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     await pool.destroy()
     pool = new DynamicThreadPool(
@@ -991,7 +1046,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: false
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -1067,45 +1123,60 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.workerUsage).toStrictEqual({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
-          executed: maxMultiplier,
+          executed: expect.any(Number),
           executing: 0,
           queued: 0,
+          maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
-        runTime: {
-          aggregate: expect.any(Number),
-          average: expect.any(Number),
-          median: 0,
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
-        elu: {
-          idle: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
+        elu: expect.objectContaining({
+          idle: expect.objectContaining({
             history: expect.any(CircularArray)
-          },
-          active: {
-            aggregate: expect.any(Number),
-            average: expect.any(Number),
-            median: 0,
+          }),
+          active: expect.objectContaining({
             history: expect.any(CircularArray)
-          },
-          utilization: expect.any(Number)
-        }
+          })
+        })
       })
-      expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
-      expect(workerNode.workerUsage.runTime.average).toBeGreaterThan(0)
-      expect(workerNode.workerUsage.elu.utilization).toBeGreaterThanOrEqual(0)
-      expect(workerNode.workerUsage.elu.utilization).toBeLessThanOrEqual(1)
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
+        max * maxMultiplier
+      )
+      if (workerNode.usage.runTime.aggregate == null) {
+        expect(workerNode.usage.runTime.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.runTime.average == null) {
+        expect(workerNode.usage.runTime.average).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.elu.active.aggregate == null) {
+        expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.elu.idle.aggregate == null) {
+        expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
+      }
+      if (workerNode.usage.elu.utilization == null) {
+        expect(workerNode.usage.elu.utilization).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
+        expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
+      }
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1131,49 +1202,60 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.workerUsage).toStrictEqual({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
           queued: 0,
+          maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
-        runTime: {
-          aggregate: expect.any(Number),
-          average: expect.any(Number),
-          median: 0,
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
-        elu: {
-          idle: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
+        elu: expect.objectContaining({
+          idle: expect.objectContaining({
             history: expect.any(CircularArray)
-          },
-          active: {
-            aggregate: expect.any(Number),
-            average: expect.any(Number),
-            median: 0,
+          }),
+          active: expect.objectContaining({
             history: expect.any(CircularArray)
-          },
-          utilization: expect.any(Number)
-        }
+          })
+        })
       })
-      expect(workerNode.workerUsage.tasks.executed).toBeGreaterThan(0)
-      expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
         max * maxMultiplier
       )
-      expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
-      expect(workerNode.workerUsage.runTime.average).toBeGreaterThan(0)
-      expect(workerNode.workerUsage.elu.utilization).toBeGreaterThanOrEqual(0)
-      expect(workerNode.workerUsage.elu.utilization).toBeLessThanOrEqual(1)
+      if (workerNode.usage.runTime.aggregate == null) {
+        expect(workerNode.usage.runTime.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.runTime.average == null) {
+        expect(workerNode.usage.runTime.average).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.elu.active.aggregate == null) {
+        expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.elu.idle.aggregate == null) {
+        expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
+      }
+      if (workerNode.usage.elu.utilization == null) {
+        expect(workerNode.usage.elu.utilization).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
+        expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
+      }
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1204,49 +1286,60 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.workerUsage).toStrictEqual({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
           queued: 0,
+          maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
-        runTime: {
-          aggregate: expect.any(Number),
-          average: 0,
-          median: expect.any(Number),
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
-        elu: {
-          idle: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
+        elu: expect.objectContaining({
+          idle: expect.objectContaining({
             history: expect.any(CircularArray)
-          },
-          active: {
-            aggregate: expect.any(Number),
-            average: expect.any(Number),
-            median: 0,
+          }),
+          active: expect.objectContaining({
             history: expect.any(CircularArray)
-          },
-          utilization: expect.any(Number)
-        }
+          })
+        })
       })
-      expect(workerNode.workerUsage.tasks.executed).toBeGreaterThan(0)
-      expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
         max * maxMultiplier
       )
-      expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
-      expect(workerNode.workerUsage.runTime.median).toBeGreaterThan(0)
-      expect(workerNode.workerUsage.elu.utilization).toBeGreaterThanOrEqual(0)
-      expect(workerNode.workerUsage.elu.utilization).toBeLessThanOrEqual(1)
+      if (workerNode.usage.runTime.aggregate == null) {
+        expect(workerNode.usage.runTime.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.runTime.median == null) {
+        expect(workerNode.usage.runTime.median).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.elu.active.aggregate == null) {
+        expect(workerNode.usage.elu.active.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.active.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.elu.idle.aggregate == null) {
+        expect(workerNode.usage.elu.idle.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.idle.aggregate).toBeGreaterThanOrEqual(0)
+      }
+      if (workerNode.usage.elu.utilization == null) {
+        expect(workerNode.usage.elu.utilization).toBeUndefined()
+      } else {
+        expect(workerNode.usage.elu.utilization).toBeGreaterThanOrEqual(0)
+        expect(workerNode.usage.elu.utilization).toBeLessThanOrEqual(1)
+      }
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1284,12 +1377,12 @@ describe('Selection strategies test suite', () => {
     pool.setWorkerChoiceStrategy(workerChoiceStrategy)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).workersVirtualTaskEndTimestamp
     ).toBeInstanceOf(Array)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).workersVirtualTaskEndTimestamp.length
     ).toBe(0)
     await pool.destroy()
@@ -1319,12 +1412,12 @@ describe('Selection strategies test suite', () => {
     pool.setWorkerChoiceStrategy(workerChoiceStrategy)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).workersVirtualTaskEndTimestamp
     ).toBeInstanceOf(Array)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).workersVirtualTaskEndTimestamp.length
     ).toBe(0)
     // We need to clean up the resources after our test
@@ -1339,7 +1432,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: true
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     await pool.destroy()
     pool = new DynamicThreadPool(
@@ -1349,7 +1443,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: true
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -1425,47 +1520,44 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.workerUsage).toStrictEqual({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
           queued: 0,
+          maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
-        runTime: {
-          aggregate: expect.any(Number),
-          average: expect.any(Number),
-          median: 0,
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
-          },
-          utilization: 0
+            history: new CircularArray()
+          }
         }
       })
-      expect(workerNode.workerUsage.tasks.executed).toBeGreaterThanOrEqual(0)
-      expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
         max * maxMultiplier
       )
-      expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThanOrEqual(0)
-      expect(workerNode.workerUsage.runTime.average).toBeGreaterThanOrEqual(0)
+      if (workerNode.usage.runTime.aggregate == null) {
+        expect(workerNode.usage.runTime.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.runTime.average == null) {
+        expect(workerNode.usage.runTime.average).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
+      }
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1496,47 +1588,44 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.workerUsage).toStrictEqual({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
           queued: 0,
+          maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
-        runTime: {
-          aggregate: expect.any(Number),
-          average: expect.any(Number),
-          median: 0,
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
-          },
-          utilization: 0
+            history: new CircularArray()
+          }
         }
       })
-      expect(workerNode.workerUsage.tasks.executed).toBeGreaterThanOrEqual(0)
-      expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
         max * maxMultiplier
       )
-      expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
-      expect(workerNode.workerUsage.runTime.average).toBeGreaterThan(0)
+      if (workerNode.usage.runTime.aggregate == null) {
+        expect(workerNode.usage.runTime.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.runTime.average == null) {
+        expect(workerNode.usage.runTime.average).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.average).toBeGreaterThan(0)
+      }
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1572,47 +1661,44 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.workerUsage).toStrictEqual({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
           executed: expect.any(Number),
           executing: 0,
           queued: 0,
+          maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
-        runTime: {
-          aggregate: expect.any(Number),
-          average: 0,
-          median: expect.any(Number),
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
-          },
-          utilization: 0
+            history: new CircularArray()
+          }
         }
       })
-      expect(workerNode.workerUsage.tasks.executed).toBeGreaterThanOrEqual(0)
-      expect(workerNode.workerUsage.tasks.executed).toBeLessThanOrEqual(
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
         max * maxMultiplier
       )
-      expect(workerNode.workerUsage.runTime.aggregate).toBeGreaterThan(0)
-      expect(workerNode.workerUsage.runTime.median).toBeGreaterThan(0)
+      if (workerNode.usage.runTime.aggregate == null) {
+        expect(workerNode.usage.runTime.aggregate).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.aggregate).toBeGreaterThan(0)
+      }
+      if (workerNode.usage.runTime.median == null) {
+        expect(workerNode.usage.runTime.median).toBeUndefined()
+      } else {
+        expect(workerNode.usage.runTime.median).toBeGreaterThan(0)
+      }
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1637,7 +1723,12 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
-      ).currentWorkerNodeId
+      ).nextWorkerNodeKey
+    ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).previousWorkerNodeKey
     ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1653,7 +1744,12 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
-      ).currentWorkerNodeId
+      ).nextWorkerNodeKey
+    ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
     ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1662,7 +1758,7 @@ describe('Selection strategies test suite', () => {
     ).toBeGreaterThan(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).workerVirtualTaskRunTime
     ).toBe(0)
     await pool.destroy()
@@ -1674,7 +1770,12 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
-      ).currentWorkerNodeId
+      ).nextWorkerNodeKey
+    ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).previousWorkerNodeKey
     ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1690,7 +1791,12 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
-      ).currentWorkerNodeId
+      ).nextWorkerNodeKey
+    ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
     ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1699,7 +1805,7 @@ describe('Selection strategies test suite', () => {
     ).toBeGreaterThan(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).workerVirtualTaskRunTime
     ).toBe(0)
     // We need to clean up the resources after our test
@@ -1715,7 +1821,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: true
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     await pool.destroy()
     pool = new DynamicThreadPool(
@@ -1725,7 +1832,8 @@ describe('Selection strategies test suite', () => {
       { workerChoiceStrategy }
     )
     expect(pool.workerChoiceStrategyContext.getStrategyPolicy()).toStrictEqual({
-      useDynamicWorker: true
+      dynamicWorkerUsage: false,
+      dynamicWorkerReady: true
     })
     // We need to clean up the resources after our test
     await pool.destroy()
@@ -1743,8 +1851,8 @@ describe('Selection strategies test suite', () => {
       pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
     ).toStrictEqual({
       runTime: {
-        aggregate: false,
-        average: false,
+        aggregate: true,
+        average: true,
         median: false
       },
       waitTime: {
@@ -1769,8 +1877,8 @@ describe('Selection strategies test suite', () => {
       pool.workerChoiceStrategyContext.getTaskStatisticsRequirements()
     ).toStrictEqual({
       runTime: {
-        aggregate: false,
-        average: false,
+        aggregate: true,
+        average: true,
         median: false
       },
       waitTime: {
@@ -1805,41 +1913,34 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.workerUsage).toStrictEqual({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
-          executed: maxMultiplier,
+          executed: expect.any(Number),
           executing: 0,
           queued: 0,
+          maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
-        runTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
-          },
-          utilization: 0
+            history: new CircularArray()
+          }
         }
       })
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
+        max * maxMultiplier
+      )
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1849,13 +1950,23 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
-      ).currentRoundId
+      ).roundId
+    ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).workerNodeId
     ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
-      ).currentWorkerNodeId
+      ).nextWorkerNodeKey
     ).toBe(0)
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
+      ).previousWorkerNodeKey
+    ).toEqual(expect.any(Number))
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
@@ -1887,41 +1998,34 @@ describe('Selection strategies test suite', () => {
     }
     await Promise.all(promises)
     for (const workerNode of pool.workerNodes) {
-      expect(workerNode.workerUsage).toStrictEqual({
+      expect(workerNode.usage).toStrictEqual({
         tasks: {
-          executed: maxMultiplier,
+          executed: expect.any(Number),
           executing: 0,
           queued: 0,
+          maxQueued: 0,
+          stolen: 0,
           failed: 0
         },
-        runTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
+        runTime: expect.objectContaining({
           history: expect.any(CircularArray)
-        },
+        }),
         waitTime: {
-          aggregate: 0,
-          average: 0,
-          median: 0,
-          history: expect.any(CircularArray)
+          history: new CircularArray()
         },
         elu: {
           idle: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
+            history: new CircularArray()
           },
           active: {
-            aggregate: 0,
-            average: 0,
-            median: 0,
-            history: expect.any(CircularArray)
-          },
-          utilization: 0
+            history: new CircularArray()
+          }
         }
       })
+      expect(workerNode.usage.tasks.executed).toBeGreaterThanOrEqual(0)
+      expect(workerNode.usage.tasks.executed).toBeLessThanOrEqual(
+        max * maxMultiplier
+      )
     }
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1931,13 +2035,23 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
-      ).currentRoundId
+      ).roundId
     ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
-      ).currentWorkerNodeId
+      ).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
@@ -1961,12 +2075,22 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
-      ).currentRoundId
+      ).roundId
+    ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).workerNodeId
+    ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).nextWorkerNodeKey
     ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
-      ).currentWorkerNodeId
+      ).previousWorkerNodeKey
     ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1981,13 +2105,23 @@ describe('Selection strategies test suite', () => {
     pool.setWorkerChoiceStrategy(workerChoiceStrategy)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
-      ).currentRoundId
+        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
-      ).currentWorkerNodeId
+      ).previousWorkerNodeKey
     ).toBe(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -1996,7 +2130,7 @@ describe('Selection strategies test suite', () => {
     ).toBeGreaterThan(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).roundWeights
     ).toStrictEqual([
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -2012,12 +2146,22 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
-      ).currentRoundId
+      ).roundId
     ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         workerChoiceStrategy
-      ).currentWorkerNodeId
+      ).workerNodeId
+    ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).nextWorkerNodeKey
+    ).toBeDefined()
+    expect(
+      pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
+        workerChoiceStrategy
+      ).previousWorkerNodeKey
     ).toBeDefined()
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
@@ -2033,7 +2177,22 @@ describe('Selection strategies test suite', () => {
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
         pool.workerChoiceStrategyContext.workerChoiceStrategy
-      ).currentWorkerNodeId
+      ).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(
@@ -2042,7 +2201,7 @@ describe('Selection strategies test suite', () => {
     ).toBeGreaterThan(0)
     expect(
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(
-        workerChoiceStrategy
+        pool.workerChoiceStrategyContext.workerChoiceStrategy
       ).roundWeights
     ).toStrictEqual([
       pool.workerChoiceStrategyContext.workerChoiceStrategies.get(