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

4.0 KiB

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.