Files
skills/docs/foundation/flow/queue-distribution/src/load-balancing/least-busy/least-busy.md
2026-05-29 08:20:56 +01:00

3.1 KiB

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

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.

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.