package main import ( "context" "fmt" "log" "net/http" "os" "os/signal" "syscall" "time" "github.com/gin-gonic/gin" swaggerFiles "github.com/swaggo/files" ginSwagger "github.com/swaggo/gin-swagger" _ "github.com/timetracker/backend/docs" // This line is important for swag to work "github.com/timetracker/backend/internal/api/routes" "github.com/timetracker/backend/internal/config" "github.com/timetracker/backend/internal/models" _ "gorm.io/driver/postgres" ) // @title Time Tracker API // @version 1.0 // @description This is a simple time tracker API. // @host localhost:8080 // @BasePath /api // @securityDefinitions.apikey BearerAuth // @in header // @name Authorization // @Summary Say hello // @Description Get a hello message // @ID hello // @Produce plain // @Success 200 {string} string "Hello from the Time Tracker Backend!" // @Router / [get] func helloHandler(c *gin.Context) { c.String(http.StatusOK, "Hello from the Time Tracker Backend!") } func main() { cfg, err := config.LoadConfig() if err != nil { log.Fatalf("Failed to load config: %v", err) } // Initialize database if err := models.InitDB(cfg.Database); err != nil { log.Fatalf("Error initializing database: %v", err) } defer func() { if err := models.CloseDB(); err != nil { log.Printf("Error closing database connection: %v", err) } }() // Migrate database schema if err := models.MigrateDB(); err != nil { log.Fatalf("Error migrating database: %v", err) } // Create Gin router r := gin.Default() // Basic route for health check r.GET("/api", helloHandler) // Setup API routes routes.SetupRouter(r) // Swagger documentation r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) // Create a server with graceful shutdown srv := &http.Server{ Addr: ":8080", Handler: r, } // Start server in a goroutine go func() { fmt.Println("Server listening on port 8080") if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("Error starting server: %v", err) } }() // Wait for interrupt signal to gracefully shut down the server quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit log.Println("Shutting down server...") // Create a deadline for server shutdown ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() // Shutdown the server if err := srv.Shutdown(ctx); err != nil { log.Fatalf("Server forced to shutdown: %v", err) } log.Println("Server exited properly") }