Files
PTah 6ad59c9990 fix: ограничить пул Postgres и реже писать прогресс скана
- DB_MAX_OPEN_CONNS (25), DB_MAX_IDLE_CONNS (10), DB_CONN_MAX_LIFETIME_SEC (1800)

- Throttle UpdateScan прогресса в Runner (500ms), меньше одновременных запросов к БД

Устраняет FATAL too many clients при больших сканах и частом опросе GetScan

Made-with: Cursor
2026-04-13 15:33:25 +10:00

81 lines
1.9 KiB
Go

package main
import (
"database/sql"
"log"
"net/http"
"nettopo-go/internal/api"
"nettopo-go/internal/config"
"nettopo-go/internal/scans"
"nettopo-go/internal/store"
_ "github.com/jackc/pgx/v5/stdlib"
)
func main() {
cfg := config.FromEnv()
scanStore, dbClose := makeStore(cfg)
if dbClose != nil {
defer dbClose()
}
runner := scans.NewRunner(scanStore, scans.RunnerConfig{
SNMPEnabled: cfg.SNMPEnabled,
SNMPCommunity: cfg.SNMPCommunity,
})
handler := api.NewHandler(scanStore, runner, cfg.ResetDBSecret)
server := &http.Server{
Addr: cfg.HTTPAddr,
Handler: handler.Routes(),
}
log.Printf("nettopo API is starting on %s", cfg.HTTPAddr)
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("server failed: %v", err)
}
}
func makeStore(cfg config.Config) (scans.Store, func()) {
if cfg.StoreBackend != "postgres" {
log.Printf("store backend: memory")
return scans.NewMemoryStore(), nil
}
if cfg.DBDSN == "" {
log.Fatalf("STORE_BACKEND=postgres requires DB_DSN")
}
db, err := sql.Open("pgx", cfg.DBDSN)
if err != nil {
log.Fatalf("db open failed: %v", err)
}
if err = db.Ping(); err != nil {
_ = db.Close()
log.Fatalf("db ping failed: %v", err)
}
db.SetMaxOpenConns(cfg.DBMaxOpenConns)
db.SetMaxIdleConns(cfg.DBMaxIdleConns)
if cfg.DBConnMaxLifetime > 0 {
db.SetConnMaxLifetime(cfg.DBConnMaxLifetime)
log.Printf("postgres pool: max_open=%d max_idle=%d conn_max_lifetime=%v", cfg.DBMaxOpenConns, cfg.DBMaxIdleConns, cfg.DBConnMaxLifetime)
} else {
log.Printf("postgres pool: max_open=%d max_idle=%d conn_max_lifetime=off", cfg.DBMaxOpenConns, cfg.DBMaxIdleConns)
}
if cfg.RunMigrations {
if err = store.RunMigrations(db); err != nil {
_ = db.Close()
log.Fatalf("db migration failed: %v", err)
}
}
log.Printf("store backend: postgres")
return scans.NewPostgresStore(db), func() {
_ = db.Close()
}
}