Skip to content

gasmod/gas-database

Repository files navigation

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
}

About

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

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors