error
Structured errors with a kind, a message, a chain of causes, metadata and a retry policy.
import error
A function that may fail can return an error.Error: either "nil", meaning everything went well, or an error with a kind, such as "not found", and a message. The kind is for the code to decide on; the message is for a person to read.
When an error comes up from a lower layer, Wrap it so the current layer's explanation is added. The final message shows the whole chain, as in "could not save the report: the disk is full", and RootMessage gives the original cause.
For transient errors, such as a dropped network connection, RetryPolicy says when and how often to try again and how long to wait between attempts; the delay doubles each time.
Types
Error
struct Error| Name | Type | Description |
|---|---|---|
kind | str = "" | The kind of the error: one of the constants above, or one you define yourself. |
messages | Vector | The message from each layer, from the innermost cause to the outermost. |
kinds | Vector | The kind of each layer. |
trace | Vector | The places the error has passed through. |
meta_keys | Vector | The metadata keys. |
meta_vals | Vector | The metadata values. |
import error
func find_user(id: int): error.Error:
if id <= 0:
ret error.New(error.KindInvalidArgument, "the id has to be positive")
end
if id > 100:
ret error.NewAt(error.KindNotFound, "no such user", "find_user")
end
ret error.Nil()
end
func main:
each id in [7, -1, 500]:
mut e := find_user(id)
if error.Ok(e):
println id, "found", error.IsNil(e)
else:
println id, error.Kind(e), error.Message(e)
println error.Is(e, error.KindNotFound), error.IsNotFound(e), error.IsInvalidArgument(e)
end
error.Free(e)
end
mut args := Vector {} as Vector<str>
defer args.free()
args.push("config.ini")
e2 := error.Newf(error.KindIO, "cannot read {}", args)
println error.Message(e2)
endRetryPolicy
struct RetryPolicy| Name | Type | Description |
|---|---|---|
max_attempts | int = 3 | The greatest number of attempts; three by default. |
base_delay_ms | int = 100 | The delay after the first failed attempt, in milliseconds; 100 by default. |
max_delay_ms | int = 5000 | The ceiling on the delay, in milliseconds; 5000 by default. |
import error
func main:
mut policy := error.NewRetryPolicy(4, 100, 1000)
println policy.max_attempts, policy.base_delay_ms, policy.max_delay_ms
e := error.New(error.KindTimeout, "the server did not answer")
mut attempt := 1
until error.ShouldRetry(policy, e, attempt):
println "attempt", attempt, "after", error.DelayForAttempt(policy, attempt), "milliseconds"
attempt += 1
end
println error.ShouldRetry(policy, error.New(error.KindInvalidArgument, "bad input"), 1)
endConstants and variables
KindUnknown
const KindUnknown: str = "unknown"The example for this item is shown with the ones above: error-New.salam
KindNotFound
const KindNotFound: str = "not_found"The example for this item is shown with the ones above: error-New.salam
KindInvalidArgument
const KindInvalidArgument: str = "invalid_argument"The example for this item is shown with the ones above: error-New.salam
KindPermissionDenied
const KindPermissionDenied: str = "permission_denied"import error
func main:
each kind in [error.KindPermissionDenied, error.KindAlreadyExists, error.KindTimeout, error.KindCanceled, error.KindUnavailable, error.KindUnknown, error.KindUnimplemented]:
e := error.New(kind, "an example")
println kind, error.IsPermissionDenied(e), error.IsAlreadyExists(e), error.IsTimeout(e), error.IsCanceled(e), error.IsUnavailable(e), error.IsRetryable(e)
end
endKindAlreadyExists
const KindAlreadyExists: str = "already_exists"The example for this item is shown with the ones above: error-Kinds.salam
KindUnavailable
const KindUnavailable: str = "unavailable"The example for this item is shown with the ones above: error-Kinds.salam
KindTimeout
const KindTimeout: str = "timeout"The example for this item is shown with the ones above: error-Kinds.salam
KindCanceled
const KindCanceled: str = "canceled"The example for this item is shown with the ones above: error-Kinds.salam
KindInternal
const KindInternal: str = "internal"import error
func main:
root := error.New(error.KindIO, "the disk is full")
a := error.Wrap(root, "could not save the report")
b := error.WrapAt(a, "the nightly run stopped", "nightly job")
c := error.WrapKind(b, error.KindInternal, "internal error")
d := error.WithMeta(c, "disk", "/dev/sda1")
println error.Message(d)
println error.RootMessage(d)
println error.Kind(d), error.IsInternal(d), error.Meta(d, "disk")
println error.Trace(d)
println error.Format(d)
endKindIO
const KindIO: str = "io"The example for this item is shown with the ones above: error-New.salam
KindUnimplemented
const KindUnimplemented: str = "unimplemented"The example for this item is shown with the ones above: error-Kinds.salam
Functions
Nil
func Nil(): ErrorThe example for this item is shown with the ones above: error-New.salam
IsNil
func IsNil(e: Error): boolThe example for this item is shown with the ones above: error-New.salam
Ok
func Ok(e: Error): boolIsNil, and easier to read in a condition.The example for this item is shown with the ones above: error-New.salam
New
func New(kind: str, message: str): ErrorThe example for this item is shown with the ones above: error-New.salam
NewAt
func NewAt(kind: str, message: str, at: str): ErrorThe example for this item is shown with the ones above: error-New.salam
Newf
func Newf(kind: str, tmpl: str, args: Vector<str>): Error{} is filled with the next value.The example for this item is shown with the ones above: error-New.salam
Wrap
func Wrap(e: Error, message: str): ErrorThe example for this item is shown with the ones above: error-Wrap.salam
WrapAt
func WrapAt(e: Error, message: str, at: str): ErrorWrap, with the name of the place.The example for this item is shown with the ones above: error-Wrap.salam
WrapKind
func WrapKind(e: Error, kind: str, message: str): ErrorWrap, and changes the kind too; the earlier kind is still recognised by Is.The example for this item is shown with the ones above: error-Wrap.salam
WithMeta
func WithMeta(e: Error, key: str, val: str): ErrorThe example for this item is shown with the ones above: error-Wrap.salam
Meta
func Meta(e: Error, key: str): strThe example for this item is shown with the ones above: error-Wrap.salam
Kind
func Kind(e: Error): strThe example for this item is shown with the ones above: error-New.salam
Is
func Is(e: Error, kind: str): boolThe example for this item is shown with the ones above: error-New.salam
Message
func Message(e: Error): strThe example for this item is shown with the ones above: error-New.salam
RootMessage
func RootMessage(e: Error): strThe example for this item is shown with the ones above: error-Wrap.salam
Trace
func Trace(e: Error): str->.The example for this item is shown with the ones above: error-Wrap.salam
Format
func Format(e: Error): strThe example for this item is shown with the ones above: error-Wrap.salam
IsNotFound
func IsNotFound(e: Error): boolThe example for this item is shown with the ones above: error-New.salam
IsInvalidArgument
func IsInvalidArgument(e: Error): boolThe example for this item is shown with the ones above: error-New.salam
IsPermissionDenied
func IsPermissionDenied(e: Error): boolThe example for this item is shown with the ones above: error-Kinds.salam
IsAlreadyExists
func IsAlreadyExists(e: Error): boolThe example for this item is shown with the ones above: error-Kinds.salam
IsTimeout
func IsTimeout(e: Error): boolThe example for this item is shown with the ones above: error-Kinds.salam
IsCanceled
func IsCanceled(e: Error): boolThe example for this item is shown with the ones above: error-Kinds.salam
IsUnavailable
func IsUnavailable(e: Error): boolThe example for this item is shown with the ones above: error-Kinds.salam
IsInternal
func IsInternal(e: Error): boolThe example for this item is shown with the ones above: error-Wrap.salam
IsRetryable
func IsRetryable(e: Error): boolThe example for this item is shown with the ones above: error-Kinds.salam
NewRetryPolicy
func NewRetryPolicy(max_attempts: int, base_delay_ms: int, max_delay_ms: int): RetryPolicyThe example for this item is shown with the ones above: error-RetryPolicy.salam
DelayForAttempt
func DelayForAttempt(p &: RetryPolicy, attempt: int): intattempt failed: the base delay after the first, then doubling each time up to the ceiling.The example for this item is shown with the ones above: error-RetryPolicy.salam
ShouldRetry
func ShouldRetry(p &: RetryPolicy, e: Error, attempt: int): boolThe example for this item is shown with the ones above: error-RetryPolicy.salam
Free
func Free(e &: Error)The example for this item is shown with the ones above: error-New.salam