# External Health Checker **Last Updated:** 2026-02-03 **Confidence:** High ## Summary Background worker that continuously monitors external systems (registry, CI, git) and surfaces issues proactively via metrics, logs, and the `/ready` endpoint. Runs every 30s, caches results for instant lookups, and logs state transitions. **Key Facts:** - Monitors: `registry` (zot), `ci` (woodpecker), `git` (gitea) - Check interval: 30 seconds (configurable) - Caches results for `/ready` endpoint (no blocking network calls) - Logs only on state changes (healthy→unhealthy, unhealthy→healthy) - Preserves `LastHealthy` timestamp through unhealthy periods **File Pointers:** - Domain types: `internal/domain/external_health.go` - Worker implementation: `internal/worker/external_health.go` - Port interface: `internal/port/health.go:ExternalHealthChecker` - Handler integration: `internal/handlers/health.go:WithExternalHealthChecker` - Wiring: `cmd/rdev-api/main.go:433-455` ## How It Works 1. Background goroutine polls all configured external systems every 30s 2. Checks run in parallel with 10s timeout per system 3. Results cached in thread-safe map 4. `/ready` reads cached statuses (no network calls) 5. Prometheus metrics updated on each check cycle **Adapter implementations:** - Registry: `internal/adapter/zot/client.go:Check()` - calls `/v2/` endpoint - CI: `internal/adapter/woodpecker/client.go:Check()` - calls `Self()` API - Git: `internal/adapter/gitea/client.go:Check()` - calls `ListMyOrgs()` ## Prometheus Metrics | Metric | Type | Labels | Description | |--------|------|--------|-------------| | `rdev_external_system_healthy` | Gauge | `system` | 1=healthy, 0=unhealthy | | `rdev_external_system_latency_seconds` | Gauge | `system` | Check latency | | `rdev_external_system_last_check_timestamp` | Gauge | `system` | Unix timestamp of last check | ## Related Topics - [Work Queue](./work-queue.md) - Uses similar background worker pattern - [CI Provider](./ci-provider.md) - Woodpecker adapter details - [Worker Pool](./worker-pool.md) - Another background worker example