package main import ( "context" "sync" "time" "git.ravensburg.dev/cabele/opnsense-portal/internal/check" "git.ravensburg.dev/cabele/opnsense-portal/internal/web" ) // healthCacheTTL verhindert, dass häufige Monitoring-Abfragen Firewall und // Verzeichnis belasten. const healthCacheTTL = 30 * time.Second // directoryPinger ist der für /healthz benötigte Ausschnitt des AD-Clients. type directoryPinger interface { ResolveGroupDN(ctx context.Context) (string, error) } // healthChecker beantwortet /healthz mit kurz gecachten Ergebnissen. type healthChecker struct { fw check.Pinger dir directoryPinger clock func() time.Time mu sync.Mutex cached web.HealthReport cachedAt time.Time } func newHealthChecker(fw check.Pinger, dir directoryPinger) *healthChecker { return &healthChecker{fw: fw, dir: dir, clock: time.Now} } func (h *healthChecker) Check(ctx context.Context) web.HealthReport { now := h.clock() h.mu.Lock() if !h.cachedAt.IsZero() && now.Sub(h.cachedAt) < healthCacheTTL { rep := h.cached h.mu.Unlock() return rep } h.mu.Unlock() ctx, cancel := context.WithTimeout(ctx, 10*time.Second) defer cancel() var rep web.HealthReport _, fwErr := h.fw.Ping(ctx) rep.OPNsense = fwErr == nil _, dirErr := h.dir.ResolveGroupDN(ctx) rep.Directory = dirErr == nil rep.OK = rep.OPNsense && rep.Directory h.mu.Lock() h.cached, h.cachedAt = rep, now h.mu.Unlock() return rep } var _ web.HealthChecker = (*healthChecker)(nil)