Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func run() error {
defer cancelConnect()
// Adaptador de almacenamiento: PostgreSQL + TimescaleDB. La conexión es perezosa (la API arranca aunque la
// base no responda todavía) y /health informa el estado real.
pool, err := postgres.Connect(connectCtx, cfg.Database.URL, int32(cfg.Database.MaxConns))
pool, err := postgres.Connect(connectCtx, cfg.Database.URL, cfg.Database.MaxConns)
if err != nil {
return err
}
Expand Down
11 changes: 9 additions & 2 deletions internal/storage/postgres/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,21 @@ type Pool struct {
Pool *pgxpool.Pool
}

// MaxPoolConns acota DATABASE_MAX_CONNS: más conexiones por instancia de la API no tiene sentido y el pool
// de pgx usa int32.
const MaxPoolConns = 1000

// Connect crea el pool a partir de la URL de PostgreSQL. No abre conexiones hasta la primera consulta.
func Connect(ctx context.Context, url string, maxConns int32) (*Pool, error) {
func Connect(ctx context.Context, url string, maxConns int) (*Pool, error) {
cfg, err := pgxpool.ParseConfig(url)
if err != nil {
return nil, fmt.Errorf("DATABASE_URL inválida: %w", err)
}
if maxConns > MaxPoolConns {
return nil, fmt.Errorf("DATABASE_MAX_CONNS no puede superar %d", MaxPoolConns)
}
if maxConns > 0 {
cfg.MaxConns = maxConns
cfg.MaxConns = int32(maxConns)
}
cfg.MaxConnIdleTime = 5 * time.Minute
pool, err := pgxpool.NewWithConfig(ctx, cfg)
Expand Down
28 changes: 28 additions & 0 deletions internal/storage/postgres/postgres_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package postgres

import (
"context"
"strings"
"testing"
)

// La URL es válida pero no se conecta: Connect no abre conexiones hasta la primera consulta.
const lazyURL = "postgres://smartpot:clave@127.0.0.1:1/smartpot?sslmode=disable"

func TestConnectRechazaPoolDesmedido(t *testing.T) {
_, err := Connect(context.Background(), lazyURL, MaxPoolConns+1)
if err == nil || !strings.Contains(err.Error(), "DATABASE_MAX_CONNS") {
t.Fatalf("se esperaba el error de DATABASE_MAX_CONNS, llegó %v", err)
}
}

func TestConnectAplicaElMaximoDeConexiones(t *testing.T) {
pool, err := Connect(context.Background(), lazyURL, 7)
if err != nil {
t.Fatalf("Connect: %v", err)
}
defer pool.Pool.Close()
if got := pool.Pool.Config().MaxConns; got != 7 {
t.Fatalf("MaxConns = %d, se esperaba 7", got)
}
}
Loading