package main import ( "context" "flag" "log/slog" "net/http" "os" "os/signal" "syscall" "time" "hash-of-wisdom/internal/config" "hash-of-wisdom/internal/lib/sl" "hash-of-wisdom/internal/pow/challenge" "hash-of-wisdom/internal/quotes" "hash-of-wisdom/internal/server" "hash-of-wisdom/internal/service" "github.com/prometheus/client_golang/prometheus/promhttp" _ "net/http/pprof" ) func main() { configPath := flag.String("config", "", "path to configuration file") flag.Parse() // Load configuration cfg, err := config.Load(*configPath) if err != nil { slog.Error("failed to load config", sl.Err(err)) os.Exit(1) } logger := slog.Default() logger.Info("starting word of wisdom server", "address", cfg.Server.Address) // Create components using config challengeConfig, err := challenge.NewConfig( challenge.WithDefaultDifficulty(cfg.PoW.Difficulty), challenge.WithMaxDifficulty(cfg.PoW.MaxDifficulty), challenge.WithChallengeTTL(cfg.PoW.TTL), challenge.WithHMACSecret([]byte(cfg.PoW.HMACSecret)), ) if err != nil { logger.Error("failed to create challenge config", sl.Err(err)) os.Exit(1) } generator := challenge.NewGenerator(challengeConfig) verifier := challenge.NewVerifier(challengeConfig) quoteService := quotes.NewHTTPService() // Wire up service genAdapter := service.NewGeneratorAdapter(generator) wisdomService := service.NewWisdomService(genAdapter, verifier, quoteService) // Create server configuration serverConfig := server.DefaultConfig() serverConfig.Address = addr // Create server srv := server.NewTCPServer(wisdomService, server.WithConfig(serverConfig), server.WithLogger(logger)) // Start server ctx := context.Background() if err := srv.Start(ctx); err != nil { logger.Error("failed to start server", sl.Err(err)) os.Exit(1) } // Wait for interrupt sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) logger.Info("server ready - press ctrl+c to stop") <-sigChan // Graceful shutdown logger.Info("shutting down server") if err := srv.Stop(); err != nil { logger.Error("error during shutdown", sl.Err(err)) } // Give connections time to close time.Sleep(100 * time.Millisecond) logger.Info("server stopped") }