diff --git a/pkg/server/server.go b/pkg/server/server.go index 1cf4f00..4e2163e 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -213,7 +213,7 @@ func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) { // handleReadiness godoc // // @Summary Readiness check -// @Description Check if the service is ready to accept traffic +// @Description Check if the service is ready to accept traffic including database connectivity // @Tags System/Health // @Accept json // @Produce json @@ -223,12 +223,23 @@ func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) { func (s *Server) handleReadiness(w http.ResponseWriter, r *http.Request) { log.Trace().Msg("Readiness check requested") + // Check if server is shutting down select { case <-s.readyCtx.Done(): log.Trace().Msg("Readiness check: not ready (shutting down)") w.WriteHeader(http.StatusServiceUnavailable) w.Write([]byte(`{"ready":false}`)) + return default: + // Server is not shutting down, check database if available + if s.userRepo != nil { + if err := s.userRepo.CheckDatabaseHealth(r.Context()); err != nil { + log.Warn().Err(err).Msg("Database health check failed") + w.WriteHeader(http.StatusServiceUnavailable) + w.Write([]byte(`{"ready":false}`)) + return + } + } log.Trace().Msg("Readiness check: ready") w.Write([]byte(`{"ready":true}`)) } diff --git a/pkg/user/sqlite_repository.go b/pkg/user/sqlite_repository.go index 4e959d6..cba9c21 100644 --- a/pkg/user/sqlite_repository.go +++ b/pkg/user/sqlite_repository.go @@ -201,6 +201,17 @@ func (r *SQLiteRepository) Close() error { return sqlDB.Close() } +// CheckDatabaseHealth checks if the database is healthy and responsive +func (r *SQLiteRepository) CheckDatabaseHealth(ctx context.Context) error { + // Simple query to test database connectivity + var count int64 + result := r.db.WithContext(ctx).Model(&User{}).Count(&count) + if result.Error != nil { + return fmt.Errorf("database health check failed: %w", result.Error) + } + return nil +} + // createSpan creates a new telemetry span if persistence telemetry is enabled func (r *SQLiteRepository) createSpan(ctx context.Context, operation string) (context.Context, trace.Span) { if r.config == nil || !r.config.GetPersistenceTelemetryEnabled() { diff --git a/pkg/user/user.go b/pkg/user/user.go index ae8b505..04aafd7 100644 --- a/pkg/user/user.go +++ b/pkg/user/user.go @@ -30,6 +30,7 @@ type UserRepository interface { AllowPasswordReset(ctx context.Context, username string) error CompletePasswordReset(ctx context.Context, username, newPassword string) error UserExists(ctx context.Context, username string) (bool, error) + CheckDatabaseHealth(ctx context.Context) error } // AuthService defines interface for authentication operations