package main import ( "context" "log" "net/http" "os" "os/signal" "syscall" "github.com/joho/godotenv" "golang.org/x/crypto/bcrypt" "yaum/internal/alerts" "yaum/internal/api" "yaum/internal/config" "yaum/internal/monitor" "yaum/internal/servermetrics" "yaum/internal/sse" "yaum/internal/store" ) func main() { godotenv.Load() cfgPath := os.Getenv("CONFIG_PATH") cfg, err := config.Load(cfgPath) if err != nil { log.Fatalf("config: %v", err) } passwordHash := cfg.AdminPasswordHash() if passwordHash == "" { if pw := os.Getenv("ADMIN_PASSWORD"); pw != "" { hash, err := bcrypt.GenerateFromPassword([]byte(pw), bcrypt.DefaultCost) if err != nil { log.Fatalf("erro ao gerar hash da senha: %v", err) } passwordHash = string(hash) } } if passwordHash == "" { log.Fatal("ADMIN_PASSWORD_HASH ou ADMIN_PASSWORD nao definido — defina no .env ou config.json") } ctx, cancel := context.WithCancel(context.Background()) defer cancel() var st store.Store if dbURL := cfg.DatabaseURL(); dbURL != "" { log.Println("conectando ao postgres...") pg, err := store.NewPostgresStore(ctx, dbURL) if err != nil { log.Fatalf("banco: %v", err) } defer pg.Close() st = pg log.Println("conectado ao postgres") } else { log.Println("database.url vazio — usando store em memoria") ms := store.NewMemoryStore() ms.SeedMockData() st = ms } broadcaster := sse.NewBroadcaster() worker := monitor.NewWorker(st, cfg.CheckInterval(), cfg.CheckTimeout(), broadcaster) if cfg.SMTP.From != "" { smtpCfg := &alerts.SMTPConfig{ Host: cfg.SMTP.Host, Port: cfg.SMTP.Port, Username: cfg.SMTP.Username, Password: cfg.SMTP.Password, From: cfg.SMTP.From, } worker.WithSMTP(smtpCfg) } metricsCollector := servermetrics.New(".") go metricsCollector.Start(ctx) handler := api.NewHandler(st, int(cfg.CheckTimeout().Seconds()), metricsCollector) streamHandler := api.NewStreamHandler(broadcaster) authHandler := api.NewAuthHandler( cfg.AdminUsername(), passwordHash, cfg.JWTSecret(), ) server := &http.Server{ Addr: cfg.ServerAddr(), Handler: api.NewRouter(handler, streamHandler, authHandler), } go worker.Start(ctx) go func() { sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) sig := <-sigCh log.Printf("sinal recebido: %s. desligando...", sig) worker.Stop() server.Shutdown(context.Background()) }() log.Printf("yaum rodando em %s", cfg.ServerAddr()) if err := server.ListenAndServe(); err != http.ErrServerClosed { log.Fatalf("erro ao iniciar servidor: %v", err) } log.Println("servidor encerrado com sucesso") }