2025-11-17 12:17:44 +07:00

121 lines
2.9 KiB
Go

// main.go
package main
import (
"log"
"lost-and-found/internal/config"
"lost-and-found/internal/middleware"
"lost-and-found/internal/routes"
"lost-and-found/internal/workers"
"os"
"os/signal"
"syscall"
"github.com/gin-gonic/gin"
"github.com/joho/godotenv"
)
func main() {
// Load .env file
if err := godotenv.Load(); err != nil {
log.Println("⚠️ No .env file found, using environment variables")
}
// Initialize JWT config
config.InitJWT()
// Initialize database
if err := config.InitDB(); err != nil {
log.Fatalf("❌ Failed to initialize database: %v", err)
}
defer config.CloseDB()
// Run migrations
db := config.GetDB()
if err := config.RunMigrations(db); err != nil {
log.Fatalf("❌ Failed to run migrations: %v", err)
}
// Initialize Gin
if config.IsProduction() {
gin.SetMode(gin.ReleaseMode)
}
router := gin.Default()
// Apply middleware
router.Use(middleware.CORSMiddleware())
router.Use(middleware.LoggerMiddleware())
router.Use(middleware.RateLimiterMiddleware())
// Serve static files (uploads)
router.Static("/uploads", "./uploads")
router.Static("/css", "./web/css")
router.Static("/js", "./web/js")
// Frontend routes - REFACTORED: nama file lebih simple
router.GET("/", func(c *gin.Context) {
c.File("./web/index.html")
})
router.GET("/login", func(c *gin.Context) {
c.File("./web/login.html")
})
router.GET("/register", func(c *gin.Context) {
c.File("./web/register.html")
})
// ✅ REFACTORED: URL dan nama file lebih clean
router.GET("/admin", func(c *gin.Context) {
c.File("./web/admin.html")
})
router.GET("/manager", func(c *gin.Context) {
c.File("./web/manager.html")
})
router.GET("/user", func(c *gin.Context) {
c.File("./web/user.html")
})
// Setup API routes
routes.SetupRoutes(router, db)
// Start background workers
expireWorker := workers.NewExpireWorker(db)
auditWorker := workers.NewAuditWorker(db)
matchingWorker := workers.NewMatchingWorker(db)
notificationWorker := workers.NewNotificationWorker(db)
go expireWorker.Start()
go auditWorker.Start()
go matchingWorker.Start()
go notificationWorker.Start()
// Setup graceful shutdown
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
// Get server config
serverConfig := config.GetServerConfig()
port := serverConfig.Port
// Start server
go func() {
log.Printf("🚀 Server started on http://localhost:%s", port)
log.Printf("🔌 API available at http://localhost:%s/api", port)
log.Printf("🌐 Frontend available at http://localhost:%s", port)
if err := router.Run(":" + port); err != nil {
log.Fatalf("❌ Failed to start server: %v", err)
}
}()
// Wait for interrupt signal
<-quit
log.Println("\n🛑 Shutting down server...")
// Stop workers
expireWorker.Stop()
auditWorker.Stop()
matchingWorker.Stop()
notificationWorker.Stop()
log.Println("✅ Server exited gracefully")
}