Go backend with Gin, pgx, Valkey (go-valkey), and PostGIS. Domains: - Market search with PostGIS geo-queries (ST_DWithin, ST_Distance), German full-text search (tsvector + ILIKE fallback for compound words), date range filtering, pagination, and slug-based detail endpoint - Auth with email+password (bcrypt), JWT access tokens (15min), session tokens (30d, dual Valkey+Postgres storage), OAuth (Google/GitHub/Facebook), magic links, and TOTP 2FA - User profile with CRUD, soft-delete (30d grace), and restore Infrastructure: - 6 database migrations (users, sessions, oauth_accounts, magic_links, markets with PostGIS+FTS, totp_secrets) - Middleware: recovery, request ID, structured logging (slog), CORS, per-IP rate limiting, JWT auth - Seed data: 10 medieval markets across DACH region - Docker Compose (PostGIS 17 + Valkey 8), multi-stage Dockerfile, Woodpecker CI pipeline, Kubernetes manifests - Justfile, golangci-lint config, env example
35 lines
784 B
Go
35 lines
784 B
Go
package database
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log/slog"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
|
|
"marktvogt.de/backend/internal/config"
|
|
)
|
|
|
|
func NewPostgres(ctx context.Context, cfg config.DBConfig) (*pgxpool.Pool, error) {
|
|
poolCfg, err := pgxpool.ParseConfig(cfg.DSN())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("parsing postgres config: %w", err)
|
|
}
|
|
|
|
poolCfg.MaxConns = int32(cfg.MaxConns)
|
|
poolCfg.MinConns = int32(cfg.MinConns)
|
|
|
|
pool, err := pgxpool.NewWithConfig(ctx, poolCfg)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("creating postgres pool: %w", err)
|
|
}
|
|
|
|
if err := pool.Ping(ctx); err != nil {
|
|
pool.Close()
|
|
return nil, fmt.Errorf("pinging postgres: %w", err)
|
|
}
|
|
|
|
slog.Info("connected to postgres", "host", cfg.Host, "port", cfg.Port, "db", cfg.Name)
|
|
return pool, nil
|
|
}
|