package cmd import ( "context" "os" "os/signal" "syscall" "time" "github.com/rs/zerolog/log" "github.com/spf13/cobra" "tss-rocks-be/internal/config" "tss-rocks-be/internal/server" "tss-rocks-be/pkg/logger" ) func GetServerCmd() *cobra.Command { var configPath string cmd := &cobra.Command{ Use: "server", Short: "Start the server", Long: `Start the server with the specified configuration.`, RunE: func(cmd *cobra.Command, args []string) error { // Load configuration cfg, err := config.Load(configPath) if err != nil { return err } // Setup logger logger.Setup(cfg) // Create a context that can be cancelled ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Set up signal handling sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) // Create ent client client := server.NewEntClient(cfg) if client == nil { log.Fatal().Msg("Failed to create database client") } defer client.Close() // Run the auto migration tool if err := client.Schema.Create(ctx); err != nil { log.Fatal().Err(err).Msg("Failed to create schema resources") } // Create and start server srv, err := server.New(cfg, client) if err != nil { log.Fatal().Err(err).Msg("Failed to create server") } // Start server in a goroutine go func() { if err := srv.Start(); err != nil { log.Fatal().Err(err).Msg("Failed to start server") } }() // Wait for interrupt signal sig := <-sigChan log.Info().Msgf("Received signal: %v", sig) // Attempt graceful shutdown with timeout log.Info().Msg("Shutting down server...") shutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if err := srv.Shutdown(shutdownCtx); err != nil { log.Error().Err(err).Msg("Server forced to shutdown") os.Exit(1) } return nil }, } // Add flags cmd.Flags().StringVarP(&configPath, "config", "c", "config/config.yaml", "path to config file") return cmd }