package main import ( "context" "log" "net/http" "os" "os/signal" "time" "git.farahty.com/nimer/go-mongo/app" "github.com/fatih/color" ) func main() { // Setup cancelable root context ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Panic recovery defer func() { if r := recover(); r != nil { color.Red("🔴 Panic occurred: %v\n", r) os.Exit(1) } }() color.Yellow("🚀 Starting server ...\n") // Load and validate config err := app.LoadConfig() if err != nil { log.Fatal("🔴 Config error: ", err) } // Connect to Mongo dbCancel, err := app.Connect() if err != nil { log.Fatalf("🔴 MongoDB connection error: %v", err) } defer func() { color.Red("❌ Closing MongoDB connection...\n") dbCancel() if err := app.Mongo.Disconnect(ctx); err != nil { log.Fatal("🔴 MongoDB disconnection error: ", err) } }() color.Green("✅ Connected to MongoDB successfully\n") // Load authorization policies using root context if err := app.LoadAuthorizer(ctx); err != nil { log.Fatal("🔴 Authorizer error: ", err) } color.Green("✅ Authorization policies loaded successfully\n") // Redis if err := app.InitRedis(ctx); err != nil { log.Fatal("🔴 Redis connection error: ", err) } defer func() { color.Red("❌ Closing Redis connection...\n") _ = app.RedisClient.Close() }() color.Green("✅ Connected to Redis cache successfully\n") // Create GraphQL server graphqlServer := createGraphqlServer() // Start HTTP server server := &http.Server{ Addr: ":" + app.Config.Port, Handler: createRouter(graphqlServer), ReadTimeout: 30 * time.Second, WriteTimeout: 30 * time.Second, IdleTimeout: 30 * time.Second, } go func() { color.Green("🌐 Server listening at http://localhost:%s\n", app.Config.Port) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatalf("🔴 Server failed: %v", err) } }() // Graceful shutdown quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit color.Yellow("🟡 Shutdown signal received, initiating cleanup...") // Cancel root context and wait for graceful shutdown shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 15*time.Second) defer shutdownCancel() if err := server.Shutdown(shutdownCtx); err != nil { log.Fatalf("🔴 Server forced to shutdown: %v", err) } color.Green("✅ Server shutdown completed gracefully") }