waymaker-client/go/errors.go

59 lines
1.8 KiB
Go

// Package waymaker is the official Go client for waymaker, a distributed
// coordination service. It wraps the gRPC stubs in genpb/ with ergonomic
// handles for locks, streams, KV, collections, sketches, object store and
// cache.
//
// Usage:
//
// client, err := waymaker.Connect(ctx, "http://localhost:8818")
// lock, err := client.AcquireLock(ctx, "my-key", waymaker.LockConfig{...})
package waymaker
import (
"fmt"
"google.golang.org/grpc/status"
)
// Error is the typed error surface for the waymaker Go client.
//
// There are three categories:
// - [ErrRPC] — gRPC transport / status error (network, server-side code).
// - [ErrServer] — server returned success=false with a result_code string.
// - [ErrInvalid] — caller passed a value the wrapper could not translate.
type Error struct {
// Kind is one of "rpc", "server", "invalid".
Kind string
// Code is the server result_code ("no_such_stream", "expired", …) for
// Kind=="server", or the gRPC status code string for Kind=="rpc".
Code string
// Message is the human-readable detail.
Message string
}
func (e *Error) Error() string {
return fmt.Sprintf("waymaker %s %s: %s", e.Kind, e.Code, e.Message)
}
// IsServerCode reports whether err is a server error whose result_code
// equals code.
func IsServerCode(err error, code string) bool {
e, ok := err.(*Error)
return ok && e.Kind == "server" && e.Code == code
}
func serverErr(code, message string) *Error {
return &Error{Kind: "server", Code: code, Message: message}
}
func invalidErr(msg string) *Error {
return &Error{Kind: "invalid", Code: "invalid_argument", Message: msg}
}
func rpcErr(err error) *Error {
if s, ok := status.FromError(err); ok {
return &Error{Kind: "rpc", Code: s.Code().String(), Message: s.Message()}
}
return &Error{Kind: "rpc", Code: "unknown", Message: err.Error()}
}