txmanager

package module
v1.0.0 Latest Latest
Warning

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

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

README

txmanager

txmanager is a Go library designed to simplify transaction management by providing a flexible and extensible interface for working with different database drivers. It supports custom adapters, allowing developers to integrate it with any database system that implements the required interfaces.

Installation

To install txmanager, run:

go get github.com/zhark0vv/txmanager

Key Features

  • Simple and flexible transaction management.
  • Support for custom database adapters.
  • Driver-agnostic interface for Query, Exec, and transaction handling.
  • Error-safe transactional workflow with automatic rollback on failure.

Interfaces

Adapter

The Adapter interface defines the methods required for a database adapter:

type Adapter interface {
    Begin(ctx context.Context) (Tx, error)                // Start a new transaction
    Query(ctx context.Context, sql string, args ...interface{}) (Rows, error) // Execute a query
    Exec(ctx context.Context, sql string, args ...interface{}) error          // Execute a command
}
Tx

The Tx interface represents a transaction:

type Tx interface {
    Commit(ctx context.Context) error   // Commit the transaction
    Rollback(ctx context.Context) error // Rollback the transaction
}
Rows

The Rows interface abstracts the result set of a query:

type Rows interface {
    Close()                   // Close the result set
    Next() bool               // Advance to the next row
    Scan(dest ...interface{}) error // Scan the current row into destination variables
}

Usage

Example: Using txmanager with the pgx Driver
package main

import (
    "context"
    "fmt"
    "log"

    "github.com/jackc/pgx/v4"
    "github.com/zhark0vv/txmanager"
)

func main() {
    ctx := context.Background()

    // Connect to the PostgreSQL database
    conn, err := pgx.Connect(ctx, "postgres://user:password@localhost:5432/db")
    if err != nil {
        log.Fatalf("Failed to connect to database: %v", err)
    }
    defer conn.Close(ctx)

    // Initialize transaction manager with pgx adapter
    manager := txmanager.New(txmanager.WithPgxAdapter(conn))

    // Start a transaction
    ctx, err = manager.Start(ctx)
    if err != nil {
        log.Fatalf("Failed to start transaction: %v", err)
    }

    // Ensure transaction is properly finished
    var txErr error
    defer func() {
        if err := manager.Finish(ctx, txErr); err != nil {
            log.Fatalf("Failed to finish transaction: %v", err)
        }
    }()

    // Execute a query within the transaction
    rows, txErr := manager.Query(ctx, "SELECT id, name FROM users")
    if txErr != nil {
        return
    }
    defer rows.Close()

    for rows.Next() {
        var id int
        var name string
        if err := rows.Scan(&id, &name); err != nil {
            log.Fatalf("Failed to scan row: %v", err)
        }
        fmt.Printf("User: %d, %s\n", id, name)
    }

    // Execute a command within the transaction
    txErr = manager.Exec(ctx, "UPDATE users SET active = $1 WHERE id = $2", true, 1)
    if txErr != nil {
        log.Fatalf("Failed to execute command: %v", txErr)
    }
}

Adapters

You can use already implemented adapters for popular database drivers:

  • txmanager.WithPgxAdapter(conn *pgx.Conn) - Use the pgx/v4 driver.
  • txmanager.WithSqlAdapter(db *sql.DB) - Use the database/sql driver.

Custom Adapters

You can implement your own adapter to work with a custom database or driver. A custom adapter must implement the Adapter interface.

Example: Custom Adapter for a Hypothetical Database
package customadapter

import (
    "context"
    "fmt"
    "pgxctx/pkg/txmanager"
)

// HypotheticalConn represents a connection to a custom database
type HypotheticalConn struct {}

// HypotheticalTx represents a transaction in the custom database
type HypotheticalTx struct {}

func (tx *HypotheticalTx) Commit(ctx context.Context) error {
    fmt.Println("Transaction committed")
    return nil
}

func (tx *HypotheticalTx) Rollback(ctx context.Context) error {
    fmt.Println("Transaction rolled back")
    return nil
}

type CustomAdapter struct {
    conn *HypotheticalConn
}

func NewCustomAdapter(conn *HypotheticalConn) *CustomAdapter {
    return &CustomAdapter{conn: conn}
}

func (a *CustomAdapter) Begin(ctx context.Context) (txmanager.Tx, error) {
    fmt.Println("Transaction started")
    return &HypotheticalTx{}, nil
}

func (a *CustomAdapter) Query(ctx context.Context, sql string, args ...interface{}) (txmanager.Rows, error) {
    fmt.Printf("Executing query: %s\n", sql)
    return nil, nil
}

func (a *CustomAdapter) Exec(ctx context.Context, sql string, args ...interface{}) error {
    fmt.Printf("Executing command: %s\n", sql)
    return nil
}

Advanced Configuration

manager := txmanager.New(
    txmanager.WithAdapter(customAdapter), // Use a custom adapter
)

License

txmanager is licensed under the MIT License. See the LICENSE file for more details.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Adapter

type Adapter interface {
	Begin(ctx context.Context) (Tx, error)
	Query(ctx context.Context, sql string, args ...interface{}) (Rows, error)
	Exec(ctx context.Context, sql string, args ...interface{}) error
	Select(ctx context.Context, dst interface{}, query string, args ...interface{}) error
	Get(ctx context.Context, dst interface{}, query string, args ...interface{}) error
}

Adapter представляет интерфейс для начала транзакций

type ContextManager

type ContextManager interface {
	Start(ctx context.Context) (context.Context, error)
	Finish(ctx context.Context, err error) error
	Query(ctx context.Context, sql string, args ...interface{}) (Rows, error)
	Exec(ctx context.Context, sql string, args ...interface{}) error
	Select(ctx context.Context, dst interface{}, query string, args ...interface{}) error
	Get(ctx context.Context, dst interface{}, query string, args ...interface{}) error
}

ContextManager управляет транзакциями на уровне сервисного слоя

func New

func New(opts ...Option) ContextManager

type Option

type Option func(*contextManager)

func WithAdapter

func WithAdapter(adapter Adapter) Option

func WithLogging

func WithLogging(logger *log.Logger) Option

func WithPgxAdapter

func WithPgxAdapter(conn PgxConn) Option

type PgxAdapter

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

func (*PgxAdapter) Begin

func (a *PgxAdapter) Begin(ctx context.Context) (Tx, error)

func (*PgxAdapter) Exec

func (a *PgxAdapter) Exec(ctx context.Context, sql string, args ...interface{}) error

func (*PgxAdapter) Get added in v1.0.0

func (a *PgxAdapter) Get(ctx context.Context, dest interface{}, sql string, args ...interface{}) error

func (*PgxAdapter) Query

func (a *PgxAdapter) Query(ctx context.Context, sql string, args ...interface{}) (Rows, error)

func (*PgxAdapter) Select added in v1.0.0

func (a *PgxAdapter) Select(ctx context.Context, dest interface{}, sql string, args ...interface{}) error

type PgxConn

type PgxConn interface {
	Begin(ctx context.Context) (pgx.Tx, error)
	Query(ctx context.Context, sql string, args ...interface{}) (pgx.Rows, error)
	Exec(ctx context.Context, sql string, args ...interface{}) (pgconn.CommandTag, error)
}

type PgxTx

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

func (*PgxTx) Commit

func (t *PgxTx) Commit(ctx context.Context) error

func (*PgxTx) Rollback

func (t *PgxTx) Rollback(ctx context.Context) error

type Rows

type Rows interface {
	Scan(dest ...interface{}) error
	Next() bool
	Close()
}

type Tx

type Tx interface {
	Commit(ctx context.Context) error
	Rollback(ctx context.Context) error
}

Tx - interface for transaction

Jump to

Keyboard shortcuts

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