first commit
This commit is contained in:
129
docs/foundation/flow/queue-distribution/README.md
Normal file
129
docs/foundation/flow/queue-distribution/README.md
Normal file
@@ -0,0 +1,129 @@
|
||||
# @suaveplan/queue-distribution - Worker-pool distribution layer: load-balancing strategies (round-robin / least-busy / weighted), worker pool, manager with retry + health checks, in-process LocalWorker. Transport-agnostic — HTTP and worker-thread plugins ship as separate packages.
|
||||
|
||||
## Summary
|
||||
|
||||
Worker-pool distribution layer: load-balancing strategies, worker pool management, manager with retry and health checks, in-process `LocalWorker`. Transport-agnostic — HTTP and worker-thread transports ship as separate plugin packages (`@suaveplan/queue-distribution-http`, `@suaveplan/queue-distribution-worker-thread`).
|
||||
|
||||
The package is decoupled from `@suaveplan/queue`'s `Job` model: distribution operates on a minimal `DistributedTask<I, O>` contract so it can serve any consumer that produces typed work units (queue, batch, RPC, agent dispatch).
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
## Documentation tree
|
||||
|
||||
- [errors](./src/errors/queue-distribution-error.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [queue-distribution-error](./src/errors/queue-distribution-error.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [health-checker](./src/health-checker/health-checker.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [health-checker](./src/health-checker/health-checker.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [internal](./src/internal/noop-logger.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [noop-logger](./src/internal/noop-logger.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [base](./src/load-balancing/base/base.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [base](./src/load-balancing/base/base.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [least-busy](./src/load-balancing/least-busy/least-busy.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [least-busy](./src/load-balancing/least-busy/least-busy.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [round-robin](./src/load-balancing/round-robin/round-robin.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [round-robin](./src/load-balancing/round-robin/round-robin.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [weighted](./src/load-balancing/weighted/weighted.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [weighted](./src/load-balancing/weighted/weighted.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [manager](./src/manager/manager.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [manager-dispatch](./src/manager/manager-dispatch.md) — `dispatchWithRetry` is the core retry loop of `WorkerManager`. It picks a worker via the configured `LoadBalancingStrat…
|
||||
- [manager-supervisor](./src/manager/manager-supervisor.md) — The supervisor module owns the worker-health side of `WorkerManager`: periodic health checks across the pool, restart o…
|
||||
- [manager](./src/manager/manager.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [observability](./src/observability/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [instruments](./src/observability/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [pool](./src/pool/pool.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [pool](./src/pool/pool.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [task](./src/task/task.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [task](./src/task/task.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [worker](./src/worker/worker.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->- abstract-metrics — `abstract-metrics.ts` carries the…
|
||||
- [abstract](./src/worker/abstract/abstract.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [abstract-metrics](./src/worker/abstract/abstract-metrics.md) — `abstract-metrics.ts` carries the pure functions and the small accumulator used by `AbstractWorker` to track success/fa…
|
||||
- [abstract](./src/worker/abstract/abstract.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [local](./src/worker/local/local.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [local](./src/worker/local/local.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [worker](./src/worker/worker.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->- abstract-metrics — `abstract-metrics.ts` carries the…
|
||||
<!-- end:auto-docs --> - [queue-distribution-error](./src/errors/queue-distribution-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [health-checker](./src/health-checker/health-checker.md) — <!-- begin:auto-docs --> _(no submodules)_- [health-checker](./src/health-checker/health-checker.md) — <!-- begin:auto-docs --> _(no submodules)_- [internal](./src/internal/noop-logger.md) — <!-- begin:auto-docs --> _(no submodules)_- [noop-logger](./src/internal/noop-logger.md) — <!-- begin:auto-docs --> _(no submodules)_- [base](./src/load-balancing/base/base.md) — <!-- begin:auto-docs --> _(no submodules)_- [base](./src/load-balancing/base/base.md) — <!-- begin:auto-docs --> _(no submodules)_- [least-busy](./src/load-balancing/least-busy/least-busy.md) — <!-- begin:auto-docs --> _(no submodules)_- [least-busy](./src/load-balancing/least-busy/least-busy.md) — <!-- begin:auto-docs --> _(no submodules)_- [round-robin](./src/load-balancing/round-robin/round-robin.md) — <!-- begin:auto-docs --> _(no submodules)_- [round-robin](./src/load-balancing/round-robin/round-robin.md) — <!-- begin:auto-docs --> _(no submodules)_- [weighted](./src/load-balancing/weighted/weighted.md) — <!-- begin:auto-docs --> _(no submodules)_- [weighted](./src/load-balancing/weighted/weighted.md) — <!-- begin:auto-docs --> _(no submodules)_- [manager](./src/manager/manager.md) — <!-- begin:auto-docs --> _(no submodules)_- [manager-dispatch](./src/manager/manager-dispatch.md) — `dispatchWithRetry` is the core retry loop of `WorkerManager`. It picks a worker via the configured `LoadBalancingStrat…
|
||||
- [manager-supervisor](./src/manager/manager-supervisor.md) — The supervisor module owns the worker-health side of `WorkerManager`: periodic health checks across the pool, restart o…
|
||||
- [manager](./src/manager/manager.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_- [instruments](./src/observability/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_- [pool](./src/pool/pool.md) — <!-- begin:auto-docs --> _(no submodules)_- [pool](./src/pool/pool.md) — <!-- begin:auto-docs --> _(no submodules)_- [task](./src/task/task.md) — <!-- begin:auto-docs --> _(no submodules)_- [task](./src/task/task.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker](./src/worker/worker.md) — <!-- begin:auto-docs --> _(no submodules)_- [abstract](./src/worker/abstract/abstract.md) — <!-- begin:auto-docs --> _(no submodules)_- [abstract-metrics](./src/worker/abstract/abstract-metrics.md) — `abstract-metrics.ts` carries the pure functions and the small accumulator used by `AbstractWorker` to track success/fa…
|
||||
- [abstract](./src/worker/abstract/abstract.md) — <!-- begin:auto-docs --> _(no submodules)_- [local](./src/worker/local/local.md) — <!-- begin:auto-docs --> _(no submodules)_- [local](./src/worker/local/local.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker](./src/worker/worker.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue-distribution-error](./src/errors/queue-distribution-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [health-checker](./src/health-checker/health-checker.md) — <!-- begin:auto-docs --> _(no submodules)_- [health-checker](./src/health-checker/health-checker.md) — <!-- begin:auto-docs --> _(no submodules)_- [internal](./src/internal/noop-logger.md) — <!-- begin:auto-docs --> _(no submodules)_- [noop-logger](./src/internal/noop-logger.md) — <!-- begin:auto-docs --> _(no submodules)_- [base](./src/load-balancing/base/base.md) — <!-- begin:auto-docs --> _(no submodules)_- [base](./src/load-balancing/base/base.md) — <!-- begin:auto-docs --> _(no submodules)_- [least-busy](./src/load-balancing/least-busy/least-busy.md) — <!-- begin:auto-docs --> _(no submodules)_- [least-busy](./src/load-balancing/least-busy/least-busy.md) — <!-- begin:auto-docs --> _(no submodules)_- [round-robin](./src/load-balancing/round-robin/round-robin.md) — <!-- begin:auto-docs --> _(no submodules)_- [round-robin](./src/load-balancing/round-robin/round-robin.md) — <!-- begin:auto-docs --> _(no submodules)_- [weighted](./src/load-balancing/weighted/weighted.md) — <!-- begin:auto-docs --> _(no submodules)_- [weighted](./src/load-balancing/weighted/weighted.md) — <!-- begin:auto-docs --> _(no submodules)_- [manager](./src/manager/manager.md) — <!-- begin:auto-docs --> _(no submodules)_- [manager-dispatch](./src/manager/manager-dispatch.md) — `dispatchWithRetry` is the core retry loop of `WorkerManager`. It picks a worker via the configured `LoadBalancingStrat…
|
||||
- [manager-supervisor](./src/manager/manager-supervisor.md) — The supervisor module owns the worker-health side of `WorkerManager`: periodic health checks across the pool, restart o…
|
||||
- [manager](./src/manager/manager.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_- [instruments](./src/observability/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_- [pool](./src/pool/pool.md) — <!-- begin:auto-docs --> _(no submodules)_- [pool](./src/pool/pool.md) — <!-- begin:auto-docs --> _(no submodules)_- [task](./src/task/task.md) — <!-- begin:auto-docs --> _(no submodules)_- [task](./src/task/task.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker](./src/worker/worker.md) — <!-- begin:auto-docs --> _(no submodules)_- abstract-metrics — `abstract…
|
||||
- [abstract](./src/worker/abstract/abstract.md) — <!-- begin:auto-docs --> _(no submodules)_- [abstract-metrics](./src/worker/abstract/abstract-metrics.md) — `abstract-metrics.ts` carries the pure functions and the small accumulator used by `AbstractWorker` to track success/fa…
|
||||
- [abstract](./src/worker/abstract/abstract.md) — <!-- begin:auto-docs --> _(no submodules)_- [local](./src/worker/local/local.md) — <!-- begin:auto-docs --> _(no submodules)_- [local](./src/worker/local/local.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker](./src/worker/worker.md) — <!-- begin:auto-docs --> _(no submodules)_- abstract-metrics — `abstract…
|
||||
- [queue-distribution-error](./src/errors/queue-distribution-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [health-checker](./src/health-checker/health-checker.md) — <!-- begin:auto-docs --> _(no submodules)_- [health-checker](./src/health-checker/health-checker.md) — <!-- begin:auto-docs --> _(no submodules)_- [internal](./src/internal/noop-logger.md) — <!-- begin:auto-docs --> _(no submodules)_- [noop-logger](./src/internal/noop-logger.md) — <!-- begin:auto-docs --> _(no submodules)_- [base](./src/load-balancing/base/base.md) — <!-- begin:auto-docs --> _(no submodules)_- [base](./src/load-balancing/base/base.md) — <!-- begin:auto-docs --> _(no submodules)_- [least-busy](./src/load-balancing/least-busy/least-busy.md) — <!-- begin:auto-docs --> _(no submodules)_- [least-busy](./src/load-balancing/least-busy/least-busy.md) — <!-- begin:auto-docs --> _(no submodules)_- [round-robin](./src/load-balancing/round-robin/round-robin.md) — <!-- begin:auto-docs --> _(no submodules)_- [round-robin](./src/load-balancing/round-robin/round-robin.md) — <!-- begin:auto-docs --> _(no submodules)_- [weighted](./src/load-balancing/weighted/weighted.md) — <!-- begin:auto-docs --> _(no submodules)_- [weighted](./src/load-balancing/weighted/weighted.md) — <!-- begin:auto-docs --> _(no submodules)_- [manager](./src/manager/manager.md) — <!-- begin:auto-docs --> _(no submodules)_- [manager-dispatch](./src/manager/manager-dispatch.md) — `dispatchWithRetry` is the core retry loop of `WorkerManager`. It picks a worker via the configured `LoadBalancingStrat…
|
||||
- [manager-supervisor](./src/manager/manager-supervisor.md) — The supervisor module owns the worker-health side of `WorkerManager`: periodic health checks across the pool, restart o…
|
||||
- [manager](./src/manager/manager.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_- [instruments](./src/observability/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_- [pool](./src/pool/pool.md) — <!-- begin:auto-docs --> _(no submodules)_- [pool](./src/pool/pool.md) — <!-- begin:auto-docs --> _(no submodules)_- [task](./src/task/task.md) — <!-- begin:auto-docs --> _(no submodules)_- [task](./src/task/task.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker](./src/worker/worker.md) — <!-- begin:auto-docs --> _(no submodules)_- abstract-metrics — `abstract-metrics.ts` carries th…
|
||||
- [abstract](./src/worker/abstract/abstract.md) — <!-- begin:auto-docs --> _(no submodules)_- [abstract-metrics](./src/worker/abstract/abstract-metrics.md) — `abstract-metrics.ts` carries the pure functions and the small accumulator used by `AbstractWorker` to track success/fa…
|
||||
- [abstract](./src/worker/abstract/abstract.md) — <!-- begin:auto-docs --> _(no submodules)_- [local](./src/worker/local/local.md) — <!-- begin:auto-docs --> _(no submodules)_- [local](./src/worker/local/local.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker](./src/worker/worker.md) — <!-- begin:auto-docs --> _(no submodules)_- abstract-metrics — `abstract-metrics.ts` carries th…
|
||||
- [queue-distribution-error](./src/errors/queue-distribution-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [health-checker](./src/health-checker/health-checker.md) — <!-- begin:auto-docs --> _(no submodules)_ - [health-checker](./src/health-checker/health-checker.md) — <!-- begin:auto-docs --> _(no submodules)_- [internal](./src/internal/noop-logger.md) — <!-- begin:auto-docs --> _(no submodules)_ - [noop-logger](./src/internal/noop-logger.md) — <!-- begin:auto-docs --> _(no submodules)_- [base](./src/load-balancing/base/base.md) — <!-- begin:auto-docs --> _(no submodules)_ - [base](./src/load-balancing/base/base.md) — <!-- begin:auto-docs --> _(no submodules)_- [least-busy](./src/load-balancing/least-busy/least-busy.md) — <!-- begin:auto-docs --> _(no submodules)_ - [least-busy](./src/load-balancing/least-busy/least-busy.md) — <!-- begin:auto-docs --> _(no submodules)_- [round-robin](./src/load-balancing/round-robin/round-robin.md) — <!-- begin:auto-docs --> _(no submodules)_ - [round-robin](./src/load-balancing/round-robin/round-robin.md) — <!-- begin:auto-docs --> _(no submodules)_- [weighted](./src/load-balancing/weighted/weighted.md) — <!-- begin:auto-docs --> _(no submodules)_ - [weighted](./src/load-balancing/weighted/weighted.md) — <!-- begin:auto-docs --> _(no submodules)_- [manager](./src/manager/manager.md) — <!-- begin:auto-docs --> _(no submodules)_ - [manager-dispatch](./src/manager/manager-dispatch.md) — `dispatchWithRetry` is the core retry loop of `WorkerManager`. It picks a worker via the configured `LoadBalancingStrat…
|
||||
- [manager-supervisor](./src/manager/manager-supervisor.md) — The supervisor module owns the worker-health side of `WorkerManager`: periodic health checks across the pool, restart o…
|
||||
- [manager](./src/manager/manager.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_ - [instruments](./src/observability/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_- [pool](./src/pool/pool.md) — <!-- begin:auto-docs --> _(no submodules)_ - [pool](./src/pool/pool.md) — <!-- begin:auto-docs --> _(no submodules)_- [task](./src/task/task.md) — <!-- begin:auto-docs --> _(no submodules)_ - [task](./src/task/task.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker](./src/worker/worker.md) — <!-- begin:auto-docs --> _(no submodules)_ - [abstract](./src/worker/abstract/abstract.md) — <!-- begin:auto-docs --> _(no submodules)_ - [abstract-metrics](./src/worker/abstract/abstract-metrics.md) — `abstract-metrics.ts` carries the pure functions and the small accumulator used by `AbstractWorker` to track success/fa…
|
||||
- [abstract](./src/worker/abstract/abstract.md) — <!-- begin:auto-docs --> _(no submodules)_ - [local](./src/worker/local/local.md) — <!-- begin:auto-docs --> _(no submodules)_ - [local](./src/worker/local/local.md) — <!-- begin:auto-docs --> _(no submodules)_ - [worker](./src/worker/worker.md) — <!-- begin:auto-docs --> _(no submodules)_
|
||||
## Install
|
||||
|
||||
```bash
|
||||
bun add @suaveplan/queue-distribution
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
```ts
|
||||
import {
|
||||
LocalWorker,
|
||||
WorkerManager,
|
||||
WorkerPool,
|
||||
} from "@suaveplan/queue-distribution";
|
||||
|
||||
const pool = new WorkerPool();
|
||||
pool.addWorker(new LocalWorker({}, { id: "a", capacity: 4 }));
|
||||
pool.addWorker(new LocalWorker({}, { id: "b", capacity: 4 }));
|
||||
await pool.startAllWorkers();
|
||||
|
||||
const manager = new WorkerManager(pool, {
|
||||
autoHealthCheck: false,
|
||||
maxTaskRetries: 2,
|
||||
});
|
||||
|
||||
const task = {
|
||||
id: "double",
|
||||
execute: async (n: number) => n * 2,
|
||||
getStatus: () => "PENDING" as const,
|
||||
setStatus: () => {},
|
||||
getMetadata: () => ({ createdAt: new Date(), attempts: 0 }),
|
||||
};
|
||||
|
||||
console.log(await manager.assignTask(task, 21)); // 42
|
||||
```
|
||||
|
||||
## Modules
|
||||
|
||||
- [Task contract](./src/task/task.md) — `DistributedTask<I, O>`, `TaskStatus`, `TaskMetadata`.
|
||||
- [Worker contract](./src/worker/worker.md) — `Worker`, `WorkerStatus`, `WorkerHealth`, `WorkerInfo` + Zod schemas.
|
||||
- [AbstractWorker](./src/worker/abstract/abstract.md) — base class with lifecycle FSM, metrics, OTel emission.
|
||||
- [`AbstractWorker` metrics helpers](./src/worker/abstract/abstract-metrics.md) — `WorkerMetricsState` accumulator.
|
||||
- [LocalWorker](./src/worker/local/local.md) — in-process executor.
|
||||
- [Strategy base](./src/load-balancing/base/base.md) — `LoadBalancingStrategy`, `AbstractLoadBalancingStrategy`.
|
||||
- [RoundRobinStrategy](./src/load-balancing/round-robin/round-robin.md).
|
||||
- [LeastBusyStrategy](./src/load-balancing/least-busy/least-busy.md) — optional EWMA performance bias.
|
||||
- [WeightedStrategy](./src/load-balancing/weighted/weighted.md) — injectable `Rng`.
|
||||
- [PeriodicHealthChecker](./src/health-checker/health-checker.md) — thresholds + cache + timeout.
|
||||
- [WorkerPool](./src/pool/pool.md) — CRUD + criteria-based search.
|
||||
- [WorkerManager](./src/manager/manager.md) — public dispatch surface.
|
||||
- [WorkerManager dispatch](./src/manager/manager-dispatch.md) — bounded retry loop with @suaveplan/retry.
|
||||
- [WorkerManager supervisor](./src/manager/manager-supervisor.md) — health-loop and restart logic.
|
||||
- [Errors](./src/errors/queue-distribution-error.md) — `QueueDistributionError` + 12 stable codes.
|
||||
- [Observability](./src/observability/instruments.md) — every counter, histogram, span the package emits.
|
||||
- [Internal: NOOP_LOGGER](./src/internal/noop-logger.md).
|
||||
|
||||
## Design highlights
|
||||
|
||||
- 100% test coverage (statements + branches + functions + lines) under `provider: "istanbul"`.
|
||||
- Injectable `Clock`, `IdGenerator`, `Rng`, `LoggerLike` everywhere — no `Math.random` / `Date.now` / `uuid` at module scope.
|
||||
- `AbortSignal` threaded through every async public method.
|
||||
- Retry routed through `@suaveplan/retry`; bounded loop, no recursion.
|
||||
- Zod schemas at every public boundary (`WorkerHealthSchema`, `WorkerInfoSchema`, `TaskMetadataSchema`, …).
|
||||
- Structured `SuaveplanError` subclasses with a frozen stable-code registry.
|
||||
- Tree-shakeable via 15 per-feature subpath exports.
|
||||
|
||||
## Status
|
||||
|
||||
This package is part of the rebuild — version `0.1.0` while it stabilises. Graduation to `1.0.0` follows the criteria in [`CLAUDE.md`](../../../CLAUDE.md).
|
||||
|
||||
Reference in New Issue
Block a user