package client import ( "context" "fmt" "time" "github.com/jackc/pgx/v5/pgxpool" "github.com/rs/zerolog" "github.com/gosec/gsc-ops-api/internal/config" ) // CardDAVClient wraps a pgx connection pool for the sabredav database type CardDAVClient struct { pool *pgxpool.Pool logger zerolog.Logger } // NewCardDAVClient creates a new CardDAV database client func NewCardDAVClient(cfg config.CardDAVConfig, dsn string, logger zerolog.Logger) (*CardDAVClient, error) { poolConfig, err := pgxpool.ParseConfig(dsn) if err != nil { return nil, fmt.Errorf("failed to parse carddav database config: %w", err) } poolConfig.MaxConns = 10 poolConfig.MinConns = 2 poolConfig.MaxConnLifetime = 1 * time.Hour poolConfig.MaxConnIdleTime = 30 * time.Minute poolConfig.HealthCheckPeriod = 1 * time.Minute ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() pool, err := pgxpool.NewWithConfig(ctx, poolConfig) if err != nil { return nil, fmt.Errorf("failed to create carddav connection pool: %w", err) } if err := pool.Ping(ctx); err != nil { pool.Close() return nil, fmt.Errorf("failed to ping carddav database: %w", err) } return &CardDAVClient{ pool: pool, logger: logger.With().Str("client", "carddav").Logger(), }, nil } // Pool returns the underlying connection pool func (c *CardDAVClient) Pool() *pgxpool.Pool { return c.pool } // Health checks the database connection func (c *CardDAVClient) Health(ctx context.Context) error { return c.pool.Ping(ctx) } // Close closes the connection pool func (c *CardDAVClient) Close() { if c.pool != nil { c.pool.Close() } }