package settings import ( "context" "errors" "fmt" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" ) // Store is the PostgreSQL implementation of Repository. type Store struct { pool *pgxpool.Pool } func NewStore(pool *pgxpool.Pool) *Store { return &Store{pool: pool} } func (s *Store) Get(ctx context.Context, key string) (string, bool, error) { var v string err := s.pool.QueryRow(ctx, `SELECT value FROM app_settings WHERE key = $1`, key).Scan(&v) if err != nil { if errors.Is(err, pgx.ErrNoRows) { return "", false, nil } return "", false, err } return v, true, nil } func (s *Store) Set(ctx context.Context, key, value string) error { _, err := s.pool.Exec(ctx, `INSERT INTO app_settings (key, value) VALUES ($1, $2) ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = now()`, key, value) return err } func (s *Store) Ensure(ctx context.Context, key string, generate func() (string, error)) (string, error) { if v, ok, err := s.Get(ctx, key); err != nil { return "", err } else if ok { return v, nil } v, err := generate() if err != nil { return "", err } if _, err := s.pool.Exec(ctx, `INSERT INTO app_settings (key, value) VALUES ($1, $2) ON CONFLICT (key) DO NOTHING`, key, v); err != nil { return "", err } got, ok, err := s.Get(ctx, key) if err != nil { return "", err } if !ok { return "", fmt.Errorf("settings: %q missing after insert", key) } return got, nil }