Files
suaveplan/openspec/archive/2026-05-25-enterprise-web-workers/proposal.md
2026-05-27 23:29:53 +01:00

68 lines
4.0 KiB
Markdown

# Proposal: Enterprise migration of `@suaveplan/web-workers`
- **Status**: PROPOSED
- **Package**: `@suaveplan/web-workers`
- **Tier**: browser
- **Category / plugin**: `foundation / data`
- **Source**: upstream `packages/browser/web-workers` (1.0.6)
- **Design**: ./design.md
- **Spec delta**: ./specs/web-workers/spec.md
## Summary
Migrate `@suaveplan/web-workers` from `../suaveplan/packages/browser/web-workers` (1.0.6) to
genesis at `packages/foundation/data/web-workers/` as version `0.1.0`. The upstream package
only manages classic `Worker` instances and exposes a `WorkerPoolConfig` type with no runtime
counterpart; the package name advertises SharedWorker support that does not exist. The genesis
rewrite ships the full contract called out in `enterprise/web-workers.md`:
- `BaseWorkerManager` + `WorkerManager` (classic) + `SharedWorkerManager` (port-per-client).
- `WorkerPool` (FIFO queue, round-robin and least-busy schedulers, min/max idle, health
checks, restart-on-crash supervision, backpressure).
- Typed RPC with `AbortSignal` cancellation, transfer-list support, backpressure ceiling,
circuit breaker, and streaming RPC (`sendStream`).
- `@suaveplan/events` `EventBus`-based lifecycle emission for both managers and the bus.
- OTel counters + histograms for workers active, restart count, RPC latency, and message
rate.
- Typed errors via `@suaveplan/error` under the `WEB_WORKERS.*` namespace.
- `defineWorker()` helper for the `new URL('./worker.ts', import.meta.url)` pattern.
## Parity Checklist
| Capability | Upstream | Migrated | Notes |
|---|---|---|---|
| `WorkerManager` (create/terminate/has/getStatus/getWorkerNames/onError) | ✅ | ✅ | Refactored to extend `BaseWorkerManager`. |
| `WorkerManager.postMessage` / `sendRequest` | ✅ | ✅ | Plus `signal?: AbortSignal` and `transfer?: Transferable[]`. |
| Pending-request map with timeout / id correlation | ✅ | ✅ | Plus `maxPendingRequests` backpressure ceiling. |
| `terminate` rejects pending requests | ✅ | ✅ | Error code `WEB_WORKERS.WORKER_TERMINATED`. |
| `MessageBus` pub/sub + once + broadcast | ✅ | ✅ | Same surface, typed payloads. |
| `MessageBus.registerHandler` + `request` | ✅ | ✅ | Plus `signal` + timeout enforcement (upstream ignored timeout). |
| `MessageBus.subscriberCount` + `getTopics` + `clear` | ✅ | ✅ | |
| `WorkerFactory` injectable for tests | ✅ | ✅ | Plus `SharedWorkerFactory`. |
| `WorkerManagerEventMap` / `MessageBusEventMap` | ✅ | ✅ | Reshaped from variadic listener args to single-payload events for genesis `EventBus`. |
| Event emission at runtime | 🚫 partial | ✅ | Upstream wired into `@suaveplan/events` `EventEmitter`; genesis re-wires onto `EventBus<TMap>`. |
| `SharedWorker` support | 🚫 | ✅ | Enhancement called out in `enterprise/web-workers.md`. |
| `WorkerPool` runtime | 🚫 | ✅ | Enhancement; round-robin + least-busy schedulers, FIFO queue, min/max idle, health probe. |
| `AbortSignal` on `sendRequest` / `MessageBus.request` | 🚫 | ✅ | Enhancement. |
| Transfer-list (`{ transfer: Transferable[] }`) | 🚫 | ✅ | Enhancement. |
| Streaming RPC (`sendStream` → `AsyncIterable`) | 🚫 | ✅ | Enhancement. |
| Circuit breaker on `sendRequest` | 🚫 | ✅ | Enhancement. |
| Structured worker errors via `@suaveplan/error` | 🚫 | ✅ | `WEB_WORKERS.*` registry. |
| OTel counters / histograms | 🚫 | ✅ | Enhancement. |
| `defineWorker()` Vite helper | 🚫 | ✅ | Enhancement. |
| Restart-on-crash supervision | 🚫 | ✅ | Pool only. |
## Impact
### Affected dependents
No genesis consumer yet imports `@suaveplan/web-workers` — this is a fresh land. The package
takes a single internal runtime dep on `@suaveplan/events` (already shipped). Downstream
adoption (drive, audio-engine-browser, packer-browser) is out of scope for this change.
## Out of scope
- Node.js `worker_threads` adapter — different tier, separate package.
- React hooks — covered by a follow-up `@suaveplan/react-web-workers` if/when needed.
- Vite plugin wiring — `defineWorker()` is the helper; no plugin authorship in this change.