# `LeastBusyStrategy` _(no submodules)_ ## Purpose `LeastBusyStrategy` selects the eligible worker with the fewest in-flight tasks. When `usePerformanceMetrics` is enabled it also tracks a rolling-average execution time per worker (success only) and uses it to break ties — preferring faster workers on equal load. The strategy is the right default for heterogeneous pools where worker performance varies but capacity counts are the primary distribution signal. ## Features - Tie-break order: lower `activeTasks` → (optional) lower `avgExecutionTime` → higher `capacity` → higher `weight`. - `notifyTaskCompleted(worker, task, success, durationMs)` updates the per-worker EWMA cumulative average; failures are ignored so a flaky worker can't bias selection downward. - `getWorkerPerformance(id)` returns the stored record or `null`. - `resetPerformanceMetrics()` clears the registry. - `setUsePerformanceMetrics(enabled)` toggles the flag at runtime; `isUsingPerformanceMetrics()` reports state. - `getName()` returns `"least-busy"`. ## Usage: Basic Example ```ts import { LeastBusyStrategy } from "@suaveplan/queue-distribution/load-balancing/least-busy/least-busy"; const strategy = new LeastBusyStrategy(); // Pool of workers with mixed activeTasks; the one with the fewest wins. const selected = strategy.selectWorker(pool.getAvailableWorkers()); ``` ## Usage: Advanced Example Switch on performance bias when the pool contains a mix of fast and slow nodes (e.g. cross-region workers). The strategy will gradually steer load away from slower nodes. ```ts import { LeastBusyStrategy } from "@suaveplan/queue-distribution/load-balancing/least-busy/least-busy"; const strategy = new LeastBusyStrategy({ usePerformanceMetrics: true }); // As tasks complete, the worker manager feeds outcomes back. strategy.notifyTaskCompleted(workerA, task, true, 120); strategy.notifyTaskCompleted(workerB, task, true, 380); strategy.selectWorker([workerA, workerB]); // prefers A when activeTasks tied ``` ## API Reference - `class LeastBusyStrategy extends AbstractLoadBalancingStrategy`. - `constructor(options?: { usePerformanceMetrics?: boolean })`. - `selectWorker(workers, task?): Worker | null`. - `notifyTaskCompleted(worker, task, success, durationMs): void`. - `getWorkerPerformance(workerId): LeastBusyPerformanceRecord | null` — `{ totalExecutionTime, taskCount, avgExecutionTime }`. - `resetPerformanceMetrics(): void`. - `setUsePerformanceMetrics(enabled: boolean): void`. - `isUsingPerformanceMetrics(): boolean`. - `getName(): string` — returns `"least-busy"`. ## Implementation Notes Tie-break by `capacity` then `weight` (when no performance data is available) prefers larger, more powerful workers — so a freshly added high-capacity worker absorbs additional load even if every worker currently has zero in-flight tasks. The performance map is per-worker keyed by id and persists across pool changes; removing and re-adding a worker with the same id continues the rolling average. If that behaviour is undesirable, call `resetPerformanceMetrics()` after `pool.removeWorker`.