// Package healthcheck provides health check functionality. package healthcheck import ( "context" "log/slog" "time" "go.uber.org/fx" "sneak.berlin/go/pixa/internal/config" "sneak.berlin/go/pixa/internal/database" "sneak.berlin/go/pixa/internal/globals" "sneak.berlin/go/pixa/internal/logger" ) // Params defines dependencies for Healthcheck. type Params struct { fx.In Globals *globals.Globals Config *config.Config Logger *logger.Logger Database *database.Database } // Healthcheck provides health check information. type Healthcheck struct { StartupTime time.Time log *slog.Logger globals *globals.Globals config *config.Config } // New creates a new Healthcheck instance. func New(lc fx.Lifecycle, params Params) (*Healthcheck, error) { s := &Healthcheck{ log: params.Logger.Get(), globals: params.Globals, config: params.Config, } lc.Append(fx.Hook{ OnStart: func(_ context.Context) error { s.StartupTime = time.Now() return nil }, OnStop: func(_ context.Context) error { return nil }, }) return s, nil } // Response is the JSON response for health checks. type Response struct { Status string `json:"status"` Now string `json:"now"` UptimeSeconds int64 `json:"uptime_seconds"` UptimeHuman string `json:"uptime_human"` Version string `json:"version"` Appname string `json:"appname"` Maintenance bool `json:"maintenance_mode"` } func (s *Healthcheck) uptime() time.Duration { return time.Since(s.StartupTime) } // Healthcheck returns the current health status. func (s *Healthcheck) Healthcheck() *Response { resp := &Response{ Status: "ok", Now: time.Now().UTC().Format(time.RFC3339Nano), UptimeSeconds: int64(s.uptime().Seconds()), UptimeHuman: s.uptime().String(), Appname: s.globals.Appname, Version: s.globals.Version, Maintenance: s.config.MaintenanceMode, } return resp }