package main import ( "context" "flag" "fmt" "log" "net/http" "os" "os/signal" "syscall" "time" "github.com/atlasos/calypso/internal/common/config" "github.com/atlasos/calypso/internal/common/database" "github.com/atlasos/calypso/internal/common/logger" "github.com/atlasos/calypso/internal/common/router" "golang.org/x/sync/errgroup" ) var ( version = "dev" buildTime = "unknown" gitCommit = "unknown" ) func main() { var ( configPath = flag.String("config", "/etc/calypso/config.yaml", "Path to configuration file") showVersion = flag.Bool("version", false, "Show version information") ) flag.Parse() if *showVersion { fmt.Printf("AtlasOS - Calypso API\n") fmt.Printf("Version: %s\n", version) fmt.Printf("Build Time: %s\n", buildTime) fmt.Printf("Git Commit: %s\n", gitCommit) os.Exit(0) } // Initialize logger logger := logger.NewLogger("calypso-api") // Load configuration cfg, err := config.Load(*configPath) if err != nil { logger.Fatal("Failed to load configuration", "error", err) } // Initialize database db, err := database.NewConnection(cfg.Database) if err != nil { logger.Fatal("Failed to connect to database", "error", err) } defer db.Close() // Run migrations if err := database.RunMigrations(context.Background(), db); err != nil { logger.Fatal("Failed to run database migrations", "error", err) } logger.Info("Database migrations completed successfully") // Initialize router r := router.NewRouter(cfg, db, logger) // Create HTTP server srv := &http.Server{ Addr: fmt.Sprintf(":%d", cfg.Server.Port), Handler: r, ReadTimeout: 15 * time.Second, WriteTimeout: 15 * time.Second, IdleTimeout: 60 * time.Second, } // Setup graceful shutdown ctx, cancel := context.WithCancel(context.Background()) defer cancel() g, gCtx := errgroup.WithContext(ctx) // Start HTTP server g.Go(func() error { logger.Info("Starting HTTP server", "port", cfg.Server.Port, "address", srv.Addr) if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { return fmt.Errorf("server failed: %w", err) } return nil }) // Graceful shutdown handler g.Go(func() error { sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) select { case <-sigChan: logger.Info("Received shutdown signal, initiating graceful shutdown...") cancel() case <-gCtx.Done(): return gCtx.Err() } shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second) defer shutdownCancel() if err := srv.Shutdown(shutdownCtx); err != nil { return fmt.Errorf("server shutdown failed: %w", err) } logger.Info("HTTP server stopped gracefully") return nil }) // Wait for all goroutines if err := g.Wait(); err != nil { log.Fatalf("Server error: %v", err) } }