2025-11-04 09:47:36 +00:00
|
|
|
|
package errs
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"errors"
|
|
|
|
|
|
|
|
|
|
|
|
"backend/pkg/library/errors/code"
|
2025-11-12 08:17:23 +00:00
|
|
|
|
|
2025-11-04 09:47:36 +00:00
|
|
|
|
"google.golang.org/grpc/status"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
func newBuiltinGRPCErr(scope, detail uint32, msg string) *Error {
|
|
|
|
|
|
return &Error{
|
|
|
|
|
|
category: uint32(code.CatGRPC),
|
|
|
|
|
|
detail: detail,
|
|
|
|
|
|
scope: scope,
|
|
|
|
|
|
msg: msg,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// FromError tries to let error as Err
|
|
|
|
|
|
// it supports to unwrap error that has Error
|
|
|
|
|
|
// return nil if failed to transfer
|
|
|
|
|
|
func FromError(err error) *Error {
|
|
|
|
|
|
if err == nil {
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var e *Error
|
|
|
|
|
|
if errors.As(err, &e) {
|
|
|
|
|
|
return e
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// FromCode parses code as following 8 碼
|
|
|
|
|
|
// Decimal: 10201000
|
|
|
|
|
|
// 10 represents Scope
|
|
|
|
|
|
// 201 represents Category
|
|
|
|
|
|
// 000 represents Detail error code
|
|
|
|
|
|
func FromCode(code uint32) *Error {
|
|
|
|
|
|
const CodeMultiplier = 1000000
|
|
|
|
|
|
const SubMultiplier = 1000
|
|
|
|
|
|
// 獲取 scope,前兩位數
|
|
|
|
|
|
scope := code / CodeMultiplier
|
|
|
|
|
|
|
|
|
|
|
|
// 獲取 detail,最後三位數
|
|
|
|
|
|
detail := code % SubMultiplier
|
|
|
|
|
|
|
|
|
|
|
|
// 獲取 category,中間三位數
|
|
|
|
|
|
category := (code / SubMultiplier) % SubMultiplier
|
|
|
|
|
|
|
|
|
|
|
|
return &Error{
|
|
|
|
|
|
category: category,
|
|
|
|
|
|
detail: detail,
|
|
|
|
|
|
scope: scope,
|
|
|
|
|
|
msg: "",
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// FromGRPCError transfer error to Err
|
|
|
|
|
|
// useful for gRPC client
|
|
|
|
|
|
func FromGRPCError(err error) *Error {
|
|
|
|
|
|
s, _ := status.FromError(err)
|
|
|
|
|
|
e := FromCode(uint32(s.Code()))
|
|
|
|
|
|
e.msg = s.Message()
|
|
|
|
|
|
|
|
|
|
|
|
// For GRPC built-in code
|
|
|
|
|
|
if e.Scope() == uint32(code.Unset) && e.Category() == 0 && e.Code() != code.OK {
|
|
|
|
|
|
e = newBuiltinGRPCErr(uint32(Scope), e.detail, s.Message()) // Note: detail is now 3-digit, but built-in codes are small
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return e
|
|
|
|
|
|
}
|