git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/db/db.go (about)

     1  package db
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"time"
     7  
     8  	// import pgx driver
     9  	_ "github.com/jackc/pgx/v5/stdlib"
    10  	"github.com/jmoiron/sqlx"
    11  )
    12  
    13  // Queryer allows to query a database.
    14  type Queryer interface {
    15  	Get(ctx context.Context, dest any, query string, args ...any) error
    16  	Select(ctx context.Context, dest any, query string, args ...any) error
    17  	Query(ctx context.Context, query string, args ...any) (*sql.Rows, error)
    18  	Exec(ctx context.Context, query string, args ...any) (sql.Result, error)
    19  	Rebind(query string) (ret string)
    20  }
    21  
    22  // DB represents a pool of zero or more underlying connections. It must be safe for concurrent use
    23  // by multiple goroutines.
    24  type DB interface {
    25  	Ping(ctx context.Context) error
    26  	SetMaxIdleConns(n int)
    27  	SetMaxOpenConns(n int)
    28  	SetConnMaxLifetime(d time.Duration)
    29  	Stats() sql.DBStats
    30  	Queryer
    31  	Txer
    32  }
    33  
    34  // Txer is the ability to start transactions
    35  type Txer interface {
    36  	Begin(ctx context.Context) (Tx, error)
    37  	BeginTx(ctx context.Context, opts *sql.TxOptions) (Tx, error)
    38  	Transaction(ctx context.Context, fn func(tx Tx) error) (err error)
    39  }
    40  
    41  // Tx represents an in-progress database transaction.
    42  type Tx interface {
    43  	Commit() error
    44  	Rollback() error
    45  	Queryer
    46  }
    47  
    48  // Connect to a database and verify the connections with a ping.
    49  // See https://www.alexedwards.net/blog/configuring-sqldb
    50  // and https://making.pusher.com/production-ready-connection-pooling-in-go
    51  // https://brandur.org/fragments/postgres-parameters
    52  // for the details
    53  func Connect(databaseURL string, poolSize int) (ret *Database, err error) {
    54  	sqlxDB, err := sqlx.Connect("pgx", databaseURL)
    55  	if err != nil {
    56  		return
    57  	}
    58  
    59  	ret = &Database{
    60  		sqlxDB: sqlxDB,
    61  	}
    62  
    63  	ret.SetMaxOpenConns(poolSize)
    64  	ret.SetMaxIdleConns(int(poolSize / 2))
    65  	ret.SetConnMaxLifetime(30 * time.Minute)
    66  	return
    67  }