2025-11-23 22:49:46 +07:00

127 lines
3.2 KiB
Go

// 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")
}