// cmd/server/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 log.Println("šŸ“Š Initializing database...") if err := config.InitDB(); err != nil { log.Fatalf("āŒ Failed to initialize database: %v", err) } defer config.CloseDB() // Run migrations log.Println("šŸ”„ Running 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 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") }) 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 with error handling log.Println("šŸ”„ Starting 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() log.Println("āœ… Background workers started") // 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 starting on http://localhost:%s\n", port) log.Printf("šŸ“ API available at http://localhost:%s/api\n", port) log.Printf("🌐 Frontend available at http://localhost:%s\n", port) log.Println("āœ… Ready to receive requests") 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 gracefully...") // Stop workers log.Println("šŸ”„ Stopping background workers...") expireWorker.Stop() auditWorker.Stop() matchingWorker.Stop() notificationWorker.Stop() log.Println("āœ… Background workers stopped") log.Println("āœ… Server exited gracefully") }