crdb

package
v0.0.0-...-b4be4ca Latest Latest
Warning

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

Go to latest
Published: Oct 16, 2019 License: Apache-2.0 Imports: 6 Imported by: 0

README

CRDB

crdb is a wrapper around the logic for issuing SQL transactions which performs retries (as required by CockroachDB).

Note that unfortunately there is no generic way of extracting a pg error code; the library has to recognize driver-dependent error types. We currently support github.com/lib/pq and github.com/jackc/pgconn (which is used by github.com/jackc/pgx/v4; previous pgx versions are not supported).

Note for developers: if you make any changes here (especially if they modify public APIs), please verify that the code in https://github.com/cockroachdb/examples-go still works and update as necessary.

Documentation

Overview

Package crdb provides helpers for using CockroachDB in client applications.

Package crdb provides helpers for using CockroachDB in client applications.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExecuteInTx

func ExecuteInTx(ctx context.Context, tx Tx, fn func() error) (err error)

ExecuteInTx runs fn inside tx which should already have begun. *WARNING*: Do not execute any statements on the supplied tx before calling this function. ExecuteInTx will only retry statements that are performed within the supplied closure (fn). Any statements performed on the tx before ExecuteInTx is invoked will *not* be re-run if the transaction needs to be retried.

fn is subject to the same restrictions as the fn passed to ExecuteTx.

func ExecuteInTxx

func ExecuteInTxx(ctx context.Context, tx Txx, fn func() error) (err error)

ExecuteInTxx runs fn inside tx which should already have begun. *WARNING*: Do not execute any statements on the supplied tx before calling this function. ExecuteInTx will only retry statements that are performed within the supplied closure (fn). Any statements performed on the tx before ExecuteInTx is invoked will *not* be re-run if the transaction needs to be retried.

fn is subject to the same restrictions as the fn passed to ExecuteTx.

func ExecuteTx

func ExecuteTx(
	ctx context.Context, db *sql.DB, txopts *sql.TxOptions, fn func(*sql.Tx) error,
) error

ExecuteTx runs fn inside a transaction and retries it as needed. On non-retryable failures, the transaction is aborted and rolled back; on success, the transaction is committed. There are cases where the state of a transaction is inherently ambiguous: if we err on RELEASE with a communication error it's unclear if the transaction has been committed or not (similar to erroring on COMMIT in other databases). In that case, we return AmbiguousCommitError. There are cases when restarting a transaction fails: we err on ROLLBACK to the SAVEPOINT. In that case, we return a TxnRestartError.

For more information about CockroachDB's transaction model see https://cockroachlabs.com/docs/stable/transactions.html.

NOTE: the supplied fn closure should not have external side effects beyond changes to the database.

fn must take care when wrapping errors returned from the database driver with additional context. For example, if the UPDATE statement fails in the following snippet, the original retryable error will be masked by the call to fmt.Errorf, and the transaction will not be automatically retried.

crdb.ExecuteTx(ctx, db, txopts, func (tx *sql.Tx) error {
    if err := tx.ExecContext(ctx, "UPDATE..."); err != nil {
        return fmt.Errorf("updating record: %s", err)
    }
    return nil
})

Instead, add context by returning an error that implements the ErrorCauser interface. Either create a custom error type that implements ErrorCauser or use a helper function that does so automatically, like pkg/errors.Wrap:

import "github.com/pkg/errors"

crdb.ExecuteTx(ctx, db, txopts, func (tx *sql.Tx) error {
    if err := tx.ExecContext(ctx, "UPDATE..."); err != nil {
        return errors.Wrap(err, "updating record")
    }
    return nil
})

func ExecuteTxx

func ExecuteTxx(
	ctx context.Context, db *sqlx.DB, txopts *sql.TxOptions, fn func(*sqlx.Tx) error,
) error

ExecuteTxx runs fn inside a transaction and retries it as needed. On non-retryable failures, the transaction is aborted and rolled back; on success, the transaction is committed. There are cases where the state of a transaction is inherently ambiguous: if we err on RELEASE with a communication error it's unclear if the transaction has been committed or not (similar to erroring on COMMIT in other databases). In that case, we return AmbiguousCommitError. There are cases when restarting a transaction fails: we err on ROLLBACK to the SAVEPOINT. In that case, we return a TxnRestartError.

For more information about CockroachDB's transaction model see https://cockroachlabs.com/docs/stable/transactions.html.

NOTE: the supplied fn closure should not have external side effects beyond changes to the database.

fn must take care when wrapping errors returned from the database driver with additional context. For example, if the UPDATE statement fails in the following snippet, the original retryable error will be masked by the call to fmt.Errorf, and the transaction will not be automatically retried.

crdb.ExecuteTx(ctx, db, txopts, func (tx *sql.Tx) error {
    if err := tx.ExecContext(ctx, "UPDATE..."); err != nil {
        return fmt.Errorf("updating record: %s", err)
    }
    return nil
})

Instead, add context by returning an error that implements the ErrorCauser interface. Either create a custom error type that implements ErrorCauser or use a helper function that does so automatically, like pkg/errors.Wrap:

import "github.com/pkg/errors"

crdb.ExecuteTx(ctx, db, txopts, func (tx *sql.Tx) error {
    if err := tx.ExecContext(ctx, "UPDATE..."); err != nil {
        return errors.Wrap(err, "updating record")
    }
    return nil
})

func Unwrap

func Unwrap(err error) error

Unwrap is equivalent to errors.Unwrap. It's implemented here to maintain compatibility with Go versions before 1.13 (when the errors package was introduced). It returns the result of calling the Unwrap method on err, if err's type implements UnwrappableError. Otherwise, Unwrap returns nil.

Types

type AmbiguousCommitError

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

AmbiguousCommitError represents an error that left a transaction in an ambiguous state: unclear if it committed or not.

func (*AmbiguousCommitError) Cause

func (e *AmbiguousCommitError) Cause() error

Cause implements the ErrorCauser interface.

func (*AmbiguousCommitError) Error

func (e *AmbiguousCommitError) Error() string

Error implements the error interface.

type ErrorCauser

type ErrorCauser interface {
	// Cause returns the proximate cause of this error.
	Cause() error
}

ErrorCauser is the type implemented by an error that remembers its cause.

ErrorCauser is intentionally equivalent to the causer interface used by the github.com/pkg/errors package.

type Tx

type Tx interface {
	ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
	Commit() error
	Rollback() error
}

Tx is used to permit clients to implement custom transaction logic.

type TxnRestartError

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

TxnRestartError represents an error when restarting a transaction. `cause` is the error from restarting the txn and `retryCause` is the original error which triggered the restart.

func (*TxnRestartError) Cause

func (e *TxnRestartError) Cause() error

Cause implements the ErrorCauser interface.

func (*TxnRestartError) Error

func (e *TxnRestartError) Error() string

Error implements the error interface.

func (*TxnRestartError) RetryCause

func (e *TxnRestartError) RetryCause() error

RetryCause returns the error that caused the transaction to be restarted.

type Txx

type Txx interface {
	ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
	Commit() error
	Rollback() error
}

Txx is used to permit clients to implement custom transaction logic.

type UnwrappableError

type UnwrappableError interface {
	// Unwrap returns the proximate cause of this error.
	Unwrap() error
}

UnwrappableError describes errors compatible with errors.Unwrap.

Jump to

Keyboard shortcuts

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