46 lines
5.0 KiB
Markdown
46 lines
5.0 KiB
Markdown
# @suaveplan/i18n-backend-chained - Universal chained backend orchestrator for the @suaveplan/i18n family. Composes N backends into a single Backend with read-fallthrough on BACKEND_LOCALE_NOT_AVAILABLE, write-through cache semantics after a successful read, and concurrent fan-out for readMulti with first-wins / last-wins merge. Transport failures (BACKEND_READ_FAILED) propagate immediately to stop the chain. Emits OpenTelemetry instrumentation under i18n.backend.chained.* including a cache_hit/cache_miss/primary outcome attribute on the read counter.
|
|
|
|
## Summary
|
|
|
|
Universal chained backend orchestrator for the `@suaveplan/i18n` family. Composes N backends into a single `Backend` with read-fallthrough on `BACKEND_LOCALE_NOT_AVAILABLE`, write-through cache semantics after a successful read, and concurrent fan-out for `readMulti` with `first-wins` (default) or `last-wins` merge strategy.
|
|
|
|
The chained backend is the canonical wiring for offline-first applications: register an in-memory or storage cache at index 0 and a network source of truth (`HttpBackend`) at the last index. The chain checks the cache first, falls through on miss, and writes the resolved record back to the cache so subsequent reads avoid the network round-trip. Transport failures (`BACKEND_READ_FAILED`) propagate immediately to stop the chain — silent degradation across an HTTP outage is not a feature.
|
|
|
|
OpenTelemetry instrumentation is emitted under `i18n.backend.chained.*`. The read counter carries an extended outcome attribute (`cache_hit | cache_miss | primary`) on top of the base `hit | miss | error` set so production teams can size cache layers correctly. A `fallthrough_total{from_backend, to_backend}` counter tracks per-link fallthrough rates.
|
|
|
|
<!-- begin:auto-docs -->
|
|
## Documentation tree
|
|
|
|
- [backend](./src/backend/backend.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
|
- [backend](./src/backend/backend.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
|
- [factory](./src/factory/factory.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
|
- [factory](./src/factory/factory.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
|
- [observability](./src/observability/observability.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
|
- [observability](./src/observability/observability.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
|
<!-- end:auto-docs --> - [backend](./src/backend/backend.md) — <!-- begin:auto-docs --> _(no submodules)_- [factory](./src/factory/factory.md) — <!-- begin:auto-docs --> _(no submodules)_- [factory](./src/factory/factory.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/observability.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/observability.md) — <!-- begin:auto-docs --> _(no submodules)_- [backend](./src/backend/backend.md) — <!-- begin:auto-docs --> _(no submodules)_- [factory](./src/factory/factory.md) — <!-- begin:auto-docs --> _(no submodules)_- [factory](./src/factory/factory.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/observability.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/observability.md) — <!-- begin:auto-docs --> _(no submodules)_- [backend](./src/backend/backend.md) — <!-- begin:auto-docs --> _(no submodules)_- [factory](./src/factory/factory.md) — <!-- begin:auto-docs --> _(no submodules)_- [factory](./src/factory/factory.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/observability.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/observability.md) — <!-- begin:auto-docs --> _(no submodules)_- [backend](./src/backend/backend.md) — <!-- begin:auto-docs --> _(no submodules)_- [factory](./src/factory/factory.md) — <!-- begin:auto-docs --> _(no submodules)_ - [factory](./src/factory/factory.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/observability.md) — <!-- begin:auto-docs --> _(no submodules)_ - [observability](./src/observability/observability.md) — <!-- begin:auto-docs --> _(no submodules)_
|
|
## Modules
|
|
|
|
| Module | Path | Doc |
|
|
|---|---|---|
|
|
| `ChainedBackend` class + Zod schema | `src/backend/backend.ts` | [`backend.md`](./src/backend/backend.md) |
|
|
| `chainedBackend` factory | `src/factory/factory.ts` | [`factory.md`](./src/factory/factory.md) |
|
|
| OTel instruments + state ring | `src/observability/observability.ts` | [`observability.md`](./src/observability/observability.md) |
|
|
|
|
## Subpath exports
|
|
|
|
- `@suaveplan/i18n-backend-chained` — root barrel
|
|
- `@suaveplan/i18n-backend-chained/backend` — `ChainedBackend` class + types + schema
|
|
- `@suaveplan/i18n-backend-chained/factory` — `chainedBackend` factory
|
|
- `@suaveplan/i18n-backend-chained/observability` — OTel instruments + state ring
|
|
|
|
## Install
|
|
|
|
```sh
|
|
bun add @suaveplan/i18n-backend-chained
|
|
```
|
|
|
|
## License
|
|
|
|
MIT — see repository root.
|
|
|