qberrors

package
v0.2.7 Latest Latest
Warning

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

Go to latest
Published: May 23, 2021 License: MIT Imports: 5 Imported by: 0

README

qberrors

The qberrors package provides consistent error handling for Quickbase applications written in Go.

Goals

  • Simplify code by sticking to common Go conventions with transparent abstractions for conveninence.
  • Improve security by separating internal errors from those that are safe for the user to see.
  • Improve user experience by returning appropriate HTTP status codes with detailed error messages.
  • Simplify internal logging by maintaining the entire error chain through the edge of the app.
  • Promote resiliency by recommending whether the operation that caused the error should be retried.

Usage

Conventions
  • Client errors are the result of user input and should not be retried until the input is changed.
  • Internal errors are internal to the application and should not be retried until code is fixed.
  • Service errors are temporary problems that should be retried using a backoff algorithm.
Examples

Standard errors are treated as Internal and unsafe for users to see.

err := errors.New("something bad happened")

fmt.Printf("%t\n", qberrors.IsSafe(err))
// Output: false

fmt.Println(qberrors.SafeMessage(err))
// Output: internal error

fmt.Println(qberrors.Upstream(err))
// Output: something bad happened

fmt.Println(qberrors.StatusCode(err))
// Output: 500

Service errors imply that the operation should be retried. The example below displays a helpful message to the user while maintaining the internal error chain for logging:

connect := func() error {
	return errors.New("timeout connecting to service")
}

cerr := connect()
werr := fmt.Errorf("additional context: %w", cerr)

time := time.Now().Add(5 * time.Minute).Format("3:04 PM") // A time 5 minutes from now.
err := qberrors.Service(werr).Safef(qberrors.ServceUnavailable, "please retry at %s", time)

fmt.Println(err)
// Output: please retry at 11:19 AM: service unavailable

fmt.Println(qberrors.SafeMessage(err))
// Output: service unavailable

fmt.Println(qberrors.SafeDetail(err))
// Output: please retry at 11:19 AM

fmt.Println(qberrors.Upstream(err))
// Output: additional context: timeout connecting to service

fmt.Println(qberrors.StatusCode(err))
// Output: 503

Handling "not found" errors is common in applications. This library treats them as Client errors so that developers can use Go's error handling capabilities to control the logic of the application and show users a helpful message with an appropriate status code.

id := "123"
err := qberrors.NotFoundError("item %q", id)

fmt.Printf("%t\n", errors.Is(err, qberrors.NotFound))
// Output: true

fmt.Println(err)
// Output: item "123": not found

fmt.Println(qberrors.Upstream(err))
// Output: <nil>

fmt.Println(qberrors.StatusCode(err))
// Output: 404

Documentation

Overview

Package qberrors provides common errors to standardize error handling across Quickbae golang projects.

See https://blog.golang.org/go1.13-errors

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	BadRequest        = ErrSafe{"bad request", http.StatusBadRequest}
	InvalidDataType   = ErrSafe{"data type not valid", http.StatusBadRequest}
	InvalidInput      = ErrSafe{"input not valid", http.StatusBadRequest}
	InvalidSyntax     = ErrSafe{"syntax not valid", http.StatusBadRequest}
	NotFound          = ErrSafe{"not found", http.StatusNotFound}
	ServceUnavailable = ErrSafe{"service unavailable", http.StatusServiceUnavailable}
)

ErrSafe errors.

Functions

func HandleErrorJSON

func HandleErrorJSON(err error) error

HandleErrorJSON handles a JSON unmarshaling error for input passed by a user by normalizing messages and returning either a ErrClient or ErrInternal.

func HandleErrorValidation

func HandleErrorValidation(err error) error

HandleErrorValidation handles github.com/go-playground/validator validation errors for input passed by a user and returns an ErrClient.

func InvalidInputError

func InvalidInputError(err error, format string, a ...interface{}) error

InvalidInputError returns an ErrClient with ErrClient.safe set as BadRequest and additional context according to the format specifier.

func IsSafe

func IsSafe(err error) bool

IsSafe returns true if err is safe to show the user.

func NotFoundError

func NotFoundError(format string, a ...interface{}) error

NotFoundError returns an ErrClient with ErrClient.safe set as NotFound and additional context according to the format specifier.

Example
package main

import (
	"errors"
	"fmt"

	"github.com/QuickBase/quickbase-cli/qberrors"
)

func main() {
	err := qberrors.NotFoundError("item %q", "123")

	if errors.Is(err, qberrors.NotFound) {
		fmt.Println(err)
	}

}
Output:

item "123": not found

func SafeDetail

func SafeDetail(err error) string

SafeDetail returns detail about the error that is safe for the user to see.

func SafeErrorf

func SafeErrorf(err error, format string, a ...interface{}) error

SafeErrorf returns a wrapped ErrSafe given the format specifier.

func SafeMessage

func SafeMessage(err error) string

SafeMessage returns an error message that is safe for the user to see.

func StatusCode

func StatusCode(err error) int

StatusCode returns the status code associated with the error.

func Upstream

func Upstream(err error) error

Upstream returns the error chain that caused the user to be shown an error. The error chain is assumed to be unsafe for the user to see.

Types

type ErrClient

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

ErrClient is an error due to client input. The operation should not be retried.

func Client

func Client(err error) *ErrClient

Client returns an ErrClient.

func (ErrClient) Error

func (e ErrClient) Error() string

func (ErrClient) Retry

func (e ErrClient) Retry() bool

Retry implements Error.Retry.

func (*ErrClient) Safe

func (e *ErrClient) Safe(err error) error

Safe sets ErrClient.safe as err. TODO add variadic argument that wraps err

func (*ErrClient) Safef

func (e *ErrClient) Safef(err error, format string, a ...interface{}) error

Safef sets ErrClient.safe as a wrapped err.

func (ErrClient) Unwrap

func (e ErrClient) Unwrap() error

func (ErrClient) Upstream

func (e ErrClient) Upstream() error

Upstream implements Error.Upstream.

type ErrInternal

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

ErrInternal is an error with the application. The operation should not be retried.

func Internal

func Internal(err error) *ErrInternal

Internal returns an ErrInternal.

func (ErrInternal) Error

func (e ErrInternal) Error() string

func (ErrInternal) Retry

func (e ErrInternal) Retry() bool

Retry implements Error.Retry.

func (*ErrInternal) Safe

func (e *ErrInternal) Safe(err error) error

Safe sets ErrInternal.safe as err. TODO add variadic argument that wraps err

func (*ErrInternal) Safef

func (e *ErrInternal) Safef(err error, format string, a ...interface{}) error

Safef sets ErrInternal.safe as a wrapped err.

func (ErrInternal) Unwrap

func (e ErrInternal) Unwrap() error

func (ErrInternal) Upstream

func (e ErrInternal) Upstream() error

Upstream implements Error.Upstream.

type ErrSafe

type ErrSafe struct {
	Message    string
	StatusCode int
}

ErrSafe is an error that is assumed to be safe to show to the user. Errors that wrap ErrSafe are also assumed to be safe to show the user, inclusive of all subsequent wraps up the chain.

func (ErrSafe) Error

func (e ErrSafe) Error() string

type ErrService

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

ErrService is an error connecting to a dependent service. The operation can be retried.

func Service

func Service(err error) *ErrService

Service returns an ErrService.

func (ErrService) Error

func (e ErrService) Error() string

func (ErrService) Retry

func (e ErrService) Retry() bool

Retry implements Error.Retry.

func (*ErrService) Safe

func (e *ErrService) Safe(err error) error

Safe sets ErrService.safe as err. TODO add variadic argument that wraps err

func (*ErrService) Safef

func (e *ErrService) Safef(err error, format string, a ...interface{}) error

Safef sets ErrService.safe as a wrapped err.

func (ErrService) Unwrap

func (e ErrService) Unwrap() error

func (ErrService) Upstream

func (e ErrService) Upstream() error

Upstream implements Error.Upstream.

type Error

type Error interface {

	// Upstream returns the error chain that caused showing the user an error.
	// It is assumed that the error chain is unsafe to show the user.
	Upstream() error

	// Retry returns whether the operation should be retried.
	Retry() bool
}

Error is implemented by errors.

Jump to

Keyboard shortcuts

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