updated skills

This commit is contained in:
2026-06-09 21:06:27 +01:00
parent db1ce43ee1
commit 427a5bd919
1283 changed files with 24684 additions and 2313 deletions

View File

@@ -56,10 +56,12 @@ browser. Zero browser/Node deps.
- [builtin](./src/tags/builtin.md) — Provides `defaultTagHandlers()`, a `TagRegistry` populated with handlers for the most-used IANA-registered CBOR tags. C…
- [registry](./src/tags/registry.md) — `TagRegistry` is the in-memory mutable container for CBOR tag handlers. The decoder consults a snapshot of the registry…
- [tagged](./src/tags/tagged.md) — Provides the `Tagged<T>` value object used by `@suaveplan/cbor` to materialise RFC 8949 §3.4 tagged items. The decoder…
<!-- end:auto-docs --> - half-float — Decodes 2 big-endian bytes representin…
- [decoder](./src/decoder/decoder.md) — <!-- begin:auto-docs --> _(no submodules)_- half-float — Decodes 2 big-endian bytes representin…
- [half-float](./src/decoder/half-float.md) — Decodes 2 big-endian bytes representing IEEE 754 binary16 to a JavaScript `number`. The decoder is always available — n…
- [well-formed](./src/decoder/well-formed.md) — `isWellFormed(bytes)` returns `true` iff `bytes` represent a single well-formed CBOR item per RFC 8949 §5.1. The functi…
- [decoder](./src/decoder/decoder.md) — <!-- begin:auto-docs --> _(no submodules)_- half-float — Decodes 2 big-endian bytes representin…
- [half-float](./src/decoder/half-float.md) — Decodes 2 big-endian bytes representing IEEE 754 binary16 to a JavaScript `number`. The decoder is always available — n…
- [well-formed](./src/decoder/well-formed.md) — `isWellFormed(bytes)` returns `true` iff `bytes` represent a single well-formed CBOR item per RFC 8949 §5.1. The functi…
- [deterministic](./src/deterministic/deterministic.md) — <!-- begin:auto-docs --> _(no submodules)_- [deterministic](./src/deterministic/deterministic.md) — <!-- begin:auto-docs --> _(no submodules)_- [diagnostic](./src/diagnostic/diagnostic.md) — <!-- begin:auto-docs --> _(no submodules)_- [diagnostic](./src/diagnostic/diagnostic.md) — <!-- begin:auto-docs --> _(no submodules)_- [encoder](./src/encoder/encoder.md) — <!-- begin:auto-docs --> _(no submodules)_- half-float — Encodes a JavaScript `number` as IEEE……
- [encoder](./src/encoder/encoder.md) — <!-- begin:auto-docs --> _(no submodules)_- half-float — Encodes a JavaScript `number` as IEEE……
- [half-float](./src/encoder/half-float.md) — Encodes a JavaScript `number` as IEEE 754 binary16 (CBOR major 7 / value 25) when the round-trip is exact, and otherwis…
@@ -180,4 +182,3 @@ const value = decode(bytes);
- RFC 8949 §5.1 — strict-mode well-formedness; every malformed-input class
raises `CborError(MALFORMED)`
- RFC 8742 §2 + §3 — CBOR Sequences encode + decode + async-iterator stream

View File

@@ -3,6 +3,7 @@
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs --> - half-float — Decodes 2 big-endian bytes representin…
- [half-float](./half-float.md) — Decodes 2 big-endian bytes representing IEEE 754 binary16 to a JavaScript `number`. The decoder is always available — n…
- [well-formed](./well-formed.md) — `isWellFormed(bytes)` returns `true` iff `bytes` represent a single well-formed CBOR item per RFC 8949 §5.1. The functi…
- half-float — Decodes 2 big-endian bytes representin…

View File

@@ -3,6 +3,7 @@
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs --> - half-float — Encodes a JavaScript `number` as IEEE……
- [half-float](./half-float.md) — Encodes a JavaScript `number` as IEEE 754 binary16 (CBOR major 7 / value 25) when the round-trip is exact, and otherwis…
- half-float — Encodes a JavaScript `number` as IEEE……

File diff suppressed because one or more lines are too long

View File

@@ -13,7 +13,9 @@ Typed, generic finite state machine (FSM) for TypeScript. Ships a synchronous-by
- [fsm-error](./src/errors/fsm-error.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [context-helpers](./src/utils/context-helpers.md) — Provides ergonomic factory helpers for building context-update and side-effect actions that can be slotted directly int…
- [definition-validator](./src/utils/definition-validator.md) — Validates an `FSMDefinition` object before the interpreter begins executing. Early structural validation prevents subtl…
<!-- end:auto-docs --> - [fsm-interpreter](./src/core/interpreter/fsm-interpreter.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/fsm-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [fsm-error](./src/errors/fsm-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [context-helpers](./src/utils/context-helpers.md) — Provides ergonomic factory helpers for building context-update and side-effect actions that can be slotted directly int…
- [definition-validator](./src/utils/definition-validator.md) — Validates an `FSMDefinition` object before the interpreter begins executing. Early structural validation prevents subtl…
- [fsm-interpreter](./src/core/interpreter/fsm-interpreter.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/fsm-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [fsm-error](./src/errors/fsm-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [context-helpers](./src/utils/context-helpers.md) — Provides ergonomic factory helpers for building context-update and side-effect actions that can be slotted directly int…
- [definition-validator](./src/utils/definition-validator.md) — Validates an `FSMDefinition` object before the interpreter begins executing. Early structural validation prevents subtl…

View File

@@ -26,7 +26,9 @@ Idempotency key guard and deduplication for async operations. The package provid
- [redis-store](./src/store/redis-store.md) — Provides a Redis-backed `IdempotencyStoreAdapter<T>` with automatic key expiration using Redis native TTL. By accepting…
- [versioning](./src/versioning/key-versioning.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [key-versioning](./src/versioning/key-versioning.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
<!-- end:auto-docs --> - [idempotency-error](./src/errors/idempotency-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [guard](./src/guard/idempotency-guard.md) — <!-- begin:auto-docs --> _(no submodules)_- [idempotency-guard](./src/guard/idempotency-guard.md) — <!-- begin:auto-docs --> _(no submodules)_- [key](./src/key/key-generator.md) — <!-- begin:auto-docs --> _(no submodules)_- [key-generator](./src/key/key-generator.md) — <!-- begin:auto-docs --> _(no submodules)_- [metrics](./src/metrics/idempotency-metrics.md) — <!-- begin:auto-docs --> _(no submodules)_- [idempotency-metrics](./src/metrics/idempotency-metrics.md) — <!-- begin:auto-docs --> _(no submodules)_- [middleware](./src/middleware/idempotency-middleware.md) — <!-- begin:auto-docs --> _(no submodules)_- [idempotency-middleware](./src/middleware/idempotency-middleware.md) — <!-- begin:auto-docs --> _(no submodules)_- [database-store](./src/store/database-store.md) — Provides a persistent `IdempotencyStoreAdapter<T>` backed by any relational database via the `IdempotencyDatabaseAdapte…
- [memory-store](./src/store/memory-store.md) — Provides an in-memory implementation of `IdempotencyStoreAdapter<T>` backed by a `Map`. It is the default store for uni…
- [redis-store](./src/store/redis-store.md) — Provides a Redis-backed `IdempotencyStoreAdapter<T>` with automatic key expiration using Redis native TTL. By accepting…
- [versioning](./src/versioning/key-versioning.md) — <!-- begin:auto-docs --> _(no submodules)_- [key-versioning](./src/versioning/key-versioning.md) — <!-- begin:auto-docs --> _(no submodules)_- [error-codes](./src/error-codes.md) — Defines and registers all stable error codes and their HTTP/retry metadata for the `@suaveplan/idempotency` package. Ev…
@@ -92,4 +94,3 @@ const safe = await guard.execute(
| [src/versioning/key-versioning.md](src/versioning/key-versioning.md) | `KeyVersioning` — multi-version record management with `reject`, `overwrite`, and `version` conflict strategies |
| [src/errors/idempotency-error.md](src/errors/idempotency-error.md) | Structured error hierarchy: `IdempotencyConflictError`, `IdempotencyMismatchError`, `LockAcquisitionError`, `VersionConflictError` |
| [src/error-codes.md](src/error-codes.md) | Stable `IDEMPOTENCY.*` error code registry |

View File

@@ -20,10 +20,12 @@ Universal in-process job scheduler with cron + queued runs, retries, timeouts, c
- [registry](./src/registry/job-registry.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [job-registry](./src/registry/job-registry.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [cron-rescheduler](./src/scheduler/cron-rescheduler.md) — Houses the two cron-related decisions the scheduler makes after a job settles or resumes: (1) compute the next fire fro…
- [job-dispatcher](./src/scheduler/job-dispatcher.md) — Encapsulates the "hand a job to the executor" step of the scheduler's tick loop. The scheduler core decides *which* job…
- [job-dispatcher](./src/scheduler/job-dispatcher.md) — Encapsulates the "hand a job to the executor" step of the scheduler's tick loop. The scheduler core decides _which_ job…
- [job-scheduler](./src/scheduler/job-scheduler.md) — The `JobScheduler` class is the package's main entry point: it accepts both cron-scheduled and one-shot queued jobs, ru…
- [job-snapshot](./src/scheduler/job-snapshot.md) — Projects a mutable `ScheduledJob` record (the scheduler's internal data structure) to an immutable `JobStatus` snapshot…
<!-- end:auto-docs --> - [job-scheduler-error](./src/errors/job-scheduler-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [events](./src/events/events.md) — <!-- begin:auto-docs --> _(no submodules)_- [events](./src/events/events.md) — <!-- begin:auto-docs --> _(no submodules)_- [execution](./src/execution/job-execution.md) — <!-- begin:auto-docs --> _(no submodules)_- [job-execution](./src/execution/job-execution.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/job-scheduler-otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [job-scheduler-otel](./src/otel/job-scheduler-otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue](./src/queue/job-queue.md) — <!-- begin:auto-docs --> _(no submodules)_- [job-queue](./src/queue/job-queue.md) — <!-- begin:auto-docs --> _(no submodules)_- [registry](./src/registry/job-registry.md) — <!-- begin:auto-docs --> _(no submodules)_- [job-registry](./src/registry/job-registry.md) — <!-- begin:auto-docs --> _(no submodules)_- [cron-rescheduler](./src/scheduler/cron-rescheduler.md) — Houses the two cron-related decisions the scheduler makes after a job settles or resumes: (1) compute the next fire fro…
- [job-dispatcher](./src/scheduler/job-dispatcher.md) — Encapsulates the "hand a job to the executor" step of the scheduler's tick loop. The scheduler core decides _which_ job…
- [job-scheduler](./src/scheduler/job-scheduler.md) — The `JobScheduler` class is the package's main entry point: it accepts both cron-scheduled and one-shot queued jobs, ru…
- [job-snapshot](./src/scheduler/job-snapshot.md) — Projects a mutable `ScheduledJob` record (the scheduler's internal data structure) to an immutable `JobStatus` snapshot…

View File

@@ -19,7 +19,9 @@ The plugin lives separately from the core distribution package so browser-only a
- [instruments](./src/observability/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [remote](./src/worker/remote/remote.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [remote](./src/worker/remote/remote.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
<!-- end:auto-docs --> - [base](./src/communicator/base/base.md) — <!-- begin:auto-docs --> _(no submodules)_- [http](./src/communicator/http/http-communicator.md) — <!-- begin:auto-docs --> _(no submodules)_- [http-communicator](./src/communicator/http/http-communicator.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/queue-distribution-http-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue-distribution-http-error](./src/errors/queue-distribution-http-error.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)_- [remote](./src/worker/remote/remote.md) — <!-- begin:auto-docs --> _(no submodules)_- [remote](./src/worker/remote/remote.md) — <!-- begin:auto-docs --> _(no submodules)_- [base](./src/communicator/base/base.md) — <!-- begin:auto-docs --> _(no submodules)_- [http](./src/communicator/http/http-communicator.md) — <!-- begin:auto-docs --> _(no submodules)_- [http-communicator](./src/communicator/http/http-communicator.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/queue-distribution-http-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue-distribution-http-error](./src/errors/queue-distribution-http-error.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)_- [remote](./src/worker/remote/remote.md) — <!-- begin:auto-docs --> _(no submodules)_- [remote](./src/worker/remote/remote.md) — <!-- begin:auto-docs --> _(no submodules)_- [base](./src/communicator/base/base.md) — <!-- begin:auto-docs --> _(no submodules)_- [http](./src/communicator/http/http-communicator.md) — <!-- begin:auto-docs --> _(no submodules)_- [http-communicator](./src/communicator/http/http-communicator.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/queue-distribution-http-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue-distribution-http-error](./src/errors/queue-distribution-http-error.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)_- [remote](./src/worker/remote/remote.md) — <!-- begin:auto-docs --> _(no submodules)_- [remote](./src/worker/remote/remote.md) — <!-- begin:auto-docs --> _(no submodules)_- [base](./src/communicator/base/base.md) — <!-- begin:auto-docs --> _(no submodules)_- [http](./src/communicator/http/http-communicator.md) — <!-- begin:auto-docs --> _(no submodules)_ - [http-communicator](./src/communicator/http/http-communicator.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/queue-distribution-http-error.md) — <!-- begin:auto-docs --> _(no submodules)_ - [queue-distribution-http-error](./src/errors/queue-distribution-http-error.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)_- [remote](./src/worker/remote/remote.md) — <!-- begin:auto-docs --> _(no submodules)_ - [remote](./src/worker/remote/remote.md) — <!-- begin:auto-docs --> _(no submodules)_
## Install
```bash
@@ -72,4 +74,3 @@ const result = await manager.assignTask(task, input);
## Status
Part of the rebuild — version `0.1.0` while it stabilises.

View File

@@ -17,7 +17,9 @@ The plugin lives separately from the core distribution package so HTTP-only and
- [instruments](./src/observability/instruments.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [worker-thread](./src/worker/worker-thread/worker-thread-worker.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [worker-thread-worker](./src/worker/worker-thread/worker-thread-worker.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
<!-- end:auto-docs --> - [worker-thread-communicator](./src/communicator/worker-thread/worker-thread-communicator.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/queue-distribution-worker-thread-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue-distribution-worker-thread-error](./src/errors/queue-distribution-worker-thread-error.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)_- [worker-thread](./src/worker/worker-thread/worker-thread-worker.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker-thread-worker](./src/worker/worker-thread/worker-thread-worker.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker-thread-communicator](./src/communicator/worker-thread/worker-thread-communicator.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/queue-distribution-worker-thread-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue-distribution-worker-thread-error](./src/errors/queue-distribution-worker-thread-error.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)_- [worker-thread](./src/worker/worker-thread/worker-thread-worker.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker-thread-worker](./src/worker/worker-thread/worker-thread-worker.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker-thread-communicator](./src/communicator/worker-thread/worker-thread-communicator.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/queue-distribution-worker-thread-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue-distribution-worker-thread-error](./src/errors/queue-distribution-worker-thread-error.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)_- [worker-thread](./src/worker/worker-thread/worker-thread-worker.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker-thread-worker](./src/worker/worker-thread/worker-thread-worker.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker-thread-communicator](./src/communicator/worker-thread/worker-thread-communicator.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/queue-distribution-worker-thread-error.md) — <!-- begin:auto-docs --> _(no submodules)_ - [queue-distribution-worker-thread-error](./src/errors/queue-distribution-worker-thread-error.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)_- [worker-thread](./src/worker/worker-thread/worker-thread-worker.md) — <!-- begin:auto-docs --> _(no submodules)_ - [worker-thread-worker](./src/worker/worker-thread/worker-thread-worker.md) — <!-- begin:auto-docs --> _(no submodules)_
## Install
```bash
@@ -65,4 +67,3 @@ const result = await manager.assignTask(task, input);
## Status
Part of the rebuild — version `0.1.0` while it stabilises.

View File

@@ -40,14 +40,16 @@ The package is decoupled from `@suaveplan/queue`'s `Job` model: distribution ope
- [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…
- [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…
@@ -57,6 +59,7 @@ The package is decoupled from `@suaveplan/queue`'s `Job` model: distribution ope
- [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
@@ -126,4 +129,3 @@ console.log(await manager.assignTask(task, 21)); // 42
## 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).

View File

@@ -3,8 +3,8 @@
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
- [abstract-metrics](./abstract/abstract-metrics.md) — `abstract-metrics.ts` carries the pure functions and the small accumulator used by `AbstractWorker` to track success/fa…
- [abstract](./abstract/abstract.md) — <!-- begin:auto-docs --> _(no submodules)_- [local](./local/local.md) — <!-- begin:auto-docs --> _(no submodules)_ - [local](./local/local.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker](./worker.md) — <!-- begin:auto-docs --> _(no submodules)_- abstract-metrics — `abstract-metrics.ts` carries the…
- [abstract-metrics](./abstract/abstract-metrics.md) — `abstract-metrics.ts` carries the pure functions and the small accumulator used by `AbstractWorker` to track success/fa…
- [abstract](./abstract/abstract.md) — <!-- begin:auto-docs --> _(no submodules)_- [local](./local/local.md) — <!-- begin:auto-docs --> _(no submodules)_ - [local](./local/local.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker](./worker.md) — <!-- begin:auto-docs --> _(no submodules)_- abstract-metrics — `abstract-metrics.ts` carries the…
- [abstract-metrics](./abstract/abstract-metrics.md) — `abstract-metrics.ts` carries the pure functions and the small accumulator used by `AbstractWorker` to track success/fa…
- [abstract](./abstract/abstract.md) — <!-- begin:auto-docs --> _(no submodules)_- [local](./local/local.md) — <!-- begin:auto-docs --> _(no submodules)_- [local](./local/local.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker](./worker.md) — <!-- begin:auto-docs --> _(no submodules)_- [abstract-metrics](./abstract/abstract-metrics.md) — `abstract-metrics.ts` carries the pure functions and the small accumulator used by `AbstractWorker` to track success/fa…
- [abstract](./abstract/abstract.md) — <!-- begin:auto-docs --> _(no submodules)_- [local](./local/local.md) — <!-- begin:auto-docs --> _(no submodules)_- [local](./local/local.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker](./worker.md) — <!-- begin:auto-docs --> _(no submodules)_- abstract-metrics — `abstract…
@@ -12,6 +12,7 @@ _(no submodules)_
- [abstract](./abstract/abstract.md) — <!-- begin:auto-docs --> _(no submodules)_- [local](./local/local.md) — <!-- begin:auto-docs --> _(no submodules)_- [local](./local/local.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker](./worker.md) — <!-- begin:auto-docs --> _(no submodules)_- abstract-metrics — `abstract-metrics.ts` carries th…
- [abstract-metrics](./abstract/abstract-metrics.md) — `abstract-metrics.ts` carries the pure functions and the small accumulator used by `AbstractWorker` to track success/fa…
- [abstract](./abstract/abstract.md) — <!-- begin:auto-docs --> _(no submodules)_- [local](./local/local.md) — <!-- begin:auto-docs --> _(no submodules)_ - [local](./local/local.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker](./worker.md) — <!-- begin:auto-docs --> _(no submodules)_
## Purpose
`Worker` is the structural interface every distribution-tier executor implements. It describes lifecycle (`start`, `stop`), task execution (`executeTask`), health probing (`getHealth`, `canAcceptTask`), and introspection (`getInfo`). Concrete workers (`LocalWorker`, `RemoteWorker` from the HTTP plugin, `WorkerThreadWorker` from the worker-thread plugin) extend `AbstractWorker`, but downstream code should program against `Worker` so transport choices stay swappable.

View File

@@ -18,7 +18,9 @@ Enterprise-grade queue management: memory/priority/delayed queues, concurrent wo
- [queue-types](./src/types/queue-types.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [worker](./src/worker/queue-worker.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [queue-worker](./src/worker/queue-worker.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
<!-- end:auto-docs --> - [queue-error](./src/errors/queue-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [job](./src/job/job.md) — <!-- begin:auto-docs --> _(no submodules)_- [job](./src/job/job.md) — <!-- begin:auto-docs --> _(no submodules)_- [delayed-queue](./src/queue/delayed-queue.md) — `DelayedQueue<T>` is an explicit alias for a delay-aware FIFO queue. It extends `MemoryQueue<T>` to make the delay inte…
- [memory-queue](./src/queue/memory-queue.md) — `MemoryQueue<T>` is the foundational FIFO queue for `@suaveplan/queue`. It stores jobs in memory in insertion order and…
- [priority-queue](./src/queue/priority-queue.md) — `PriorityQueue<T>` extends `MemoryQueue<T>` to provide priority-ordered job scheduling. Jobs with higher `priority` val…
- [types](./src/types/queue-types.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue-types](./src/types/queue-types.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker](./src/worker/queue-worker.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue-worker](./src/worker/queue-worker.md) — <!-- begin:auto-docs --> _(no submodules)_- [queue-error](./src/errors/queue-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [job](./src/job/job.md) — <!-- begin:auto-docs --> _(no submodules)_- [job](./src/job/job.md) — <!-- begin:auto-docs --> _(no submodules)_- [delayed-queue](./src/queue/delayed-queue.md) — `DelayedQueue<T>` is an explicit alias for a delay-aware FIFO queue. It extends `MemoryQueue<T>` to make the delay inte…
@@ -31,6 +33,7 @@ Enterprise-grade queue management: memory/priority/delayed queues, concurrent wo
- [memory-queue](./src/queue/memory-queue.md) — `MemoryQueue<T>` is the foundational FIFO queue for `@suaveplan/queue`. It stores jobs in memory in insertion order and…
- [priority-queue](./src/queue/priority-queue.md) — `PriorityQueue<T>` extends `MemoryQueue<T>` to provide priority-ordered job scheduling. Jobs with higher `priority` val…
- [types](./src/types/queue-types.md) — <!-- begin:auto-docs --> _(no submodules)_ - [queue-types](./src/types/queue-types.md) — <!-- begin:auto-docs --> _(no submodules)_- [worker](./src/worker/queue-worker.md) — <!-- begin:auto-docs --> _(no submodules)_ - [queue-worker](./src/worker/queue-worker.md) — <!-- begin:auto-docs --> _(no submodules)_
## Packages
| Module | Description |

File diff suppressed because one or more lines are too long

View File

@@ -21,7 +21,9 @@ Retry strategies and circuit-breaker for async operations. The package provides
- [exponential](./src/strategies/exponential/exponential.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [linear](./src/strategies/linear/linear.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [linear](./src/strategies/linear/linear.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
<!-- end:auto-docs --> - [circuit-breaker](./src/circuit-breaker/circuit-breaker.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/retry-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [retry-error](./src/errors/retry-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/retry-otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [retry-otel](./src/otel/retry-otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [retry](./src/retry/retry.md) — <!-- begin:auto-docs --> _(no submodules)_- [retry](./src/retry/retry.md) — <!-- begin:auto-docs --> _(no submodules)_- [constant](./src/strategies/constant/constant.md) — <!-- begin:auto-docs --> _(no submodules)_- [constant](./src/strategies/constant/constant.md) — <!-- begin:auto-docs --> _(no submodules)_- [exponential](./src/strategies/exponential/exponential.md) — <!-- begin:auto-docs --> _(no submodules)_- [exponential](./src/strategies/exponential/exponential.md) — <!-- begin:auto-docs --> _(no submodules)_- [linear](./src/strategies/linear/linear.md) — <!-- begin:auto-docs --> _(no submodules)_- [linear](./src/strategies/linear/linear.md) — <!-- begin:auto-docs --> _(no submodules)_- [circuit-breaker](./src/circuit-breaker/circuit-breaker.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/retry-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [retry-error](./src/errors/retry-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/retry-otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [retry-otel](./src/otel/retry-otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [retry](./src/retry/retry.md) — <!-- begin:auto-docs --> _(no submodules)_- [retry](./src/retry/retry.md) — <!-- begin:auto-docs --> _(no submodules)_- [constant](./src/strategies/constant/constant.md) — <!-- begin:auto-docs --> _(no submodules)_- [constant](./src/strategies/constant/constant.md) — <!-- begin:auto-docs --> _(no submodules)_- [exponential](./src/strategies/exponential/exponential.md) — <!-- begin:auto-docs --> _(no submodules)_- [exponential](./src/strategies/exponential/exponential.md) — <!-- begin:auto-docs --> _(no submodules)_- [linear](./src/strategies/linear/linear.md) — <!-- begin:auto-docs --> _(no submodules)_- [linear](./src/strategies/linear/linear.md) — <!-- begin:auto-docs --> _(no submodules)_- [circuit-breaker](./src/circuit-breaker/circuit-breaker.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/retry-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [retry-error](./src/errors/retry-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/retry-otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [retry-otel](./src/otel/retry-otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [retry](./src/retry/retry.md) — <!-- begin:auto-docs --> _(no submodules)_- [retry](./src/retry/retry.md) — <!-- begin:auto-docs --> _(no submodules)_- [constant](./src/strategies/constant/constant.md) — <!-- begin:auto-docs --> _(no submodules)_- [constant](./src/strategies/constant/constant.md) — <!-- begin:auto-docs --> _(no submodules)_- [exponential](./src/strategies/exponential/exponential.md) — <!-- begin:auto-docs --> _(no submodules)_- [exponential](./src/strategies/exponential/exponential.md) — <!-- begin:auto-docs --> _(no submodules)_- [linear](./src/strategies/linear/linear.md) — <!-- begin:auto-docs --> _(no submodules)_- [linear](./src/strategies/linear/linear.md) — <!-- begin:auto-docs --> _(no submodules)_- [circuit-breaker](./src/circuit-breaker/circuit-breaker.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/retry-error.md) — <!-- begin:auto-docs --> _(no submodules)_ - [retry-error](./src/errors/retry-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/retry-otel.md) — <!-- begin:auto-docs --> _(no submodules)_ - [retry-otel](./src/otel/retry-otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [retry](./src/retry/retry.md) — <!-- begin:auto-docs --> _(no submodules)_ - [retry](./src/retry/retry.md) — <!-- begin:auto-docs --> _(no submodules)_- [constant](./src/strategies/constant/constant.md) — <!-- begin:auto-docs --> _(no submodules)_ - [constant](./src/strategies/constant/constant.md) — <!-- begin:auto-docs --> _(no submodules)_- [exponential](./src/strategies/exponential/exponential.md) — <!-- begin:auto-docs --> _(no submodules)_ - [exponential](./src/strategies/exponential/exponential.md) — <!-- begin:auto-docs --> _(no submodules)_- [linear](./src/strategies/linear/linear.md) — <!-- begin:auto-docs --> _(no submodules)_ - [linear](./src/strategies/linear/linear.md) — <!-- begin:auto-docs --> _(no submodules)_
## Install
```sh
@@ -75,4 +77,3 @@ const value = await breaker.call(async (signal) => {
| `circuit-breaker` — `CircuitBreaker` class, `CircuitBreakerConfig`, event map | [`src/circuit-breaker/circuit-breaker.md`](src/circuit-breaker/circuit-breaker.md) |
| `retry-error` — `RetryExhaustedError`, `RetryAbortedError`, `AttemptTimeoutError`, `CircuitOpenError` | [`src/errors/retry-error.md`](src/errors/retry-error.md) |
| `retry-otel` — OpenTelemetry span/event helpers | [`src/otel/retry-otel.md`](src/otel/retry-otel.md) |

View File

@@ -11,7 +11,9 @@ Hono middleware wrapping [`@suaveplan/rules`](../rules/README.md). Six middlewar
- [default](./src/engine/default.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [middleware](./src/middleware/middleware.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [middleware](./src/middleware/middleware.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
<!-- end:auto-docs --> - [default](./src/engine/default.md) — <!-- begin:auto-docs --> _(no submodules)_- [middleware](./src/middleware/middleware.md) — <!-- begin:auto-docs --> _(no submodules)_- [middleware](./src/middleware/middleware.md) — <!-- begin:auto-docs --> _(no submodules)_- [default](./src/engine/default.md) — <!-- begin:auto-docs --> _(no submodules)_- [middleware](./src/middleware/middleware.md) — <!-- begin:auto-docs --> _(no submodules)_- [middleware](./src/middleware/middleware.md) — <!-- begin:auto-docs --> _(no submodules)_- [default](./src/engine/default.md) — <!-- begin:auto-docs --> _(no submodules)_- [middleware](./src/middleware/middleware.md) — <!-- begin:auto-docs --> _(no submodules)_- [middleware](./src/middleware/middleware.md) — <!-- begin:auto-docs --> _(no submodules)_- [default](./src/engine/default.md) — <!-- begin:auto-docs --> _(no submodules)_- [middleware](./src/middleware/middleware.md) — <!-- begin:auto-docs --> _(no submodules)_ - [middleware](./src/middleware/middleware.md) — <!-- begin:auto-docs --> _(no submodules)_
## Install
```bash
@@ -38,4 +40,3 @@ app.get("/", (c) => c.json({ ok: true }));
## See also
- [`@suaveplan/rules`](../rules/README.md) — the underlying engine, builder, operators, validators, serializer, optimizer.

View File

@@ -35,9 +35,11 @@ Universal rule engine + validation system. Comprehensive `RuleEngine` with async
- [schema](./src/validators/schema/schema.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [schema](./src/validators/schema/schema.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [constants](./src/constants.md) — This module exposes the package-level constants consumed across the rules engine, validators, action executor, and even…
<!-- end:auto-docs --> - [actions](./src/actions/actions.md) — <!-- begin:auto-docs --> _(no submodules)_- [builder](./src/builder/builder.md) — <!-- begin:auto-docs --> _(no submodules)_- [builder](./src/builder/builder.md) — <!-- begin:auto-docs --> _(no submodules)_- [context](./src/context/context.md) — <!-- begin:auto-docs --> _(no submodules)_- [context](./src/context/context.md) — <!-- begin:auto-docs --> _(no submodules)_- [engine](./src/engine/engine.md) — <!-- begin:auto-docs --> _(no submodules)_- operators-internal — `compareValues(actual, operato…
- [engine](./src/engine/engine.md) — <!-- begin:auto-docs --> _(no submodules)_- operators-internal — `compareValues(actual, operato…
- [operators-internal](./src/engine/operators-internal.md) — `compareValues(actual, operator, expected)` is the built-in comparison dispatcher used by `RuleEngine` until the dedica…
- [engine](./src/engine/engine.md) — <!-- begin:auto-docs --> _(no submodules)_- operators-internal — `compareValues(actual, operato…
- [operators-internal](./src/engine/operators-internal.md) — `compareValues(actual, operator, expected)` is the built-in comparison dispatcher used by `RuleEngine` until the dedica…
- [errors](./src/errors/rules-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [rules-error](./src/errors/rules-error.md) — <!-- begin:auto-docs --> _(no submodules)_- [events](./src/events/event-bus.md) — <!-- begin:auto-docs --> _(no submodules)_- [event-bus](./src/events/event-bus.md) — <!-- begin:auto-docs --> _(no submodules)_- [operators](./src/operators/operators.md) — <!-- begin:auto-docs --> _(no submodules)_- [operators](./src/operators/operators.md) — <!-- begin:auto-docs --> _(no submodules)_- [optimizer](./src/optimizer/optimizer.md) — <!-- begin:auto-docs --> _(no submodules)_- [optimizer](./src/optimizer/optimizer.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [otel](./src/otel/otel.md) — <!-- begin:auto-docs --> _(no submodules)_- [serializer](./src/serializer/serializer.md) — <!-- begin:auto-docs --> _(no submodules)_- [serializer](./src/serializer/serializer.md) — <!-- begin:auto-docs --> _(no submodules)_- [custom](./src/validators/custom/custom.md) — <!-- begin:auto-docs --> _(no submodules)_- [custom](./src/validators/custom/custom.md) — <!-- begin:auto-docs --> _(no submodules)_- [field](./src/validators/field/field.md) — <!-- begin:auto-docs --> _(no submodules)_- [field](./src/validators/field/field.md) — <!-- begin:auto-docs --> _(no submodules)_- [schema](./src/validators/schema/schema.md) — <!-- begin:auto-docs --> _(no submodules)_- [schema](./src/validators/schema/schema.md) — <!-- begin:auto-docs --> _(no submodules)_- [constants](./src/constants.md) — This module exposes the package-level constants consumed across the rules engine, validators, action executor, and even…
- [actions](./src/actions/actions.md) — <!-- begin:auto-docs --> _(no submodules)_- [builder](./src/builder/builder.md) — <!-- begin:auto-docs --> _(no submodules)_- [builder](./src/builder/builder.md) — <!-- begin:auto-docs --> _(no submodules)_- [context](./src/context/context.md) — <!-- begin:auto-docs --> _(no submodules)_- [context](./src/context/context.md) — <!-- begin:auto-docs --> _(no submodules)_- [engine](./src/engine/engine.md) — <!-- begin:auto-docs --> _(no submodules)_- operators-internal — `compareValues(actual, operato…
- [engine](./src/engine/engine.md) — <!-- begin:auto-docs --> _(no submodules)_- operators-internal — `compareValues(actual, operato…
@@ -108,4 +110,3 @@ const result = await engine.evaluate(policy, context({ age: 21, region: "US" }))
## See also
- [`@suaveplan/rules-hono`](../rules-hono/README.md) — Hono middleware wrapping this package.

View File

@@ -3,6 +3,7 @@
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs --> - operators-internal — `compareValues(actual, operato…
- [operators-internal](./operators-internal.md) — `compareValues(actual, operator, expected)` is the built-in comparison dispatcher used by `RuleEngine` until the dedica…
- operators-internal — `compareValues(actual, operato…

View File

@@ -97,4 +97,3 @@ await queue.getStream().pipeTo(destination);
## License
MIT

View File

@@ -85,4 +85,3 @@ wraps every reader exception as `ExifFailedError`
- [`src/types/process-options.md`](src/types/process-options.md) — runtime
`ProcessOptions` shape (signal / clock / logger) accepted by every
transform.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -54,19 +54,19 @@ bun add @suaveplan/workflow
import { createWorkflow } from "@suaveplan/workflow";
interface OrderData {
orderId: string;
items: string[];
total: number;
orderId: string;
items: string[];
total: number;
}
const result = await createWorkflow<OrderData>("process-order")
.addStep("validate", (ctx) => {
if (ctx.items.length === 0) throw new Error("No items");
})
.build()
.run({
initialData: { orderId: "ord-1", items: ["widget"], total: 29.99 },
});
.addStep("validate", (ctx) => {
if (ctx.items.length === 0) throw new Error("No items");
})
.build()
.run({
initialData: { orderId: "ord-1", items: ["widget"], total: 29.99 },
});
```
## Modules
@@ -103,15 +103,15 @@ builder.onError("continue"); // log + skip the failure, run the rest
import { RetryPresets } from "@suaveplan/workflow";
builder
.addStep("flaky-api", async (ctx) => callExternalApi(ctx))
.withRetry(RetryPresets.standard());
.addStep("flaky-api", async (ctx) => callExternalApi(ctx))
.withRetry(RetryPresets.standard());
builder.addStep("custom", (ctx) => callApi(ctx)).withRetry({
maxAttempts: 5,
strategy: "exponential",
delayMs: 500,
maxDelayMs: 10_000,
backoffMultiplier: 2,
maxAttempts: 5,
strategy: "exponential",
delayMs: 500,
maxDelayMs: 10_000,
backoffMultiplier: 2,
});
```
@@ -121,13 +121,13 @@ builder.addStep("custom", (ctx) => callApi(ctx)).withRetry({
const engine = createWorkflowEngine(config);
engine.hooks.on("workflow:start", (p) =>
console.log(`Workflow ${p.workflowId} started`),
console.log(`Workflow ${p.workflowId} started`),
);
engine.hooks.on("step:complete", (p) =>
console.log(`Step ${p.stepId} completed`),
console.log(`Step ${p.stepId} completed`),
);
engine.hooks.on("step:fail", (p) =>
console.error(`Step ${p.stepId} failed:`, p.error),
console.error(`Step ${p.stepId} failed:`, p.error),
);
```
@@ -139,18 +139,18 @@ import { createSaga, createStep } from "@suaveplan/workflow";
const saga = createSaga({ id: "booking", name: "Booking Saga" });
saga
.addStep(createStep({
id: "reserve",
name: "Reserve Seats",
execute: (ctx) => reserveSeats(ctx),
compensate: (ctx) => releaseSeats(ctx),
}))
.addStep(createStep({
id: "charge",
name: "Charge Payment",
execute: (ctx) => chargeCard(ctx),
compensate: (ctx) => refundCard(ctx),
}));
.addStep(createStep({
id: "reserve",
name: "Reserve Seats",
execute: (ctx) => reserveSeats(ctx),
compensate: (ctx) => releaseSeats(ctx),
}))
.addStep(createStep({
id: "charge",
name: "Charge Payment",
execute: (ctx) => chargeCard(ctx),
compensate: (ctx) => refundCard(ctx),
}));
const result = await saga.execute(context);
// If "charge" fails, "reserve" is automatically compensated.
@@ -159,4 +159,3 @@ const result = await saga.execute(context);
## License
MIT

View File

@@ -49,12 +49,12 @@ await comp.compensateAll({ orderId: "ord-42" });
import { createCompensator } from "@suaveplan/workflow";
const comp = createCompensator<{ id: string }>({
continueOnError: false,
clock: () => 0,
continueOnError: false,
clock: () => 0,
});
comp.register("a", () => {
throw new Error("a failed");
throw new Error("a failed");
});
comp.register("b", () => undefined);
@@ -62,7 +62,7 @@ await comp.compensateAll({ id: "x" });
// Records contain a single entry for "b" with status "compensated"
// then the loop breaks because continueOnError is false.
if (comp.hasFailures === false) {
// Re-attempt the failed compensations later.
// Re-attempt the failed compensations later.
}
```
@@ -86,7 +86,7 @@ The internal `_runEntry` helper is shared by `compensateAll` and
`continueOnError` is false) so the callers can short-circuit without
duplicating the predicate.
`compensateSteps` filters by id *before* reversing, so the relative order
`compensateSteps` filters by id _before_ reversing, so the relative order
between matching ids is preserved as the inverse of registration order —
mirroring the `compensateAll` contract.

View File

@@ -34,27 +34,27 @@ leaking state across runs.
import { createSaga, createStep } from "@suaveplan/workflow";
const saga = createSaga<{ orderId: string }>({
id: "booking",
name: "Booking saga",
id: "booking",
name: "Booking saga",
});
saga
.addStep(
createStep({
id: "reserve",
name: "Reserve seats",
execute: (ctx) => reserveSeats(ctx),
compensate: (ctx) => releaseSeats(ctx),
}),
)
.addStep(
createStep({
id: "charge",
name: "Charge payment",
execute: (ctx) => chargeCard(ctx),
compensate: (ctx) => refundCard(ctx),
}),
);
.addStep(
createStep({
id: "reserve",
name: "Reserve seats",
execute: (ctx) => reserveSeats(ctx),
compensate: (ctx) => releaseSeats(ctx),
}),
)
.addStep(
createStep({
id: "charge",
name: "Charge payment",
execute: (ctx) => chargeCard(ctx),
compensate: (ctx) => refundCard(ctx),
}),
);
const result = await saga.execute({ orderId: "ord-1" });
```
@@ -66,28 +66,28 @@ import { createSaga, createStep } from "@suaveplan/workflow";
const fakeClock = () => 1_000;
const saga = createSaga<{ id: string }>({
id: "two-phase",
name: "Two-phase commit",
continueCompensationOnError: false,
clock: fakeClock,
id: "two-phase",
name: "Two-phase commit",
continueCompensationOnError: false,
clock: fakeClock,
});
saga.addStep(
createStep({
id: "lock",
name: "Lock resource",
execute: (ctx) => acquireLock(ctx.id),
compensate: (ctx) => releaseLock(ctx.id),
}),
createStep({
id: "lock",
name: "Lock resource",
execute: (ctx) => acquireLock(ctx.id),
compensate: (ctx) => releaseLock(ctx.id),
}),
);
saga.addStep(
createStep({
id: "commit",
name: "Commit",
execute: () => {
throw new Error("conflict");
},
}),
createStep({
id: "commit",
name: "Commit",
execute: () => {
throw new Error("conflict");
},
}),
);
const result = await saga.execute({ id: "row-7" });

View File

@@ -36,13 +36,13 @@ the live context mutating beneath the caller.
import { createContext } from "@suaveplan/workflow";
interface OrderData {
orderId: string;
total: number;
orderId: string;
total: number;
}
const ctx = createContext<OrderData>("wf-1", {
orderId: "ord-1",
total: 9.99,
orderId: "ord-1",
total: 9.99,
});
ctx.setStatus("running");
ctx.updateData({ total: 14.99 });
@@ -56,21 +56,21 @@ import { createContext } from "@suaveplan/workflow";
const ctx = createContext("wf-1", { user: "alice" });
ctx.setMeta("traceId", "00-abc-def");
ctx.addStepResult({
stepId: "validate",
status: "completed",
startedAt: 0,
completedAt: 1,
attempts: 1,
stepId: "validate",
status: "completed",
startedAt: 0,
completedAt: 1,
attempts: 1,
});
const before = ctx.snapshot();
ctx.updateData({ user: "bob" });
ctx.addStepResult({
stepId: "charge",
status: "completed",
startedAt: 1,
completedAt: 2,
attempts: 1,
stepId: "charge",
status: "completed",
startedAt: 1,
completedAt: 2,
attempts: 1,
});
console.log(before.data.user); // "alice" — snapshot is unaffected

View File

@@ -33,11 +33,11 @@ so callers can subscribe to lifecycle events before the engine is built.
import { createWorkflow } from "@suaveplan/workflow";
const result = await createWorkflow<{ orderId: string }>("checkout")
.addStep("validate", (ctx) => {
if (!ctx.orderId) throw new Error("missing");
})
.build()
.run({ initialData: { orderId: "ord-1" } });
.addStep("validate", (ctx) => {
if (!ctx.orderId) throw new Error("missing");
})
.build()
.run({ initialData: { orderId: "ord-1" } });
```
## Usage: Advanced Example
@@ -46,21 +46,21 @@ const result = await createWorkflow<{ orderId: string }>("checkout")
import { createWorkflow, RetryPresets } from "@suaveplan/workflow";
const engine = createWorkflow<{ user: string }>("onboarding", {
clock: () => 1_700_000_000_000,
clock: () => 1_700_000_000_000,
})
.withTimeout(30_000)
.onError("compensate")
.on("step:fail", (p) => console.error("failed:", p.stepId));
.withTimeout(30_000)
.onError("compensate")
.on("step:fail", (p) => console.error("failed:", p.stepId));
engine
.addStep("create", (ctx) => createAccount(ctx.user))
.withCompensation((ctx) => deleteAccount(ctx.user))
.withRetry({ maxAttempts: 2, strategy: "exponential" });
.addStep("create", (ctx) => createAccount(ctx.user))
.withCompensation((ctx) => deleteAccount(ctx.user))
.withRetry({ maxAttempts: 2, strategy: "exponential" });
engine
.addStep("notify", (ctx) => sendWelcome(ctx.user))
.withGuard((ctx) => ctx.user.startsWith("@"))
.withTimeout(5_000);
.addStep("notify", (ctx) => sendWelcome(ctx.user))
.withGuard((ctx) => ctx.user.startsWith("@"))
.withTimeout(5_000);
const result = await engine.run({ initialData: { user: "@alice" } });
```

View File

@@ -29,7 +29,7 @@ import { createWorkflowEngine } from "@suaveplan/workflow";
const engine = createWorkflowEngine({ id: "w", name: "n", steps: [] });
engine.transitionHooks.hook((data) => {
console.log("entering", data.stepName);
console.log("entering", data.stepName);
});
```
@@ -37,18 +37,18 @@ engine.transitionHooks.hook((data) => {
```ts
const engine = createWorkflowEngine<{ region: string }>({
id: "w",
name: "checkout",
steps,
id: "w",
name: "checkout",
steps,
});
const unsubscribe = engine.transitionHooks.hook(async (data) => {
if (data.context.region === "EU") {
return {
...data,
context: { ...data.context, region: "EU-norm" },
};
}
if (data.context.region === "EU") {
return {
...data,
context: { ...data.context, region: "EU-norm" },
};
}
});
await engine.run({ initialData: { region: "EU" } });

View File

@@ -40,18 +40,18 @@ codes.
import { createWorkflowEngine } from "@suaveplan/workflow";
const engine = createWorkflowEngine<{ orderId: string }>({
id: "wf-1",
name: "checkout",
onError: "stop",
steps: [
{
id: "validate",
name: "Validate",
execute: (ctx) => {
if (!ctx.orderId) throw new Error("missing");
},
},
],
id: "wf-1",
name: "checkout",
onError: "stop",
steps: [
{
id: "validate",
name: "Validate",
execute: (ctx) => {
if (!ctx.orderId) throw new Error("missing");
},
},
],
});
const result = await engine.run({ initialData: { orderId: "ord-1" } });
@@ -63,31 +63,31 @@ const result = await engine.run({ initialData: { orderId: "ord-1" } });
import { createWorkflowEngine } from "@suaveplan/workflow";
const engine = createWorkflowEngine<{ user: string }>({
id: "wf-1",
name: "onboarding",
timeout: 30_000,
onError: "compensate",
steps: [
{
id: "create-account",
name: "Create account",
execute: (ctx) => createAccount(ctx.user),
compensate: (ctx) => deleteAccount(ctx.user),
},
{
id: "send-welcome",
name: "Send welcome email",
execute: (ctx) => sendWelcome(ctx.user),
},
],
id: "wf-1",
name: "onboarding",
timeout: 30_000,
onError: "compensate",
steps: [
{
id: "create-account",
name: "Create account",
execute: (ctx) => createAccount(ctx.user),
compensate: (ctx) => deleteAccount(ctx.user),
},
{
id: "send-welcome",
name: "Send welcome email",
execute: (ctx) => sendWelcome(ctx.user),
},
],
});
engine.hooks.on("step:fail", (p) => {
console.error("step failed", p.stepId, p.error?.message);
console.error("step failed", p.stepId, p.error?.message);
});
engine.transitionHooks.hook((data) => {
return { ...data, context: { ...data.context, user: data.context.user.trim() } };
return { ...data, context: { ...data.context, user: data.context.user.trim() } };
});
const run = engine.run({ initialData: { user: " alice " } });
@@ -121,7 +121,7 @@ while still satisfying the registry's reachability gate.
is the original step error, so callers walking the cause chain still see
the real underlying error.
The `workflow:cancel` emit happens during the loop *and* the status is
The `workflow:cancel` emit happens during the loop _and_ the status is
re-set to `"cancelled"` after the loop returns; the second assignment is
a guard for the rare case where the loop returns immediately because the
flag was set before the first iteration.

View File

@@ -40,20 +40,20 @@ throw new WorkflowError(WORKFLOW_CODES.TIMEOUT, 'Workflow "checkout" timed out')
import { WORKFLOW_CODES, WorkflowError } from "@suaveplan/workflow/errors";
try {
await engine.run({ initialData });
await engine.run({ initialData });
} catch (error) {
if (error instanceof WorkflowError) {
switch (error.code) {
case WORKFLOW_CODES.TIMEOUT:
metrics.record("workflow.timeout");
break;
case WORKFLOW_CODES.COMPENSATION_FAILED:
alerts.fire({ severity: "critical", error });
break;
default:
logger.error("workflow failed", { code: error.code });
}
}
if (error instanceof WorkflowError) {
switch (error.code) {
case WORKFLOW_CODES.TIMEOUT:
metrics.record("workflow.timeout");
break;
case WORKFLOW_CODES.COMPENSATION_FAILED:
alerts.fire({ severity: "critical", error });
break;
default:
logger.error("workflow failed", { code: error.code });
}
}
}
```

View File

@@ -13,7 +13,7 @@ that aren't built in, push-notifications, audit trails). It deliberately
keeps the surface to four operations — `on`, `once`, `off`, `emit` — so
the engine and its consumers depend on a stable contract.
Every other module in the package emits *through* this class rather than
Every other module in the package emits _through_ this class rather than
acquiring its own listeners-map, so the registry is the canonical extension
point for downstream tooling.
@@ -34,12 +34,12 @@ import { createHookRegistry } from "@suaveplan/workflow";
const hooks = createHookRegistry<{ orderId: string }>();
hooks.on("workflow:start", (p) => {
console.log("starting", p.workflowId);
console.log("starting", p.workflowId);
});
await hooks.emit("workflow:start", {
workflowId: "wf-1",
context: { orderId: "ord-1" },
workflowId: "wf-1",
context: { orderId: "ord-1" },
});
```
@@ -47,34 +47,34 @@ await hooks.emit("workflow:start", {
```ts
import {
buildStepPayload,
createHookRegistry,
buildStepPayload,
createHookRegistry,
} from "@suaveplan/workflow";
const hooks = createHookRegistry<{ user: string }>();
const unsubscribe = hooks.on("step:fail", async (p) => {
if (p.stepResult && p.stepResult.attempts >= 3) {
await pageOnCall(p.error);
}
if (p.stepResult && p.stepResult.attempts >= 3) {
await pageOnCall(p.error);
}
});
hooks.once("workflow:complete", (p) => {
console.log("done", p.workflowId, p.timestamp);
console.log("done", p.workflowId, p.timestamp);
});
await hooks.emit("step:fail", buildStepPayload(
"wf-1",
{ user: "alice" },
"step-1",
{
stepId: "step-1",
status: "failed",
startedAt: 0,
completedAt: 100,
attempts: 3,
},
new Error("boom"),
"wf-1",
{ user: "alice" },
"step-1",
{
stepId: "step-1",
status: "failed",
startedAt: 0,
completedAt: 100,
attempts: 3,
},
new Error("boom"),
));
unsubscribe();

View File

@@ -35,8 +35,8 @@ the numbers in every consumer.
import { withRetry, RetryPresets } from "@suaveplan/workflow";
const result = await withRetry(
() => fetch("/api/data").then((r) => r.json()),
RetryPresets.standard(),
() => fetch("/api/data").then((r) => r.json()),
RetryPresets.standard(),
);
```
@@ -46,14 +46,14 @@ const result = await withRetry(
import { createRetryWrapper } from "@suaveplan/workflow";
const wrap = createRetryWrapper({
maxAttempts: 4,
strategy: "exponential",
delayMs: 100,
maxDelayMs: 2_000,
shouldRetry: (err) => !(err instanceof TypeError),
onRetry: (err, attempt) => {
console.warn(`attempt ${attempt} failed:`, err.message);
},
maxAttempts: 4,
strategy: "exponential",
delayMs: 100,
maxDelayMs: 2_000,
shouldRetry: (err) => !(err instanceof TypeError),
onRetry: (err, attempt) => {
console.warn(`attempt ${attempt} failed:`, err.message);
},
});
const json = await wrap(() => fetch("/api/v1").then((r) => r.json()));
@@ -72,7 +72,7 @@ const json = await wrap(() => fetch("/api/v1").then((r) => r.json()));
## Implementation Notes
`withRetry` always rethrows the *last* error, not the *first*. Callers
`withRetry` always rethrows the _last_ error, not the _first_. Callers
that want the first-error semantics can capture it inside an `onRetry`
closure. The loop checks `attempt >= maxAttempts` before `shouldRetry` so
the final attempt always actually runs even if `shouldRetry` would have

View File

@@ -52,7 +52,7 @@ await engine.run({ initialData });
const snapshot = await reader.collect();
const stepCounter = snapshot.resourceMetrics.scopeMetrics[0].metrics.find(
(m) => m.descriptor.name === "workflow.step.executed_total",
(m) => m.descriptor.name === "workflow.step.executed_total",
);
expect(stepCounter?.dataPoints.length).toBeGreaterThan(0);

View File

@@ -34,19 +34,19 @@ concerns. `compensate` rolls back only the branch that actually ran.
import { createConditionalStep, createStep } from "@suaveplan/workflow";
const branch = createConditionalStep<{ premium: boolean }>({
id: "discount",
name: "Discount",
condition: (ctx) => ctx.premium,
onTrue: createStep({
id: "premium",
name: "Premium discount",
execute: () => ({ discountPct: 30 }),
}),
onFalse: createStep({
id: "standard",
name: "Standard discount",
execute: () => ({ discountPct: 5 }),
}),
id: "discount",
name: "Discount",
condition: (ctx) => ctx.premium,
onTrue: createStep({
id: "premium",
name: "Premium discount",
execute: () => ({ discountPct: 30 }),
}),
onFalse: createStep({
id: "standard",
name: "Standard discount",
execute: () => ({ discountPct: 5 }),
}),
});
const result = await branch.run({ premium: true });
```
@@ -57,21 +57,21 @@ const result = await branch.run({ premium: true });
import { createConditionalStep, createStep } from "@suaveplan/workflow";
const ship = createStep<{ shipped: boolean }>({
id: "ship",
name: "Ship",
execute: async (ctx) => {
await dispatch(ctx);
},
compensate: async (ctx) => {
await recall(ctx);
},
id: "ship",
name: "Ship",
execute: async (ctx) => {
await dispatch(ctx);
},
compensate: async (ctx) => {
await recall(ctx);
},
});
const guard = createConditionalStep<{ ready: boolean }>({
id: "maybe-ship",
name: "Maybe ship",
condition: (ctx) => ctx.ready,
onTrue: ship,
id: "maybe-ship",
name: "Maybe ship",
condition: (ctx) => ctx.ready,
onTrue: ship,
});
await guard.run({ ready: true });

View File

@@ -36,13 +36,13 @@ failure.
import { createParallelStep, createStep } from "@suaveplan/workflow";
const group = createParallelStep<{ url: string }>({
groupId: "fetch-group",
name: "Fetch resources",
groupId: "fetch-group",
name: "Fetch resources",
});
group
.addStep(createStep({ id: "a", name: "A", execute: () => "a" }))
.addStep(createStep({ id: "b", name: "B", execute: () => "b" }));
.addStep(createStep({ id: "a", name: "A", execute: () => "a" }))
.addStep(createStep({ id: "b", name: "B", execute: () => "b" }));
const result = await group.run({ url: "https://example.com" });
```
@@ -53,31 +53,31 @@ const result = await group.run({ url: "https://example.com" });
import { createParallelStep, createStep } from "@suaveplan/workflow";
const group = createParallelStep<{ jobIds: string[] }>({
groupId: "process",
name: "Process jobs",
maxConcurrency: 2,
failFast: true,
groupId: "process",
name: "Process jobs",
maxConcurrency: 2,
failFast: true,
});
for (const id of ["a", "b", "c", "d"]) {
group.addStep(
createStep({
id,
name: `process-${id}`,
execute: async (ctx) => {
if (id === "b") throw new Error("nope");
return id;
},
compensate: async () => {
await unprocess(id);
},
}),
);
group.addStep(
createStep({
id,
name: `process-${id}`,
execute: async (ctx) => {
if (id === "b") throw new Error("nope");
return id;
},
compensate: async () => {
await unprocess(id);
},
}),
);
}
const result = await group.run({ jobIds: [] });
if (result.status === "failed") {
await group.compensateAll({ jobIds: [] });
await group.compensateAll({ jobIds: [] });
}
```

View File

@@ -37,9 +37,9 @@ unless they want to.
import { createStep } from "@suaveplan/workflow";
const charge = createStep<{ total: number }>({
id: "charge",
name: "Charge card",
execute: (ctx) => ({ chargedAt: Date.now(), amount: ctx.total }),
id: "charge",
name: "Charge card",
execute: (ctx) => ({ chargedAt: Date.now(), amount: ctx.total }),
});
const result = await charge.run({ total: 9.99 });
@@ -52,20 +52,20 @@ import { createStep, RetryPresets } from "@suaveplan/workflow";
const fakeClock = () => 0;
const flaky = createStep<{ url: string }>({
id: "fetch",
name: "Fetch resource",
execute: async (ctx) => {
const response = await fetch(ctx.url);
if (!response.ok) throw new Error(`status ${response.status}`);
return response.json();
},
guard: (ctx) => ctx.url.startsWith("https://"),
retry: RetryPresets.standard(),
timeout: 5_000,
compensate: async () => {
await releaseLock();
},
clock: fakeClock,
id: "fetch",
name: "Fetch resource",
execute: async (ctx) => {
const response = await fetch(ctx.url);
if (!response.ok) throw new Error(`status ${response.status}`);
return response.json();
},
guard: (ctx) => ctx.url.startsWith("https://"),
retry: RetryPresets.standard(),
timeout: 5_000,
compensate: async () => {
await releaseLock();
},
clock: fakeClock,
});
```

View File

@@ -26,18 +26,18 @@ package root barrel and reason about wire shapes without chasing imports.
import type { WorkflowConfig, StepDefinition } from "@suaveplan/workflow";
const validate: StepDefinition<{ items: string[] }> = {
id: "validate",
name: "Validate",
execute: (ctx) => {
if (ctx.items.length === 0) throw new Error("empty");
},
id: "validate",
name: "Validate",
execute: (ctx) => {
if (ctx.items.length === 0) throw new Error("empty");
},
};
const config: WorkflowConfig<{ items: string[] }> = {
id: "wf-1",
name: "checkout",
steps: [validate],
onError: "stop",
id: "wf-1",
name: "checkout",
steps: [validate],
onError: "stop",
};
```
@@ -45,35 +45,35 @@ const config: WorkflowConfig<{ items: string[] }> = {
```ts
import type {
HookListener,
StepResult,
RetryConfig,
HookListener,
StepResult,
RetryConfig,
} from "@suaveplan/workflow";
const auditLog: HookListener<{ orderId: string }> = (payload) => {
if (payload.event === "step:fail" && payload.stepResult) {
console.error("step failed", {
id: payload.stepResult.stepId,
attempts: payload.stepResult.attempts,
error: payload.stepResult.error?.message,
});
}
if (payload.event === "step:fail" && payload.stepResult) {
console.error("step failed", {
id: payload.stepResult.stepId,
attempts: payload.stepResult.attempts,
error: payload.stepResult.error?.message,
});
}
};
const exponential: RetryConfig = {
maxAttempts: 5,
strategy: "exponential",
delayMs: 100,
backoffMultiplier: 2,
maxDelayMs: 5000,
maxAttempts: 5,
strategy: "exponential",
delayMs: 100,
backoffMultiplier: 2,
maxDelayMs: 5000,
};
const skipped: StepResult = {
stepId: "skip",
status: "skipped",
startedAt: 0,
completedAt: 0,
attempts: 0,
stepId: "skip",
status: "skipped",
startedAt: 0,
completedAt: 0,
attempts: 0,
};
```

View File

@@ -32,7 +32,7 @@ changing the handler signatures.
import type { WorkflowTransitioningHandler } from "@suaveplan/workflow";
const audit: WorkflowTransitioningHandler<{ userId: string }> = (data) => {
console.log("entering step", data.stepName, "for", data.context.userId);
console.log("entering step", data.stepName, "for", data.context.userId);
};
```
@@ -40,25 +40,25 @@ const audit: WorkflowTransitioningHandler<{ userId: string }> = (data) => {
```ts
import type {
WorkflowTransitionData,
WorkflowTransitioningHandler,
WorkflowTransitionData,
WorkflowTransitioningHandler,
} from "@suaveplan/workflow";
interface OrderCtx {
orderId: string;
region: string;
taxRate?: number;
orderId: string;
region: string;
taxRate?: number;
}
// Enrich context with region-specific tax rate before each step runs.
const enrichTax: WorkflowTransitioningHandler<OrderCtx> = async (data) => {
if (data.context.taxRate !== undefined) return;
const rate = await fetchTaxRate(data.context.region);
const next: WorkflowTransitionData<OrderCtx> = {
...data,
context: { ...data.context, taxRate: rate },
};
return next;
if (data.context.taxRate !== undefined) return;
const rate = await fetchTaxRate(data.context.region);
const next: WorkflowTransitionData<OrderCtx> = {
...data,
context: { ...data.context, taxRate: rate },
};
return next;
};
```