127 lines
3.2 KiB
Go
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")
|
|
} |