2024-07-27 07:31:04 +00:00
|
|
|
package lib
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2024-08-22 22:56:03 +00:00
|
|
|
"fmt"
|
|
|
|
"go.uber.org/zap/zapcore"
|
|
|
|
"runtime"
|
2024-07-27 07:31:04 +00:00
|
|
|
)
|
|
|
|
|
2024-08-22 22:56:03 +00:00
|
|
|
type code uint8
|
|
|
|
|
|
|
|
const (
|
|
|
|
ErrValidationFailed code = 1
|
|
|
|
ErrInternal code = 2
|
|
|
|
ErrExternal code = 3
|
|
|
|
ErrNoPermission code = 4
|
|
|
|
ErrUnknown code = 5
|
|
|
|
ErrDeadlineExceeded code = 6
|
|
|
|
ErrNotFound code = 7
|
|
|
|
ErrAlreadyExists code = 8
|
|
|
|
ErrConflict code = 9
|
|
|
|
ErrUnimplemented code = 10
|
|
|
|
ErrBadInput code = 11
|
|
|
|
ErrUnauthenticated code = 12
|
|
|
|
)
|
|
|
|
|
|
|
|
func (c code) String() string {
|
|
|
|
switch {
|
|
|
|
case errors.Is(c, ErrValidationFailed):
|
|
|
|
return "validation error"
|
|
|
|
case errors.Is(c, ErrInternal):
|
|
|
|
return "internal error"
|
|
|
|
case errors.Is(c, ErrExternal):
|
|
|
|
return "external error"
|
|
|
|
case errors.Is(c, ErrNoPermission):
|
|
|
|
return "permission error"
|
|
|
|
case errors.Is(c, ErrUnknown):
|
|
|
|
return "unknown error"
|
|
|
|
case errors.Is(c, ErrDeadlineExceeded):
|
|
|
|
return "deadline error"
|
|
|
|
case errors.Is(c, ErrNotFound):
|
|
|
|
return "not found error"
|
|
|
|
case errors.Is(c, ErrAlreadyExists):
|
|
|
|
return "already exists error"
|
|
|
|
case errors.Is(c, ErrConflict):
|
|
|
|
return "conflict error"
|
|
|
|
case errors.Is(c, ErrUnimplemented):
|
|
|
|
return "unimplemented error"
|
|
|
|
case errors.Is(c, ErrBadInput):
|
|
|
|
return "bad input error"
|
|
|
|
}
|
|
|
|
|
|
|
|
panic("unimplemented")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c code) Error() string {
|
|
|
|
return c.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
type layer uint8
|
|
|
|
|
|
|
|
const (
|
|
|
|
LayerTransport layer = 1
|
|
|
|
LayerService layer = 2
|
|
|
|
LayerStorage layer = 3
|
2024-07-27 07:31:04 +00:00
|
|
|
)
|
|
|
|
|
2024-08-22 22:56:03 +00:00
|
|
|
func (l layer) String() string {
|
|
|
|
switch l {
|
|
|
|
case LayerTransport:
|
|
|
|
return "transport"
|
|
|
|
case LayerService:
|
|
|
|
return "service"
|
|
|
|
case LayerStorage:
|
|
|
|
return "storage"
|
|
|
|
}
|
|
|
|
|
|
|
|
panic("unimplemented")
|
|
|
|
}
|
|
|
|
|
|
|
|
func location(skip int) string {
|
|
|
|
_, file, line, _ := runtime.Caller(skip)
|
|
|
|
return fmt.Sprintf("%s:%d", file, line)
|
|
|
|
}
|
|
|
|
|
|
|
|
type Error struct {
|
|
|
|
src error
|
|
|
|
layer layer
|
|
|
|
code code
|
|
|
|
msg string
|
|
|
|
loc string
|
|
|
|
}
|
|
|
|
|
|
|
|
func wrap(src error, layer layer, class code, msg string, loc string) *Error {
|
|
|
|
return &Error{
|
|
|
|
src: src,
|
|
|
|
layer: layer,
|
|
|
|
code: class,
|
|
|
|
msg: msg,
|
|
|
|
loc: loc,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Error) Unwrap() []error {
|
|
|
|
return []error{e.src, e.code}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Error) Error() string {
|
|
|
|
return fmt.Sprintf("%s: %s", e.code.String(), e.msg)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Error) MarshalLogObject(encoder zapcore.ObjectEncoder) error {
|
|
|
|
if e.src != nil {
|
|
|
|
encoder.AddString("src", e.src.Error())
|
|
|
|
}
|
|
|
|
encoder.AddString("layer", e.layer.String())
|
|
|
|
encoder.AddString("code", e.code.String())
|
|
|
|
encoder.AddString("msg", e.msg)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func TransportError(src error, code code, msg string) error {
|
|
|
|
return wrap(src, LayerTransport, code, msg, location(2))
|
|
|
|
}
|
|
|
|
|
|
|
|
func ServiceError(src error, code code, msg string) error {
|
|
|
|
return wrap(src, LayerService, code, msg, location(2))
|
|
|
|
}
|
|
|
|
|
|
|
|
func StorageError(src error, code code, msg string) error {
|
|
|
|
return wrap(src, LayerStorage, code, msg, location(2))
|
|
|
|
}
|