@@ -0,0 +1,49 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Probe func(context.Context) error
|
||||
|
||||
type Component struct {
|
||||
Status string `json:"status"`
|
||||
}
|
||||
type Health struct {
|
||||
Status string `json:"status"`
|
||||
CheckedAt time.Time `json:"checked_at"`
|
||||
Components map[string]Component `json:"components"`
|
||||
}
|
||||
type HealthService struct{ postgres, redis Probe }
|
||||
|
||||
func NewHealthService(postgres, redis Probe) *HealthService {
|
||||
return &HealthService{postgres: postgres, redis: redis}
|
||||
}
|
||||
|
||||
func (s *HealthService) Check(ctx context.Context) Health {
|
||||
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
|
||||
defer cancel()
|
||||
result := Health{Status: "ready", CheckedAt: time.Now().UTC(), Components: map[string]Component{}}
|
||||
var mu sync.Mutex
|
||||
var wg sync.WaitGroup
|
||||
for name, probe := range map[string]Probe{"postgresql": s.postgres, "redis": s.redis} {
|
||||
wg.Go(func() {
|
||||
status := "unavailable"
|
||||
if probe == nil {
|
||||
status = "not_configured"
|
||||
} else if probe(ctx) == nil {
|
||||
status = "ready"
|
||||
}
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
result.Components[name] = Component{Status: status}
|
||||
if status != "ready" {
|
||||
result.Status = "not_ready"
|
||||
}
|
||||
})
|
||||
}
|
||||
wg.Wait()
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user