Files
suaveplan/openspec/archive/2026-05-12-enterprise-network-failover/tasks.md
2026-05-27 23:29:53 +01:00

99 lines
4.1 KiB
Markdown

# Tasks: enterprise-network-failover
**Change ID**: enterprise-network-failover
**Package**: `@suaveplan/network-failover`
**Target path**: `universal/network/network-failover`
**Prerequisite packages on Verdaccio**: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/events`, `@suaveplan/logger`, `@suaveplan/retry`, `@suaveplan/timing`
---
## 1. Scaffold
- [x] Create `universal/network/network-failover/` with `src/`, `tests/`, and all feature subdirectories.
- [x] Write `package.json` at version `0.1.0`: `"sideEffects": false`, exports map, deps per `proposal.md`.
- [x] Write `tsconfig.json`, `vitest.config.ts`, scripts.
---
## 2. Types and error codes
- [x] Define all public types in `src/types/common.ts`: `FailoverTarget`, `HealthCheckConfig`, `HealthStatus`, `FailoverState`, `FailoverStrategy`, `FailoverEvent`, `FailoverEventData`, `FailoverGroupOptions`.
- [x] Write `src/types/common.md` (≥200 words, simple + advanced examples).
- [x] Define error codes in `src/error-codes.ts`.
- [x] Write Zod schemas in `src/types/schemas.ts` + `src/types/schemas.md`.
---
## 3. Failover strategies (`src/strategies/`)
### 3a. Round-robin
- [x] Implement `roundRobin(targets: FailoverTarget[], lastIndex: number): FailoverTarget | null`:
- Returns next healthy target in round-robin order; wraps around.
- [x] Write `round-robin.test.ts` + `round-robin.md`.
### 3b. Fastest
- [x] Implement `fastest(targets: FailoverTarget[]): FailoverTarget | null`:
- Returns healthy target with lowest `health.latencyMs`; falls back to any healthy target.
- [x] Write `fastest.test.ts` + `fastest.md`.
### 3c. Weighted
- [x] Implement `weighted(targets: FailoverTarget[], rng: Rng): FailoverTarget | null`:
- Normalised-weight random selection among healthy targets only.
- [x] Write `weighted.test.ts` + `weighted.md`.
### 3d. Priority
- [x] Implement `priority(targets: FailoverTarget[]): FailoverTarget | null`:
- Returns healthy target with highest `priority` value.
- [x] Write `priority.test.ts` + `priority.md`.
---
## 4. Health checker (`src/core/health-checker/`)
- [x] Implement `createHealthChecker(target, options, clock)`:
- Runs `options.healthCheck.probe ?? defaultProbe` on `intervalMs` interval.
- Track `consecutiveFailures` / `consecutiveSuccesses`.
- Emit `target-failed` after `failureThreshold` consecutive failures.
- Emit `target-recovered` after `successThreshold` consecutive successes.
- [x] Write `health-checker.test.ts` (≤500 lines): failure threshold fires, recovery fires, intervals.
- [x] Write `health-checker.md` (≥200 words).
---
## 5. Failover group (`src/core/failover-group/`)
- [x] Implement `createFailoverGroup(options)`:
- Validates options with Zod.
- Maintains `primary` and `targets[]`; starts health checkers for all.
- On `target-failed` for primary: wait `failoverDelayMs` then run strategy to select new primary.
- On `target-recovered` for non-primary: wait `failBackDelayMs`; consider fail-back only if score is higher.
- OTel: span `failover.execute`, counter `failover.events_total`, histogram `failover.latency_ms`.
- [x] Implement `group.execute(fn, signal?)`:
- Call `fn(primary, signal)`.
- On failure, immediately promote next target via strategy and retry `fn` once.
- Throw `NetworkFailoverError(FAILOVER_EXECUTE_FAILED)` after all targets exhausted.
- [x] Implement `group.probe(targetId, signal?)` — runs single health probe.
- [x] Write `failover-group.test.ts` (≤500 lines): execute on healthy primary, primary fails → failover, all fail throws, probe.
- [x] Write `failover-group.md` (≥200 words).
---
## 6. Property-based tests (`tests/property.test.ts`)
- [x] Strategy completeness: when all targets are healthy, strategy always returns a target.
- [x] Failover selects next healthy target after primary failure.
---
## 7. Docs and verify
- [x] All per-file `.md` files per layout in `proposal.md`.
- [x] `universal/network/network-failover/README.md`.
- [x] `bunx turbo lint typecheck test test:coverage --filter=@suaveplan/network-failover` — all green, 100%.
- [x] `bun scripts/publish.ts --package @suaveplan/network-failover`.
- [x] Update `CLAUDE.md`. Archive change folder.