transactor

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Aug 16, 2026 License: MIT Imports: 2 Imported by: 0

Documentation

Overview

Package transactor decorates any r3.CRUD[T, ID] to surface the driver's transaction support, transparently satisfying the same interface and passing standard methods through to the inner repo.

Transactions in r3 are opt-in: drivers that support them implement r3.Transactor (BeginTx). The decorator delegates when the inner CRUD satisfies it, else returns r3.ErrTransactionsNotSupported.

Supported drivers

All SQL-based drivers support transactions out of the box:

  • r3pgx (PostgreSQL via pgx)
  • r3pq (PostgreSQL via lib/pq)
  • r3mysql (MySQL)
  • r3sqlite3 (SQLite)
  • r3gorm (GORM)
  • r3bun (Bun)
  • r3gopg (go-pg)

MongoDB (r3mongo) does not currently implement Transactor.

Usage

inner := r3pgx.NewPgxCRUD[User, int64](db)
repo := transactor.WithTransactor[User, int64](inner)

// repo satisfies r3.CRUD[User, int64] - all methods pass through.
// Additionally:
repo.SupportsTransactions() // true for SQL drivers

// Start a transaction manually:
tx, err := repo.BeginTx(ctx)
if err != nil { ... }
defer tx.Rollback()
tx.Create(ctx, user)
tx.Commit()

// Or use the convenience helper:
err := repo.InTx(ctx, func(tx r3.CRUD[User, int64]) error {
    _, err := tx.Create(ctx, user)
    return err
})

Composability

The decorator can be stacked with other feature decorators:

repo := transactor.WithTransactor(
    history.WithHistory(
        softdelete.WithSoftDelete(inner), store, ...opts),
)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CRUD

type CRUD[T any, ID comparable] struct {
	// contains filtered or unexported fields
}

CRUD adds transaction capabilities to the inner repo (BeginTx delegated when it implements r3.Transactor, else r3.ErrTransactionsNotSupported); standard methods pass through unchanged. See the package doc.

func WithTransactor

func WithTransactor[T any, ID comparable](inner r3.CRUD[T, ID]) *CRUD[T, ID]

WithTransactor wraps inner with transaction capabilities.

func (*CRUD[T, ID]) Aggregate added in v0.0.3

func (c *CRUD[T, ID]) Aggregate(ctx context.Context, qarg ...r3.Query) ([]r3.AggregateRow, error)

Aggregate passes through to the inner CRUD's Aggregate.

func (*CRUD[T, ID]) AggregateThroughRelation added in v0.0.5

func (c *CRUD[T, ID]) AggregateThroughRelation(
	ctx context.Context, relation string, qarg ...r3.Query,
) ([]r3.AggregateRow, error)

AggregateThroughRelation passes through to the inner CRUD.

func (*CRUD[T, ID]) BeginTx

func (c *CRUD[T, ID]) BeginTx(ctx context.Context) (r3.TxCRUD[T, ID], error)

BeginTx starts a transaction if the backend supports it. It walks the chain below the transactor to the backend, begins the transaction there, and re-applies the same decorator stack on top - so the returned r3.TxCRUD is fully decorated and in-transaction writes are still validated, audited, permission-checked, etc. Returns r3.ErrTransactionsNotSupported if no layer implements r3.Transactor.

func (*CRUD[T, ID]) Count

func (c *CRUD[T, ID]) Count(ctx context.Context, qarg ...r3.Query) (int64, error)

Count passes through to the inner CRUD.

func (*CRUD[T, ID]) Create

func (c *CRUD[T, ID]) Create(ctx context.Context, entity T) (T, error)

Create passes through to the inner CRUD.

func (*CRUD[T, ID]) Delete

func (c *CRUD[T, ID]) Delete(ctx context.Context, id ID) error

Delete passes through to the inner CRUD.

func (*CRUD[T, ID]) Get

func (c *CRUD[T, ID]) Get(ctx context.Context, id ID, qarg ...r3.Query) (T, error)

Get passes through to the inner CRUD.

func (*CRUD[T, ID]) InTx

func (c *CRUD[T, ID]) InTx(ctx context.Context, fn func(tx r3.CRUD[T, ID]) error) error

InTx runs fn inside a transaction (if supported), committing when fn returns nil and rolling back on an error or panic. Returns r3.ErrTransactionsNotSupported if the inner CRUD does not implement r3.Transactor.

func (*CRUD[T, ID]) Inner

func (c *CRUD[T, ID]) Inner() r3.CRUD[T, ID]

Inner returns the wrapped CRUD (for advanced usage / unwrapping).

func (*CRUD[T, ID]) List

func (c *CRUD[T, ID]) List(ctx context.Context, qarg ...r3.Query) ([]T, int64, error)

List passes through to the inner CRUD.

func (*CRUD[T, ID]) Patch

func (c *CRUD[T, ID]) Patch(ctx context.Context, entity T, fields r3.Fields) (T, error)

Patch passes through to the inner CRUD.

func (*CRUD[T, ID]) PatchWhere added in v0.0.4

func (c *CRUD[T, ID]) PatchWhere(
	ctx context.Context, filters r3.Filters, entity T, fields r3.Fields,
) (int64, error)

PatchWhere passes through to the inner CRUD's BulkPatcher capability.

func (*CRUD[T, ID]) SupportsTransactions

func (c *CRUD[T, ID]) SupportsTransactions() bool

SupportsTransactions reports whether the backend (seen through any decorators below the transactor) supports transactions, and so can use BeginTx / InTx.

func (*CRUD[T, ID]) Unwrap

func (c *CRUD[T, ID]) Unwrap() r3.CRUD[T, ID]

Unwrap returns the wrapped CRUD so decorator-chain walks (capability detection, transaction propagation) can reach the backend.

func (*CRUD[T, ID]) Update

func (c *CRUD[T, ID]) Update(ctx context.Context, entity T) (T, error)

Update passes through to the inner CRUD.

func (*CRUD[T, ID]) Upsert added in v0.0.4

func (c *CRUD[T, ID]) Upsert(ctx context.Context, entity T, opts ...r3.UpsertOption) (T, error)

Upsert passes through to the inner CRUD's Upserter capability, so an upsert run inside InTx participates in the transaction like any other write.

Jump to

Keyboard shortcuts

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