Documentation
¶
Overview ¶
Package transactor provides a decorator for r3.CRUD[T, ID] that surfaces transaction capabilities from the underlying driver.
It follows the same decorator pattern as features/softdelete and features/history: the decorator wraps any r3.CRUD[T, ID] and transparently satisfies the same interface, passing all six CRUD methods through to the inner implementation.
Transaction support in r3 is opt-in. Drivers that support transactions implement the r3.Transactor interface (BeginTx). The decorator delegates to the inner CRUD if it satisfies Transactor; otherwise r3.ErrTransactionsNotSupported is returned.
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 ¶
- type CRUD
- func (c *CRUD[T, ID]) BeginTx(ctx context.Context) (r3.TxCRUD[T, ID], error)
- func (c *CRUD[T, ID]) Count(ctx context.Context, qarg ...r3.Query) (int64, error)
- func (c *CRUD[T, ID]) Create(ctx context.Context, entity T) (T, error)
- func (c *CRUD[T, ID]) Delete(ctx context.Context, id ID) error
- func (c *CRUD[T, ID]) Get(ctx context.Context, id ID, qarg ...r3.Query) (T, error)
- func (c *CRUD[T, ID]) InTx(ctx context.Context, fn func(tx r3.CRUD[T, ID]) error) error
- func (c *CRUD[T, ID]) Inner() r3.CRUD[T, ID]
- func (c *CRUD[T, ID]) List(ctx context.Context, qarg ...r3.Query) ([]T, int64, error)
- func (c *CRUD[T, ID]) Patch(ctx context.Context, entity T, fields r3.Fields) (T, error)
- func (c *CRUD[T, ID]) SupportsTransactions() bool
- func (c *CRUD[T, ID]) Unwrap() r3.CRUD[T, ID]
- func (c *CRUD[T, ID]) Update(ctx context.Context, entity T) (T, error)
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 is a decorator that wraps any r3.CRUD[T, ID] and adds transaction capabilities. All six standard CRUD methods are passed through to the inner implementation unchanged.
Transaction operations (BeginTx) are delegated to the inner CRUD if it implements the r3.Transactor interface. Otherwise, r3.ErrTransactionsNotSupported is returned.
func WithTransactor ¶
func WithTransactor[T any, ID comparable](inner r3.CRUD[T, ID]) *CRUD[T, ID]
WithTransactor wraps an existing r3.CRUD with transaction capabilities. All standard CRUD methods pass through unchanged.
func (*CRUD[T, ID]) BeginTx ¶
BeginTx starts a transaction if the underlying backend supports it.
It walks the decorator chain below the transactor to the backend, begins the transaction there, and re-applies the same decorator stack on top of it — so the returned r3.TxCRUD is fully decorated and writes inside the transaction are still validated, audited, permission-checked, etc.
Returns r3.ErrTransactionsNotSupported if no layer in the chain implements r3.Transactor.
func (*CRUD[T, ID]) InTx ¶
InTx runs fn inside a transaction if the inner CRUD supports it. It begins a transaction, calls fn with a transactional CRUD, and:
- commits if fn returns nil
- rolls back if fn returns an error or panics
Returns r3.ErrTransactionsNotSupported if the inner CRUD does not implement r3.Transactor.
func (*CRUD[T, ID]) SupportsTransactions ¶
SupportsTransactions reports whether the underlying backend supports transactions (seen through any decorators between the transactor and the backend), and can therefore be used with BeginTx / InTx.