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
- Variables
- func Transact(ctx context.Context, conn *sqlx.DB, operation func(tx *sqlx.Tx) error) (err error)
- func TransactWithOptions(ctx context.Context, conn *sqlx.DB, operation func(tx *sqlx.Tx) error) (err error)
- func TransactWithRetry(ctx context.Context, conn *sqlx.DB, retry RetryOptions, ...) error
- func TransactWithRetryAndOptions(ctx context.Context, conn *sqlx.DB, txOpts *sql.TxOptions, retry RetryOptions, ...) error
- type BackOffFunc
- type RetryOptions
- type RollbackErr
Constants ¶
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 ¶
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..
var DefaultMaxRetries = 5
DefaultMaxRetries configures the default number of max retries attempted by TransactWithRetry.
Functions ¶
func Transact ¶
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 ¶
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) Error ¶
func (r *RollbackErr) Error() string
Error returns a formatted error message containing both the OriginalErr and RollbackErr.