database

package
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Aug 16, 2025 License: MIT Imports: 14 Imported by: 0

README

Database Infrastructure

This package provides database infrastructure components for the GraphQL service, including connection management, transaction handling, and database migrations.

Components

Connection Management (connection.go)

The DB struct wraps the standard sql.DB with additional functionality:

  • Connection Pooling: Configurable connection pool settings
  • Health Checks: Built-in health check functionality
  • Logging: Structured logging for database operations
  • URL Masking: Secure logging of database URLs
db, err := database.NewConnection(cfg.Database, logger)
if err != nil {
    return fmt.Errorf("failed to create database connection: %w", err)
}
defer db.Close()
Transaction Management (transaction.go)

Provides utilities for handling database transactions:

  • Automatic Rollback: Transactions are automatically rolled back on errors or panics
  • Logging: Transaction operations are logged with duration and status
  • Options Support: Custom transaction options (isolation levels, read-only, etc.)
err := db.WithTransaction(ctx, func(tx *sql.Tx) error {
    // Your transactional operations here
    return nil
})
Migration Management (migration.go)

Handles database schema migrations using golang-migrate:

  • Automatic Migration: Run all pending migrations on startup
  • Rollback Support: Rollback migrations when needed
  • Version Tracking: Track current migration version
  • Dirty State Detection: Detect and handle dirty migration states
migrationManager := database.NewMigrationManager(db, logger)
err := migrationManager.RunMigrations(ctx, "./migrations")
Database Manager (database.go)

Provides a unified interface for all database components:

manager, err := database.NewManager(cfg.Database, logger)
if err != nil {
    return err
}

// Initialize with migrations
err = manager.Initialize(ctx, "./migrations")
if err != nil {
    return err
}

defer manager.Close()

Configuration

Database configuration is handled through the config.DatabaseConfig struct:

database:
  url: "postgres://user:password@localhost:5432/dbname?sslmode=disable"
  max_open_conns: 25
  max_idle_conns: 5
  conn_max_lifetime: "5m"
  conn_max_idle_time: "1m"

Migrations

Migration files should be placed in the migrations/ directory with the following naming convention:

  • {version}_{description}.up.sql - Forward migration
  • {version}_{description}.down.sql - Rollback migration

Example:

  • 001_create_users_table.up.sql
  • 001_create_users_table.down.sql

Testing

Unit Tests

Unit tests are provided for core functionality and can be run without a database:

go test ./internal/infrastructure/database/...
Integration Tests

Integration tests require a test database and are automatically skipped if TEST_DATABASE_URL is not set:

export TEST_DATABASE_URL="postgres://user:password@localhost:5432/test_db?sslmode=disable"
go test ./internal/infrastructure/persistence/sql/...

Usage Example

package main

import (
    "context"
    "log/slog"
    
    "github.com/captain-corgi/go-graphql-example/internal/infrastructure/config"
    "github.com/captain-corgi/go-graphql-example/internal/infrastructure/database"
    "github.com/captain-corgi/go-graphql-example/internal/infrastructure/persistence/sql"
)

func main() {
    // Load configuration
    cfg, err := config.Load()
    if err != nil {
        panic(err)
    }
    
    // Create logger
    logger := slog.Default()
    
    // Create database manager
    dbManager, err := database.NewManager(cfg.Database, logger)
    if err != nil {
        panic(err)
    }
    defer dbManager.Close()
    
    // Initialize database (run migrations)
    ctx := context.Background()
    err = dbManager.Initialize(ctx, "./migrations")
    if err != nil {
        panic(err)
    }
    
    // Create repository
    userRepo := sql.NewUserRepository(dbManager.DB, logger)
    
    // Use repository...
}

Error Handling

The database infrastructure provides comprehensive error handling:

  • Connection Errors: Detailed error messages for connection failures
  • Transaction Errors: Automatic rollback with error context
  • Migration Errors: Clear error messages for migration failures
  • Constraint Violations: Domain-specific error mapping for database constraints

Security Considerations

  • Database URLs are masked in logs to prevent credential exposure
  • Prepared statements are used to prevent SQL injection
  • Connection pooling limits are enforced to prevent resource exhaustion
  • Transaction timeouts prevent long-running operations from blocking resources

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type DB

type DB struct {
	*sql.DB
	// contains filtered or unexported fields
}

DB wraps the database connection with additional functionality

func NewConnection

func NewConnection(cfg config.DatabaseConfig, logger *slog.Logger) (*DB, error)

NewConnection creates a new database connection with proper configuration

func TestDBSetup

func TestDBSetup(t *testing.T, migrationsPath string) (*DB, func())

TestDBSetup is a helper function for setting up test database in test suites

func TestDBSetupWithConfig

func TestDBSetupWithConfig(t *testing.T, cfg TestDBConfig, migrationsPath string) (*DB, func())

TestDBSetupWithConfig is a helper function for setting up test database with custom config

func (*DB) Close

func (db *DB) Close() error

Close closes the database connection

func (*DB) Health

func (db *DB) Health(ctx context.Context) error

Health checks the database connection health

func (*DB) Stats

func (db *DB) Stats() sql.DBStats

Stats returns database connection statistics

func (*DB) WithTransaction

func (db *DB) WithTransaction(ctx context.Context, fn TxFunc) error

WithTransaction executes a function within a database transaction If the function returns an error, the transaction is rolled back Otherwise, the transaction is committed

func (*DB) WithTransactionOptions

func (db *DB) WithTransactionOptions(ctx context.Context, opts *sql.TxOptions, fn TxFunc) error

WithTransactionOptions executes a function within a database transaction with custom options

type Manager

type Manager struct {
	DB               *DB
	TxManager        *TxManager
	MigrationManager *MigrationManager
	// contains filtered or unexported fields
}

Manager manages database connections, migrations, and transactions

func NewManager

func NewManager(cfg config.DatabaseConfig, logger *slog.Logger) (*Manager, error)

NewManager creates a new database manager with all components

func (*Manager) Close

func (m *Manager) Close() error

Close closes all database connections

func (*Manager) Health

func (m *Manager) Health(ctx context.Context) error

Health checks the health of all database components

func (*Manager) Initialize

func (m *Manager) Initialize(ctx context.Context, migrationsPath string) error

Initialize sets up the database by running migrations

type MigrationManager

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

MigrationManager handles database migrations

func NewMigrationManager

func NewMigrationManager(db *DB, logger *slog.Logger) *MigrationManager

NewMigrationManager creates a new migration manager

func (*MigrationManager) GetMigrationVersion

func (mm *MigrationManager) GetMigrationVersion(ctx context.Context, migrationsPath string) (uint, bool, error)

GetMigrationVersion returns the current migration version

func (*MigrationManager) RollbackMigration

func (mm *MigrationManager) RollbackMigration(ctx context.Context, migrationsPath string) error

RollbackMigration rolls back the last migration

func (*MigrationManager) RunMigrations

func (mm *MigrationManager) RunMigrations(ctx context.Context, migrationsPath string) error

RunMigrations executes all pending database migrations

type TestDBConfig

type TestDBConfig struct {
	BaseURL         string
	TestDBName      string
	MaxOpenConns    int
	MaxIdleConns    int
	ConnMaxLifetime time.Duration
	ConnMaxIdleTime time.Duration
}

TestDBConfig holds configuration for test database setup

func DefaultTestDBConfig

func DefaultTestDBConfig() TestDBConfig

DefaultTestDBConfig returns default test database configuration

type TestDBManager

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

TestDBManager manages test database lifecycle

func NewTestDBManager

func NewTestDBManager(t *testing.T, cfg TestDBConfig) *TestDBManager

NewTestDBManager creates a new test database manager

func (*TestDBManager) CleanupTestDB

func (tm *TestDBManager) CleanupTestDB(t *testing.T)

CleanupTestDB drops the test database and closes connections

func (*TestDBManager) CreateTestDB

func (tm *TestDBManager) CreateTestDB(t *testing.T) *DB

CreateTestDB creates a new test database

func (*TestDBManager) ExecuteSQL

func (tm *TestDBManager) ExecuteSQL(t *testing.T, sql string, args ...interface{})

ExecuteSQL executes arbitrary SQL on the test database (useful for test setup)

func (*TestDBManager) GetTestDB

func (tm *TestDBManager) GetTestDB(t *testing.T) *DB

GetTestDB returns the test database connection (creates if not exists)

func (*TestDBManager) QueryRow

func (tm *TestDBManager) QueryRow(t *testing.T, sql string, args ...interface{}) *sql.Row

QueryRow executes a query that returns a single row

func (*TestDBManager) RunMigrations

func (tm *TestDBManager) RunMigrations(t *testing.T, migrationsPath string)

RunMigrations runs migrations on the test database

func (*TestDBManager) TruncateAllTables

func (tm *TestDBManager) TruncateAllTables(t *testing.T)

TruncateAllTables truncates all tables in the test database (useful for test cleanup)

type TxFunc

type TxFunc func(tx *sql.Tx) error

TxFunc represents a function that executes within a transaction

type TxManager

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

TxManager provides transaction management utilities

func NewTxManager

func NewTxManager(db *DB, logger *slog.Logger) *TxManager

NewTxManager creates a new transaction manager

func (*TxManager) Execute

func (tm *TxManager) Execute(ctx context.Context, operation string, fn TxFunc) error

Execute runs a function within a transaction with logging

func (*TxManager) ExecuteWithOptions

func (tm *TxManager) ExecuteWithOptions(ctx context.Context, operation string, opts *sql.TxOptions, fn TxFunc) error

ExecuteWithOptions runs a function within a transaction with custom options and logging

Jump to

Keyboard shortcuts

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