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

4.1 KiB

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

  • Create universal/network/network-failover/ with src/, tests/, and all feature subdirectories.
  • Write package.json at version 0.1.0: "sideEffects": false, exports map, deps per proposal.md.
  • Write tsconfig.json, vitest.config.ts, scripts.

2. Types and error codes

  • Define all public types in src/types/common.ts: FailoverTarget, HealthCheckConfig, HealthStatus, FailoverState, FailoverStrategy, FailoverEvent, FailoverEventData, FailoverGroupOptions.
  • Write src/types/common.md (≥200 words, simple + advanced examples).
  • Define error codes in src/error-codes.ts.
  • Write Zod schemas in src/types/schemas.ts + src/types/schemas.md.

3. Failover strategies (src/strategies/)

3a. Round-robin

  • Implement roundRobin(targets: FailoverTarget[], lastIndex: number): FailoverTarget | null:
    • Returns next healthy target in round-robin order; wraps around.
  • Write round-robin.test.ts + round-robin.md.

3b. Fastest

  • Implement fastest(targets: FailoverTarget[]): FailoverTarget | null:
    • Returns healthy target with lowest health.latencyMs; falls back to any healthy target.
  • Write fastest.test.ts + fastest.md.

3c. Weighted

  • Implement weighted(targets: FailoverTarget[], rng: Rng): FailoverTarget | null:
    • Normalised-weight random selection among healthy targets only.
  • Write weighted.test.ts + weighted.md.

3d. Priority

  • Implement priority(targets: FailoverTarget[]): FailoverTarget | null:
    • Returns healthy target with highest priority value.
  • Write priority.test.ts + priority.md.

4. Health checker (src/core/health-checker/)

  • 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.
  • Write health-checker.test.ts (≤500 lines): failure threshold fires, recovery fires, intervals.
  • Write health-checker.md (≥200 words).

5. Failover group (src/core/failover-group/)

  • 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.
  • 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.
  • Implement group.probe(targetId, signal?) — runs single health probe.
  • Write failover-group.test.ts (≤500 lines): execute on healthy primary, primary fails → failover, all fail throws, probe.
  • Write failover-group.md (≥200 words).

6. Property-based tests (tests/property.test.ts)

  • Strategy completeness: when all targets are healthy, strategy always returns a target.
  • Failover selects next healthy target after primary failure.

7. Docs and verify

  • All per-file .md files per layout in proposal.md.
  • universal/network/network-failover/README.md.
  • bunx turbo lint typecheck test test:coverage --filter=@suaveplan/network-failover — all green, 100%.
  • bun scripts/publish.ts --package @suaveplan/network-failover.
  • Update CLAUDE.md. Archive change folder.