first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
# `LeastBusyStrategy`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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`.