database

package module
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 2, 2026 License: MIT Imports: 11 Imported by: 0

README

gas-database

Test Go Reference Go Version License

Database connection service for the Gas ecosystem. Wraps database/sql and native pgxpool to provide connection management, transaction helpers, and sqlc compatibility.

Install

go get github.com/gasmod/gas-database

Modes

Mode Backend Use case
database.ModeSQL (default) database/sql Any driver: PostgreSQL, SQLite, MySQL, etc.
database.ModePgx pgxpool.Pool Native pgx for PostgreSQL (better performance, pgx types, batch queries)

In both modes, DB() returns a *sql.DB so sqlc database/sql mode always works. In pgx mode, Pool() additionally returns the native *pgxpool.Pool for sqlc pgx mode.

Usage

Basic setup (database/sql)
package main

import (
	_ "github.com/jackc/pgx/v5/stdlib" // register pgx as database/sql driver

	"github.com/gasmod/gas"
	database "github.com/gasmod/gas-database"
)

func main() {
	app := gas.NewApp(
		gas.WithService[*database.Service](
			database.New(database.WithConfig(&database.Config{
				Database: database.Settings{
					DSN:    "postgres://user:pass@localhost:5432/mydb?sslmode=disable",
					Driver: "pgx",
				},
			})),
			gas.ServiceLifetimeSingleton,
		),
		// ...
	)

	app.Run()
}
Native pgx mode
database.New(database.WithConfig(&database.Config{
	Database: database.Settings{
		Mode: database.ModePgx,
		DSN:  "postgres://user:pass@localhost:5432/mydb?sslmode=disable",
	},
}))

// After Init(), both are available:
// svc.DB()   -> *sql.DB (via stdlib adapter)
// svc.Pool() -> *pgxpool.Pool
Using a connector (sql.OpenDB)

When you need full control over connection setup (e.g., custom TLS, auth tokens), pass a driver.Connector directly:

import "github.com/jackc/pgx/v5/stdlib"

connConfig, _ := pgx.ParseConfig("postgres://user:pass@localhost:5432/mydb")
connector := stdlib.GetConnector(*connConfig)

database.New(database.WithConnector(connector))

When a connector is provided, Database.Driver and Database.DSN are not required.

SQLite
import _ "modernc.org/sqlite"

database.New(database.WithConfig(&database.Config{
	Database: database.Settings{
		Driver: "sqlite",
		DSN:    "./app.db",
	},
}))
Dependency injection

Services receive the database through gas.DatabaseProvider via constructor injection:

// gas-auth/service.go
type Service struct {
	db gas.DatabaseProvider
}

func New(db gas.DatabaseProvider) *Service {
	return &Service{db: db}
}

func (s *Service) Init() error {
	s.queries = authdb.New(s.db.DB()) // sqlc database/sql mode
	return nil
}

For services that want native pgx access, define a local interface and type-assert:

// gas-auth/providers.go
type PgxProvider interface {
	Pool() *pgxpool.Pool
}

// gas-auth/service.go
func (s *Service) Init() error {
	if pp, ok := s.db.(PgxProvider); ok && pp.Pool() != nil {
		s.queries = authdb.New(pp.Pool()) // sqlc pgx mode
	} else {
		s.queries = authdb.New(s.db.DB()) // fallback to database/sql
	}
	return nil
}
Transactions

Manual transaction management:

tx, err := dbSvc.BeginTx(ctx, nil)
if err != nil {
	return err
}
// use tx with sqlc: queries.WithTx(tx)
err = tx.Commit()

Automatic commit/rollback with WithTx:

err := dbSvc.WithTx(ctx, nil, func(tx *sql.Tx) error {
	qtx := queries.WithTx(tx)
	if err := qtx.CreateUser(ctx, params); err != nil {
		return err // triggers rollback
	}
	return qtx.CreateProfile(ctx, params) // commits if nil
})

WithTx also rolls back on panic.

Health and readiness probes

Service implements gas.HealthReporter and gas.ReadyReporter, auto-discovered by gas core:

  • CheckHealth (liveness) — fails only when the service is uninitialized or closed. It does not ping the database, because database/sql and pgxpool both auto-reconnect; a transient outage should not trigger a pod restart.
  • CheckReady (readiness) — pings the database. A failure signals that traffic should drain off this instance until the dependency recovers.

Config

If WithConfig is not provided, the service automatically binds configuration from the gas.ConfigProvider injected via DI. This lets you drive database settings from environment variables or a config file without any explicit wiring.

Field Default Description
Database.Mode "sql" Backend mode: "sql" or "pgx"
Database.Driver "postgres" database/sql driver name (ModeSQL only)
Database.DSN Connection string (required unless using WithConnector)
Database.MaxOpenConns 25 Max open connections
Database.MaxIdleConns 5 Max idle connections (ModeSQL only)
Database.ConnMaxLifetime 30m Max connection reuse time
Database.ConnMaxIdleTime 5m Max connection idle time
Database.ConnRetries 0 Number of connection retry attempts (0 = no retries)
Database.ConnRetryInterval 2s Base retry interval; doubles each attempt (exp. backoff)

DBTX Interface

The package exports a DBTX interface matching what sqlc generates. Both *sql.DB and *sql.Tx satisfy it:

type DBTX interface {
	ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
	PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
	QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
	QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
}

Documentation

Overview

Package database provides database connection management for the Gas ecosystem with database/sql and pgx backends. Provides transaction helpers, sqlc integration, and connection retry with exponential backoff.

See the module README for usage examples and design rationale.

SPDX-License-Identifier: MIT

Index

Constants

View Source
const (
	// ModeSQL uses database/sql with any registered driver.
	ModeSQL = "sql"

	// ModePgx uses native pgxpool.Pool for PostgreSQL. DB() still works
	// via the pgx stdlib adapter. Pool() returns the native pool for
	// sqlc pgx mode.
	ModePgx = "pgx"
)

Mode selects the database backend.

View Source
const (
	// DriverPostgres defines the constant for the PostgreSQL database driver.
	DriverPostgres = "postgres"

	// DriverPgx represents the const string identifier for the "pgx" database driver.
	DriverPgx = "pgx"

	// DriverSQLite represents the identifier for the SQLite database driver.
	DriverSQLite = "sqlite"
)

Variables

This section is empty.

Functions

func New

func New(opts ...Option) func(gas.ConfigProvider, gas.Logger) *Service

New captures options and returns a DI-injectable constructor. The returned func receives gas.ConfigProvider from the DI container.

Types

type Config

type Config struct {
	env.WithGasEnv

	Database Settings
	// contains filtered or unexported fields
}

Config holds database connection settings.

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns a Config with sensible defaults using database/sql.

func (*Config) Validate

func (c *Config) Validate() error

Validate checks the Config struct for correctness and returns an error if any validation rule is violated. nolint:cyclop,gocyclo // intentionally complex

type DBTX

type DBTX interface {
	ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
	PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
	QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
	QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
}

DBTX is the interface that sqlc-generated code expects. Both *sql.DB and *sql.Tx satisfy it, making it easy to swap between pooled and transactional access.

type Option

type Option func(*Service)

Option configures a Service.

func WithConfig

func WithConfig(cfg *Config) Option

WithConfig sets the database configuration.

func WithConnector

func WithConnector(c driver.Connector) Option

WithConnector sets a driver.Connector for ModeSQL. When provided, sql.OpenDB(connector) is used instead of sql.Open(driver, dsn), and DatabaseDriver / DatabaseDSN are not required.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service manages a database connection and implements both gas.Service and gas.DatabaseProvider. In ModeSQL it wraps *sql.DB with any driver. In ModePgx it creates a native pgxpool.Pool and derives *sql.DB from it via the pgx stdlib adapter, so DB() always works regardless of mode.

func (*Service) BeginTx

func (s *Service) BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error)

BeginTx starts a new database transaction. The caller is responsible for calling Commit or Rollback on the returned *sql.Tx.

func (*Service) CheckHealth

func (s *Service) CheckHealth(_ context.Context) error

CheckHealth reports liveness. It only fails for states a restart would resolve (uninitialized or closed). Transient connectivity issues are surfaced via CheckReady instead, since database/sql and pgxpool both auto-reconnect.

func (*Service) CheckReady

func (s *Service) CheckReady(ctx context.Context) error

CheckReady reports readiness by pinging the database. A failure here means traffic should not be routed to this instance until the dependency is reachable again.

func (*Service) Close

func (s *Service) Close() error

Close closes the underlying database connections.

func (*Service) DB

func (s *Service) DB() *sql.DB

DB returns the underlying *sql.DB. This satisfies gas.DatabaseProvider and works in both ModeSQL and ModePgx (via stdlib adapter).

func (*Service) Driver

func (s *Service) Driver() string

Driver returns the database driver name based on the configured mode and settings.

func (*Service) Exec

func (s *Service) Exec(ctx context.Context, query string, args ...any) (gas.Result, error)

Exec executes a query that doesn't return rows. The returned gas.Result is backed by sql.Result which natively satisfies the interface.

func (*Service) Init

func (s *Service) Init() error

Init opens the database connection, configures the pool, and pings the database to verify connectivity.

func (*Service) Name

func (s *Service) Name() string

Name returns the service identifier.

func (*Service) Ping

func (s *Service) Ping(ctx context.Context) error

Ping verifies the database connection is still alive.

func (*Service) Pool

func (s *Service) Pool() *pgxpool.Pool

Pool returns the native pgxpool.Pool. Returns nil when running in ModeSQL. Consuming services that want native pgx access can define a local interface (e.g., type PgxProvider interface { Pool() *pgxpool.Pool }) and type-assert the DatabaseProvider.

func (*Service) Query

func (s *Service) Query(ctx context.Context, query string, args ...any) (gas.Rows, error)

Query executes a query that returns rows. The returned gas.Rows is backed by *sql.Rows which natively satisfies the interface.

func (*Service) WithTx

func (s *Service) WithTx(ctx context.Context, opts *sql.TxOptions, fn func(*sql.Tx) error) (err error)

WithTx executes fn within a transaction. If fn returns nil the transaction is committed; otherwise it is rolled back. Any panic inside fn also triggers a rollback.

type Settings

type Settings struct {
	// Mode selects the backend: ModeSQL (default) or ModePgx.
	Mode string

	// Driver is the database/sql driver name (e.g., "postgres", "pgx", "sqlite").
	// Only used in ModeSQL.
	Driver string

	// DSN is the data source name (connection string).
	DSN string

	// MaxOpenConns is the maximum number of open connections to the database.
	MaxOpenConns int32

	// MaxIdleConns is the maximum number of idle connections in the pool.
	// Only used in ModeSQL; pgx manages idle connections internally.
	MaxIdleConns int

	// ConnMaxLifetime is the maximum amount of time a connection may be reused.
	ConnMaxLifetime time.Duration

	// ConnMaxIdleTime is the maximum amount of time a connection may be idle.
	ConnMaxIdleTime time.Duration

	// ConnRetries is the number of times to retry connecting to the database
	// on failure. 0 means no retries (fail immediately).
	ConnRetries int

	// ConnRetryInterval is the base interval between connection retry attempts.
	// The interval doubles after each failed attempt (exponential backoff).
	ConnRetryInterval time.Duration
}

Settings represents the configuration required to establish and manage database connections.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL