Files
satusehat-worker/internal/infrastructure/transport/http/servers/server.go
T
2026-04-14 05:14:09 +00:00

149 lines
4.5 KiB
Go

// internal/infrastructure/transport/http/servers/server.go
package servers
import (
"context" // PERBAIKAN: Tambahkan import untuk graceful shutdown
"fmt"
"log"
"net/http"
"time"
"service/internal/infrastructure/cache" // PERBAIKAN: Tambahkan import cache
"service/internal/infrastructure/config"
"service/internal/infrastructure/transport/http/middleware"
"service/internal/infrastructure/transport/http/routes"
authHttp "service/internal/infrastructure/transport/http/handlers/main/auth"
healthHttp "service/internal/infrastructure/transport/http/handlers/main/health"
roleHttp "service/internal/infrastructure/transport/http/handlers/main/master/roles"
// Inisialisasi pkg
"service/pkg/errors"
"github.com/gin-gonic/gin"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
)
type Server struct {
engine *gin.Engine
config *config.ServerRESTConfig
cacheConfig cache.CacheConfig // PERBAIKAN: Tambahkan cacheConfig
httpServer *http.Server // PERBAIKAN: Simpan instance http.Server untuk graceful shutdown
}
// NewHTTPServer membuat instance server HTTP baru
func NewHTTPServer(
restConfig *config.ServerRESTConfig,
registry *ServiceRegistry,
) *Server {
if !restConfig.Enabled {
log.Println("HTTP server is disabled in configuration.")
return &Server{
config: restConfig,
}
}
// Set mode Gin berdasarkan konfigurasi global
if registry.Config.Server.Mode == "release" {
gin.SetMode(gin.ReleaseMode)
}
engine := gin.New()
// Middleware untuk recovery dan penanganan error konsisten.
// Diletakkan paling awal untuk menangkap panic dari middleware/handler lain.
engine.Use(errors.CombinedMiddleware())
// Middleware lainnya
engine.Use(middleware.LoggingMiddleware())
engine.Use(middleware.SecurityMiddleware())
engine.Use(middleware.CORSMiddleware())
// PERBAIKAN: Berikan cacheManager ke RateLimitMiddleware
engine.Use(middleware.RateLimitMiddleware(registry.CacheManager))
// Inisialisasi ModuleHandlers secara dinamis berdasarkan fitur yang aktif
appHandlers := &routes.ModuleHandlers{}
if registry.AuthService != nil {
appHandlers.Auth = authHttp.NewAuthHandler(registry.AuthService)
}
// Inisialisasi Handlers Modul Master
if registry.Master != nil {
if registry.Master.RolePages != nil {
appHandlers.RolePages = roleHttp.NewRolPagesHandler(registry.Master.RolePages)
}
if registry.Master.RolePermission != nil {
appHandlers.RolePermission = roleHttp.NewRolPermissionHandler(registry.Master.RolePermission)
}
if registry.Master.RoleMaster != nil {
appHandlers.RoleMaster = roleHttp.NewRoleMasterHandler(registry.Master.RoleMaster)
}
}
// Inisialisasi Health Handler dengan dependensi yang benar
// Gunakan constructor baru yang menerima cache manager
healthHandler := healthHttp.NewHealthHandlerWithCache(registry.PrimaryDB, registry.CacheManager, registry.Config, registry.DBManager)
// Setup routes menggunakan handler yang sudah diinisialisasi
routes.SetupRoutes(
engine,
registry.Config,
registry.CacheManager,
healthHandler,
appHandlers,
)
return &Server{
engine: engine,
config: restConfig,
}
}
// RegisterSwagger mendaftarkan dokumentasi Swagger UI
func (s *Server) RegisterSwagger() {
if s.engine == nil {
log.Println("Cannot register Swagger: engine is nil (server disabled)")
return
}
s.engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
}
// Start menjalankan server HTTP
func (s *Server) Start(globalConfig *config.ServerConfig) error {
if !s.config.Enabled {
log.Println("HTTP server is disabled, not starting.")
return nil
}
addr := fmt.Sprintf(":%d", s.config.Port)
log.Printf("Starting HTTP server on %s", addr)
// PERBAIKAN: Simpan instance server ke struct
s.httpServer = &http.Server{
Addr: addr,
Handler: s.engine,
ReadTimeout: time.Duration(globalConfig.ReadTimeout) * time.Second,
WriteTimeout: time.Duration(globalConfig.WriteTimeout) * time.Second,
IdleTimeout: 60 * time.Second, // Good practice to have an idle timeout
}
return s.httpServer.ListenAndServe()
}
// PERBAIKAN: Tambahkan method untuk graceful shutdown
// Shutdown memberhentikan server HTTP dengan graceful shutdown
func (s *Server) Shutdown(ctx context.Context) error {
if s.httpServer == nil {
return nil
}
log.Println("Shutting down HTTP server...")
return s.httpServer.Shutdown(ctx)
}
// GetEngine mengembalikan instance Gin engine (terutama untuk testing)
func (s *Server) GetEngine() *gin.Engine {
return s.engine
}