package main import ( "context" "log" "net/http" "os" "os/signal" "syscall" "time" "github.com/joho/godotenv" "github.com/yourusername/markedit/internal/api" "github.com/yourusername/markedit/internal/auth" "github.com/yourusername/markedit/internal/database" ) func main() { // Load environment variables if err := godotenv.Load(); err != nil { log.Println("No .env file found, using environment variables") } // Get configuration port := os.Getenv("PORT") if port == "" { port = "8080" } dbPath := os.Getenv("DATABASE_PATH") if dbPath == "" { dbPath = "./data/markedit.db" } // Initialize database db, err := database.New(dbPath) if err != nil { log.Fatalf("Failed to initialize database: %v", err) } defer db.Close() // Run migrations if err := db.RunMigrations(); err != nil { log.Fatalf("Failed to run migrations: %v", err) } // Initialize authentication if err := auth.InitSessions(); err != nil { log.Fatalf("Failed to initialize sessions: %v", err) } if err := auth.SetupProviders(); err != nil { log.Fatalf("Failed to setup OAuth providers: %v", err) } // Create router router := api.NewRouter(db) // Create HTTP server srv := &http.Server{ Addr: ":" + port, Handler: router, ReadTimeout: 15 * time.Second, WriteTimeout: 15 * time.Second, IdleTimeout: 60 * time.Second, } // Start server in a goroutine go func() { log.Printf("Starting server on port %s", port) if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("Failed to start server: %v", err) } }() // Wait for interrupt signal quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit log.Println("Shutting down server...") // Graceful shutdown ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { log.Fatalf("Server forced to shutdown: %v", err) } log.Println("Server exited") }