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,91 @@
# `WorkerManager`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`WorkerManager` is the public entry point for distributing tasks across a `WorkerPool`. It owns task assignment (load-balancing, retry, dead-letter), supervision (periodic health checks, auto-restart of unhealthy workers), and option lifecycle (configurable at construction and at runtime via `updateOptions`). Implementation details — the retry-with-backoff loop and the supervisor — live in `manager-dispatch.ts` and `manager-supervisor.ts` so this file stays focused on the surface contract.
## Features
- `assignTask<I, O>(task, input, signal?): Promise<O>` — pick a worker, execute, retry up to `maxTaskRetries`, record dead-letter on exhaustion.
- `assignTasks<I, O>(tasks[], inputs[], signal?)` — fan-out wrapper over `assignTask`.
- Auto health-check loop driven by `setInterval` over `healthCheckIntervalMs`; toggleable at runtime.
- Auto-restart of `UNHEALTHY` workers up to `maxWorkerRestarts`.
- `failedTasks` Set and per-task retry counter for observability.
- Injectable `LoadBalancingStrategy` (default `RoundRobinStrategy`), `WorkerHealthChecker` (default `PeriodicHealthChecker`), `Clock`, `LoggerLike`.
- AbortSignal threaded through every public async method.
- Throws `InvalidOptionsError` for negative numeric options at construction and on `updateOptions`.
## Usage: Basic Example
```ts
import { WorkerManager } from "@suaveplan/queue-distribution/manager/manager";
import { WorkerPool } from "@suaveplan/queue-distribution/pool/pool";
import { LocalWorker } from "@suaveplan/queue-distribution/worker/local/local";
const pool = new WorkerPool();
pool.addWorker(new LocalWorker({}, { id: "a" }));
const manager = new WorkerManager(pool, {
autoHealthCheck: false,
maxTaskRetries: 2,
});
const result = await manager.assignTask(task, input);
```
## Usage: Advanced Example
Stand up a production-shaped manager with a least-busy strategy, performance bias, a custom health checker, and a deterministic clock for tests.
```ts
import { WorkerManager } from "@suaveplan/queue-distribution/manager/manager";
import { WorkerPool } from "@suaveplan/queue-distribution/pool/pool";
import { LeastBusyStrategy } from "@suaveplan/queue-distribution/load-balancing/least-busy/least-busy";
import { PeriodicHealthChecker } from "@suaveplan/queue-distribution/health-checker/health-checker";
const clock = (): number => Date.now();
const pool = new WorkerPool();
// ... add workers ...
const manager = new WorkerManager(
pool,
{
balancer: new LeastBusyStrategy({ usePerformanceMetrics: true }),
healthChecker: new PeriodicHealthChecker({ unhealthyThreshold: 3 }),
autoHealthCheck: true,
healthCheckIntervalMs: 10_000,
maxTaskRetries: 5,
taskRetryDelayMs: 250,
autoRestartUnhealthy: true,
maxWorkerRestarts: 5,
minOnlineWorkers: 2,
},
{ clock, logger: console as never },
);
const ctrl = new AbortController();
setTimeout(() => ctrl.abort(), 30_000); // hard ceiling
await manager.assignTasks(tasks, inputs, ctrl.signal);
```
## API Reference
- `interface WorkerManagerOptions` — `healthCheckIntervalMs?`, `autoHealthCheck?`, `taskRetryDelayMs?`, `maxTaskRetries?`, `autoRestartUnhealthy?`, `maxWorkerRestarts?`, `minOnlineWorkers?`.
- `interface WorkerManagerDeps` — `clock?`, `logger?`.
- `class WorkerManager`.
- `constructor(pool, options?: { balancer?, healthChecker?, ...WorkerManagerOptions }, deps?: WorkerManagerDeps)`.
- `assignTask<I, O>(task, input, signal?): Promise<O>`.
- `assignTasks<I, O>(tasks[], inputs[], signal?): Promise<O[]>`.
- `startHealthChecks(): void`, `stopHealthChecks(): void`.
- `checkAllWorkersHealth(signal?): Promise<Map<string, WorkerHealth>>`.
- `handleWorkerFailure(worker, error): Promise<void>`.
- `getWorkerPool(): WorkerPool`, `getLoadBalancer(): LoadBalancingStrategy`, `setLoadBalancer(b): void`, `getHealthChecker(): WorkerHealthChecker`.
- `getFailedTasks(): ReadonlySet<DistributedTask>`, `clearFailedTasks(): void`.
- `getTaskRetries(taskId): number`.
- `getOptions(): Required<WorkerManagerOptions>`, `updateOptions(partial): void`.
## Implementation Notes
`updateOptions` performs validate-then-apply: a negative `maxTaskRetries` is rejected before any mutation, so the manager remains in a consistent state across failed updates. Toggling `autoHealthCheck` mid-run actually starts or stops the interval — passing the same value as the current state is a no-op, which lets callers idempotently bounce settings without disrupting an active loop. The dispatch and supervisor configs are recreated on each call to `assignTask` / `checkAllWorkersHealth` so changes via `setLoadBalancer` are picked up immediately without rebuilding the manager.