forked from baron/baron-sso
헬스체크 추가
This commit is contained in:
@@ -6,12 +6,21 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/bwmarrin/snowflake"
|
||||
"baron-sso-backend/internal/handler"
|
||||
"baron-sso-backend/internal/logger"
|
||||
"baron-sso-backend/internal/repository"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/bwmarrin/snowflake"
|
||||
|
||||
"baron-sso-backend/internal/handler"
|
||||
|
||||
"baron-sso-backend/internal/logger"
|
||||
|
||||
"baron-sso-backend/internal/repository"
|
||||
|
||||
"baron-sso-backend/internal/service"
|
||||
|
||||
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
|
||||
|
||||
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||
"github.com/gofiber/fiber/v2/middleware/encryptcookie"
|
||||
"github.com/gofiber/fiber/v2/middleware/recover"
|
||||
@@ -58,9 +67,14 @@ func main() {
|
||||
slog.Warn("Failed to connect to ClickHouse. Audit logs will fail.", "error", err)
|
||||
}
|
||||
|
||||
redisService, err := service.NewRedisService()
|
||||
if err != nil {
|
||||
slog.Warn("Failed to connect to Redis. Auth features may fail.", "error", err)
|
||||
}
|
||||
|
||||
// 2. Initialize Handlers
|
||||
auditHandler := handler.NewAuditHandler(auditRepo)
|
||||
authHandler := handler.NewAuthHandler()
|
||||
authHandler := handler.NewAuthHandler(redisService)
|
||||
adminHandler := handler.NewAdminHandler()
|
||||
|
||||
// 3. Initialize Fiber
|
||||
@@ -118,7 +132,46 @@ func main() {
|
||||
})
|
||||
|
||||
app.Get("/health", func(c *fiber.Ctx) error {
|
||||
return c.JSON(fiber.Map{"status": "ok"})
|
||||
status := "ok"
|
||||
checks := make(map[string]string)
|
||||
|
||||
// Check ClickHouse
|
||||
if auditRepo != nil {
|
||||
if err := auditRepo.Ping(c.Context()); err != nil {
|
||||
checks["clickhouse"] = "error: " + err.Error()
|
||||
status = "error"
|
||||
} else {
|
||||
checks["clickhouse"] = "ok"
|
||||
}
|
||||
} else {
|
||||
checks["clickhouse"] = "not_initialized"
|
||||
status = "degraded"
|
||||
}
|
||||
|
||||
// Check Redis
|
||||
if redisService != nil {
|
||||
if err := redisService.Ping(c.Context()); err != nil {
|
||||
checks["redis"] = "error: " + err.Error()
|
||||
status = "error"
|
||||
} else {
|
||||
checks["redis"] = "ok"
|
||||
}
|
||||
} else {
|
||||
checks["redis"] = "not_initialized"
|
||||
status = "degraded"
|
||||
}
|
||||
|
||||
if status == "error" {
|
||||
return c.Status(fiber.StatusServiceUnavailable).JSON(fiber.Map{
|
||||
"status": status,
|
||||
"checks": checks,
|
||||
})
|
||||
}
|
||||
|
||||
return c.JSON(fiber.Map{
|
||||
"status": status,
|
||||
"checks": checks,
|
||||
})
|
||||
})
|
||||
|
||||
// API Group
|
||||
|
||||
@@ -49,16 +49,12 @@ func GenerateSecureToken(length int) string {
|
||||
return hex.EncodeToString(b)
|
||||
}
|
||||
|
||||
func NewAuthHandler() *AuthHandler {
|
||||
redisService, err := service.NewRedisService()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to connect to Redis: %v", err)
|
||||
}
|
||||
|
||||
func NewAuthHandler(redisService *service.RedisService) *AuthHandler {
|
||||
projectID := os.Getenv("DESCOPE_PROJECT_ID")
|
||||
managementKey := os.Getenv("DESCOPE_MANAGEMENT_KEY")
|
||||
|
||||
var descopeClient *client.DescopeClient
|
||||
var err error
|
||||
if projectID != "" {
|
||||
descopeClient, err = client.NewWithConfig(&client.Config{
|
||||
ProjectID: projectID,
|
||||
|
||||
@@ -79,3 +79,10 @@ func (r *ClickHouseRepository) Create(log *domain.AuditLog) error {
|
||||
log.Details,
|
||||
)
|
||||
}
|
||||
|
||||
func (r *ClickHouseRepository) Ping(ctx context.Context) error {
|
||||
if r.conn == nil {
|
||||
return fmt.Errorf("clickhouse connection is nil")
|
||||
}
|
||||
return r.conn.Ping(ctx)
|
||||
}
|
||||
|
||||
@@ -33,6 +33,13 @@ func NewRedisService() (*RedisService, error) {
|
||||
return &RedisService{Client: rdb}, nil
|
||||
}
|
||||
|
||||
func (s *RedisService) Ping(ctx context.Context) error {
|
||||
if s.Client == nil {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
return s.Client.Ping(ctx).Err()
|
||||
}
|
||||
|
||||
// StoreVerificationCode saves the SMS verification code with a 3-minute expiration
|
||||
func (s *RedisService) StoreVerificationCode(phone, code string) error {
|
||||
// Key format: "sms_verify:01012345678"
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
backend:
|
||||
build:
|
||||
@@ -35,6 +33,13 @@ services:
|
||||
- ./backend:/app
|
||||
command: ["go", "run", "./cmd/server/main.go"]
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/health"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
|
||||
frontend:
|
||||
build:
|
||||
context: ./frontend
|
||||
@@ -52,7 +57,8 @@ services:
|
||||
networks:
|
||||
- baron_net
|
||||
depends_on:
|
||||
- backend
|
||||
backend:
|
||||
condition: service_healthy
|
||||
command: >
|
||||
/bin/sh -c "mkdir -p /usr/share/nginx/html/assets &&
|
||||
echo \"DESCOPE_PROJECT_ID=$${DESCOPE_PROJECT_ID}\" > /usr/share/nginx/html/assets/.env &&
|
||||
|
||||
@@ -20,6 +20,12 @@ services:
|
||||
- "${BACKEND_PORT:-3000}:3000"
|
||||
depends_on:
|
||||
- infra_check
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/health"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
networks:
|
||||
- baron_net
|
||||
|
||||
@@ -30,7 +36,8 @@ services:
|
||||
ports:
|
||||
- "${FRONTEND_PORT:-80}:80"
|
||||
depends_on:
|
||||
- backend
|
||||
backend:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- baron_net
|
||||
|
||||
|
||||
Reference in New Issue
Block a user