mirror of
https://github.com/foomo/keel.git
synced 2025-10-16 12:35:34 +00:00
108 lines
2.0 KiB
Go
108 lines
2.0 KiB
Go
package keelpostgres
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/jackc/pgx/v4"
|
|
"github.com/jackc/pgx/v4/log/zapadapter"
|
|
"github.com/pkg/errors"
|
|
"go.uber.org/zap"
|
|
|
|
"github.com/foomo/keel/log"
|
|
)
|
|
|
|
// Persistor exported to used also for embedding into other types in foreign packages.
|
|
type (
|
|
Persistor struct {
|
|
db *pgx.Conn
|
|
l *zap.Logger
|
|
}
|
|
Options struct {
|
|
Init string
|
|
Logger *zap.Logger
|
|
}
|
|
Option func(*Options)
|
|
)
|
|
|
|
func WithInit(v string) Option {
|
|
return func(o *Options) {
|
|
o.Init = v
|
|
}
|
|
}
|
|
|
|
func WithLogger(v *zap.Logger) Option {
|
|
return func(o *Options) {
|
|
o.Logger = v
|
|
}
|
|
}
|
|
|
|
func DefaultOptions() Options {
|
|
return Options{
|
|
Logger: log.Logger(),
|
|
}
|
|
}
|
|
|
|
func New(ctx context.Context, uri string, opts ...Option) (*Persistor, error) {
|
|
// urlExample := "postgres://username:password@localhost:5432/database_name"
|
|
|
|
o := DefaultOptions()
|
|
for _, opt := range opts {
|
|
opt(&o)
|
|
}
|
|
|
|
config, err := pgx.ParseConfig(uri)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to parse uri")
|
|
}
|
|
|
|
config.Logger = zapadapter.NewLogger(o.Logger)
|
|
// TODO @franklin performance config
|
|
|
|
db, err := pgx.ConnectConfig(ctx, config)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "failed to connect")
|
|
}
|
|
|
|
// TODO @franklin add telemetry
|
|
|
|
if err := db.Ping(ctx); err != nil {
|
|
return nil, errors.Wrap(err, "failed to ping database")
|
|
}
|
|
|
|
p := &Persistor{
|
|
db: db,
|
|
l: o.Logger,
|
|
}
|
|
|
|
// initialize
|
|
if o.Init != "" {
|
|
if _, err := p.db.Exec(ctx, o.Init); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return p, nil
|
|
}
|
|
|
|
func (p *Persistor) TableExists(ctx context.Context, name string) (bool, error) {
|
|
var n int64
|
|
if err := p.db.QueryRow(ctx, `select 1 from information_schema.tables where table_name=$1`, name).Scan(&n); errors.Is(err, pgx.ErrNoRows) {
|
|
return false, nil
|
|
} else if err != nil {
|
|
return false, err
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
func (p *Persistor) Ping(ctx context.Context) error {
|
|
return p.db.Ping(ctx)
|
|
}
|
|
|
|
func (p *Persistor) Conn() *pgx.Conn {
|
|
return p.db
|
|
}
|
|
|
|
func (p *Persistor) Close(ctx context.Context) error {
|
|
return p.db.Close(ctx)
|
|
}
|