autotx

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Oct 28, 2021 License: MIT Imports: 6 Imported by: 0

README

autotx

Test Status GoDoc

Golang transaction manager that supports rollback and retry on error

See package docs for documentation

Documentation

Overview

Package autotx provides wrappers for managing the lifecycle of a transaction and handling retries.

With the raw sql library, a transactional operation looks something like

tx, err := db.BeginTx(ctx)
if err != nil {
    return err
}
_, err := tx.ExecContext(ctx, "INSERT INTO dinosaurs VALUES (?)", "Nothronychus")
if err != nil {
    tx.Rollback()
    return err
}
return tx.Commit()

It can get repetitive and be easy to forget to call Rollback on every error. Also, in this example, panics are not handled, and the error from Rollback is discarded.

Manage the transaction lifecycle

Using the The Transact function wraps the transactional operation, committing on completion, or rolling back the transaction on error or panic. This can simplify operations significantly. The operation above would look like

autotx.Transact(ctx, db, func(tx *sql.Tx) error {
    _, err := tx.ExecContext(ctx, "INSERT INTO dinosaurs VALUES (?)", "Nothronychus")
    return err
})

The TransactWithRetry function behaves identically like the Transact function, but will retry errors returned by the operation according to policies defined in autotx.RetryOptions{}.

autotx.TransactWithRetry(ctx, db, autotx.RetryOptions{}, func(tx *sql.Tx) error {
    _, err := tx.ExecContext(ctx, "INSERT INTO dinosaurs VALUES (?)", "Nothronychus")
    return err
}

Index

Constants

View Source
const (
	// DefaultInitialBackoff configures the initial backoff interval.
	DefaultInitialBackOff = 10 * time.Millisecond
	// DefaultMaxBackoff configures the maximum backoff interval.
	DefaultMaxBackOff = 1 * time.Second
	// DefaultBackOffFactor configues the factor the previous backoff interval will be multiplied by
	// to get the next backoff.
	DefaultBackOffFactor = 2
)

Variables

View Source
var DefaultIsRetryable = alwaysRetryable

DefaultIsRetryable configures the default function for determining whether the error returned from the operation is retryable. By default, all errors are retryable. A RollbackErr is never retryable..

View Source
var DefaultMaxRetries = 5

DefaultMaxRetries configures the default number of max retries attempted by TransactWithRetry.

Functions

func Transact

func Transact(ctx context.Context, conn *sqlx.DB, operation func(tx *sqlx.Tx) error) (err error)

Transact executes the operation inside a transaction, committing the transaction on completion. If the operation returns an error or panic, the transaction will be rolled back, returning the original error or propagating the original panic. If the rollback caused by an error also receives an error, a RollbackErr will be returned. If the rollback caused by a panic returns an error, the error message and original panic merged and propagated as a new panic.

func TransactWithOptions

func TransactWithOptions(ctx context.Context, conn *sqlx.DB, operation func(tx *sqlx.Tx) error) (err error)

TransactWithOptions executes the operation inside a transaction, committing the transaction on completion. If the operation returns an error or panic, the transaction will be rolled back, returning the original error or propagating the original panic. If the rollback caused by an error also receives an error, a RollbackErr will be returned. If the rollback caused by a panic returns an error, the error message and original panic merged and propagated as a new panic.

The provided TxOptions is optional and may be nil if defaults should be used. If a non-default isolation level is used that the driver doesn't support, an error will be returned.

func TransactWithRetry

func TransactWithRetry(ctx context.Context, conn *sqlx.DB, retry RetryOptions, operation func(tx *sqlx.Tx) error) error

TransactWithRetry runs the operation using Transact, performing retries according to RetryOptions. If all retries fail, the error from the last attempt will be returned. If a rollback fails, no further attempts will be made and the RollbackErr will be returned.

Since the transaction operation may be executed multiple times, it is important that any mutations it applies to application state (outside the database) be idempotent.

func TransactWithRetryAndOptions

func TransactWithRetryAndOptions(ctx context.Context, conn *sqlx.DB, txOpts *sql.TxOptions, retry RetryOptions, operation func(tx *sqlx.Tx) error) error

TransactWithRetryAndOptions runs the operation using Transact, performing retries according to RetryOptions. If all retries fail, the error from the last attempt will be returned. If a rollback fails, no further attempts will be made and the RollbackErr will be returned.

Since the transaction operation may be executed multiple times, it is important that any mutations it applies to application state (outside the database) be idempotent.

The provided TxOptions is optional and may be nil if defaults should be used. If a non-default isolation level is used that the driver doesn't support, an error will be returned.

Types

type BackOffFunc

type BackOffFunc func() time.Duration

BackOffFunc is a function called on each retry attempt. It should return a time.Duration to wait before making the next attempt. If a negative time.Duration is returned, retries will be immediately aborted.

type RetryOptions

type RetryOptions struct {
	// MaxRetries configures how many attempts will be made to complete the operation when a retryable error is
	// encountered. The default is DefaultMaxRetries. If set to a negative number, math.MaxInt32 attempts will be made.
	MaxRetries int
	// BackOff is called on each retry, and should return a time.Duration indicating how long to wait before the next
	// attempt. The default is an exponential backoff based on the values of DefaultInitialBackOff, DefaultMaxBackOff,
	// and DefaultBackOffFactor. If a negative Duration is returned by NextBackOff(), retries will be aborted.
	//
	// Most backoff implementations are compatible, including github.com/cenkalti/backoff and
	// github.com/jpillora/backoff.
	BackOff func() time.Duration
	// IsRetryable determines whether the error from the operation should be retried. Return true to retry.
	IsRetryable func(err error) bool
	// Sleep is an optional value to be used for mocking out time.Sleep() for testing. If set, backoff wait
	// will use this function instead of time.Sleep().
	Sleep func(duration time.Duration)
}

RetryOptions controls how TransactWithRetry behaves.

type RollbackErr

type RollbackErr struct {
	// The original error that the operation returned.
	OriginalErr error
	// The error returned by sql.Tx.Rollback()
	Err error
}

RollbackErr is the error returned if the transaction operation returned an error, and the rollback automatically attempted also returns an error.

func (*RollbackErr) Cause

func (r *RollbackErr) Cause() error

Cause returns the OriginalErr.

func (*RollbackErr) Error

func (r *RollbackErr) Error() string

Error returns a formatted error message containing both the OriginalErr and RollbackErr.

func (*RollbackErr) Unwrap

func (r *RollbackErr) Unwrap() error

Unwrap returns the OriginalErr.

Jump to

Keyboard shortcuts

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