package errors import ( "errors" "fmt" "strings" "code.30cm.net/digimon/library-go/errors/code" "github.com/zeromicro/go-zero/core/logx" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) func newErr(scope, detail uint32, msg string) *LibError { cat := detail / 100 * 100 return &LibError{ category: cat, code: detail, scope: scope, msg: msg, } } func newBuiltinGRPCErr(scope, detail uint32, msg string) *LibError { return &LibError{ category: code.CatGRPC, code: detail, scope: scope, msg: msg, } } // FromError tries to let error as Err // it supports to unwrap error that has Err // return nil if failed to transfer func FromError(err error) *LibError { if err == nil { return nil } var e *LibError if errors.As(err, &e) { return e } return nil } // FromCode parses code as following // Decimal: 120314 // 12 represents Scope // 03 represents Category // 14 represents Detail error code func FromCode(code uint32) *LibError { scope := code / 10000 detail := code % 10000 return &LibError{ category: detail / 100 * 100, code: detail, scope: scope, msg: "", } } // FromGRPCError transfer error to Err // useful for gRPC client func FromGRPCError(err error) *LibError { s, _ := status.FromError(err) e := FromCode(uint32(s.Code())) e.msg = s.Message() // For GRPC built-in code if e.Scope() == code.Unset && e.Category() == 0 && e.Code() != code.OK { e = newBuiltinGRPCErr(Scope, e.Code(), s.Message()) } return e } // Deprecated: check GRPCStatus() in Errs struct // ToGRPCError returns the status.Status // Useful to return error in gRPC server func ToGRPCError(e *LibError) error { return status.New(codes.Code(e.FullCode()), e.Error()).Err() } /*** System ***/ // SystemTimeoutError returns Err func SystemTimeoutError(s ...string) *LibError { return newErr(Scope, code.SystemTimeoutError, fmt.Sprintf("system timeout: %s", strings.Join(s, " "))) } // SystemTimeoutErrorL logs error message and returns Err func SystemTimeoutErrorL(l logx.Logger, s ...string) *LibError { e := SystemTimeoutError(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // SystemInternalError returns Err struct func SystemInternalError(s ...string) *LibError { return newErr(Scope, code.SystemInternalError, fmt.Sprintf("internal error: %s", strings.Join(s, " "))) } // SystemInternalErrorL logs error message and returns Err func SystemInternalErrorL(l logx.Logger, s ...string) *LibError { e := SystemInternalError(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // SystemMaintainErrorL logs error message and returns Err func SystemMaintainErrorL(l logx.Logger, s ...string) *LibError { e := SystemMaintainError(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // SystemMaintainError returns Err struct func SystemMaintainError(s ...string) *LibError { return newErr(Scope, code.SystemMaintainError, fmt.Sprintf("service under maintenance: %s", strings.Join(s, " "))) } /*** CatInput ***/ // InvalidFormat returns Err struct func InvalidFormat(s ...string) *LibError { return newErr(Scope, code.InvalidFormat, fmt.Sprintf("invalid format: %s", strings.Join(s, " "))) } // InvalidFormatL logs error message and returns Err func InvalidFormatL(l logx.Logger, s ...string) *LibError { e := InvalidFormat(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // InvalidRange returns Err struct func InvalidRange(s ...string) *LibError { return newErr(Scope, code.InvalidRange, fmt.Sprintf("invalid range: %s", strings.Join(s, " "))) } // InvalidRangeL logs error message and returns Err func InvalidRangeL(l logx.Logger, s ...string) *LibError { e := InvalidRange(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // NotValidImplementation returns Err struct func NotValidImplementation(s ...string) *LibError { return newErr(Scope, code.NotValidImplementation, fmt.Sprintf("not valid implementation: %s", strings.Join(s, " "))) } // NotValidImplementationL logs error message and returns Err func NotValidImplementationL(l logx.Logger, s ...string) *LibError { e := NotValidImplementation(s...) l.WithCallerSkip(1).Error(e.Error()) return e } /*** CatDB ***/ // DBError returns Err func DBError(s ...string) *LibError { return newErr(Scope, code.DBError, fmt.Sprintf("db error: %s", strings.Join(s, " "))) } // DBErrorL logs error message and returns Err func DBErrorL(l logx.Logger, s ...string) *LibError { e := DBError(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // DBDataConvert returns Err func DBDataConvert(s ...string) *LibError { return newErr(Scope, code.DBDataConvert, fmt.Sprintf("data from db convert error: %s", strings.Join(s, " "))) } // DBDataConvertL logs error message and returns Err func DBDataConvertL(l logx.Logger, s ...string) *LibError { e := DBDataConvert(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // DBDuplicate returns Err func DBDuplicate(s ...string) *LibError { return newErr(Scope, code.DBDuplicate, fmt.Sprintf("data Duplicate key error: %s", strings.Join(s, " "))) } // DBDuplicateL logs error message and returns Err func DBDuplicateL(l logx.Logger, s ...string) *LibError { e := DBDuplicate(s...) l.WithCallerSkip(1).Error(e.Error()) return e } /*** CatResource ***/ // ResourceNotFound returns Err and logging func ResourceNotFound(s ...string) *LibError { return newErr(Scope, code.ResourceNotFound, fmt.Sprintf("resource not found: %s", strings.Join(s, " "))) } // ResourceNotFoundL logs error message and returns Err func ResourceNotFoundL(l logx.Logger, s ...string) *LibError { e := ResourceNotFound(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // InvalidResourceFormat returns Err func InvalidResourceFormat(s ...string) *LibError { return newErr(Scope, code.InvalidResourceFormat, fmt.Sprintf("invalid resource format: %s", strings.Join(s, " "))) } // InvalidResourceFormatL logs error message and returns Err func InvalidResourceFormatL(l logx.Logger, s ...string) *LibError { e := InvalidResourceFormat(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // InvalidResourceState returns status not correct. // for example: company should be destroy, agent should be no-sensor/fail-install ... func InvalidResourceState(s ...string) *LibError { return newErr(Scope, code.InvalidResourceState, fmt.Sprintf("invalid resource state: %s", strings.Join(s, " "))) } // InvalidResourceStateL logs error message and returns status not correct. func InvalidResourceStateL(l logx.Logger, s ...string) *LibError { e := InvalidResourceState(s...) l.WithCallerSkip(1).Error(e.Error()) return e } func ResourceInsufficient(s ...string) *LibError { return newErr(Scope, code.ResourceInsufficient, fmt.Sprintf("insufficient resource: %s", strings.Join(s, " "))) } func ResourceInsufficientL(l logx.Logger, s ...string) *LibError { e := ResourceInsufficient(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // InsufficientPermission returns Err func InsufficientPermission(s ...string) *LibError { return newErr(Scope, code.InsufficientPermission, fmt.Sprintf("insufficient permission: %s", strings.Join(s, " "))) } // InsufficientPermissionL returns Err and log func InsufficientPermissionL(l logx.Logger, s ...string) *LibError { e := InsufficientPermission(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // ResourceAlreadyExist returns Err func ResourceAlreadyExist(s ...string) *LibError { return newErr(Scope, code.ResourceAlreadyExist, fmt.Sprintf("resource already exist: %s", strings.Join(s, " "))) } // ResourceAlreadyExistL logs error message and returns Err func ResourceAlreadyExistL(l logx.Logger, s ...string) *LibError { e := ResourceAlreadyExist(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // InvalidMeasurementID returns Err func InvalidMeasurementID(s ...string) *LibError { return newErr(Scope, code.InvalidMeasurementID, fmt.Sprintf("missing measurement id: %s", strings.Join(s, " "))) } // InvalidMeasurementIDL logs error message and returns Err func InvalidMeasurementIDL(l logx.Logger, s ...string) *LibError { e := InvalidMeasurementID(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // ResourceExpired returns Err func ResourceExpired(s ...string) *LibError { return newErr(Scope, code.ResourceExpired, fmt.Sprintf("resource expired: %s", strings.Join(s, " "))) } // ResourceExpiredL logs error message and returns Err func ResourceExpiredL(l logx.Logger, s ...string) *LibError { e := ResourceExpired(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // ResourceMigrated returns Err func ResourceMigrated(s ...string) *LibError { return newErr(Scope, code.ResourceMigrated, fmt.Sprintf("resource migrated: %s", strings.Join(s, " "))) } // ResourceMigratedL logs error message and returns Err func ResourceMigratedL(l logx.Logger, s ...string) *LibError { e := ResourceMigrated(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // InsufficientQuota returns Err func InsufficientQuota(s ...string) *LibError { return newErr(Scope, code.InsufficientQuota, fmt.Sprintf("insufficient quota: %s", strings.Join(s, " "))) } // InsufficientQuotaL logs error message and returns Err func InsufficientQuotaL(l logx.Logger, s ...string) *LibError { e := InsufficientQuota(s...) l.WithCallerSkip(1).Error(e.Error()) return e } /*** CatAuth ***/ // Unauthorized returns Err func Unauthorized(s ...string) *LibError { return newErr(Scope, code.Unauthorized, fmt.Sprintf("unauthorized: %s", strings.Join(s, " "))) } // UnauthorizedL logs error message and returns Err func UnauthorizedL(l logx.Logger, s ...string) *LibError { e := Unauthorized(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // AuthExpired returns Err func AuthExpired(s ...string) *LibError { return newErr(Scope, code.AuthExpired, fmt.Sprintf("expired: %s", strings.Join(s, " "))) } // AuthExpiredL logs error message and returns Err func AuthExpiredL(l logx.Logger, s ...string) *LibError { e := AuthExpired(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // InvalidPosixTime returns Err func InvalidPosixTime(s ...string) *LibError { return newErr(Scope, code.InvalidPosixTime, fmt.Sprintf("invalid posix time: %s", strings.Join(s, " "))) } // InvalidPosixTimeL logs error message and returns Err func InvalidPosixTimeL(l logx.Logger, s ...string) *LibError { e := InvalidPosixTime(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // SigAndPayloadNotMatched returns Err func SigAndPayloadNotMatched(s ...string) *LibError { return newErr(Scope, code.SigAndPayloadNotMatched, fmt.Sprintf("signature and the payload are not match: %s", strings.Join(s, " "))) } // SigAndPayloadNotMatchedL logs error message and returns Err func SigAndPayloadNotMatchedL(l logx.Logger, s ...string) *LibError { e := SigAndPayloadNotMatched(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // Forbidden returns Err func Forbidden(s ...string) *LibError { return newErr(Scope, code.Forbidden, fmt.Sprintf("forbidden: %s", strings.Join(s, " "))) } // ForbiddenL logs error message and returns Err func ForbiddenL(l logx.Logger, s ...string) *LibError { e := Forbidden(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // IsAuthUnauthorizedError check the err is unauthorized error func IsAuthUnauthorizedError(err *LibError) bool { switch err.Code() { case code.Unauthorized, code.AuthExpired, code.InvalidPosixTime, code.SigAndPayloadNotMatched, code.Forbidden, code.InvalidFormat, code.ResourceNotFound: return true default: return false } } /*** CatXBC ***/ // ArkInternal returns Err func ArkInternal(s ...string) *LibError { return newErr(Scope, code.ArkInternal, fmt.Sprintf("ark internal error: %s", strings.Join(s, " "))) } // ArkInternalL logs error message and returns Err func ArkInternalL(l logx.Logger, s ...string) *LibError { e := ArkInternal(s...) l.WithCallerSkip(1).Error(e.Error()) return e } /*** CatPubSub ***/ // Publish returns Err func Publish(s ...string) *LibError { return newErr(Scope, code.Publish, fmt.Sprintf("publish: %s", strings.Join(s, " "))) } // PublishL logs error message and returns Err func PublishL(l logx.Logger, s ...string) *LibError { e := Publish(s...) l.WithCallerSkip(1).Error(e.Error()) return e } // Consume returns Err func Consume(s ...string) *LibError { return newErr(Scope, code.Consume, fmt.Sprintf("consume: %s", strings.Join(s, " "))) } // MsgSizeTooLarge returns Err func MsgSizeTooLarge(s ...string) *LibError { return newErr(Scope, code.MsgSizeTooLarge, fmt.Sprintf("kafka error: %s", strings.Join(s, " "))) } // MsgSizeTooLargeL logs error message and returns Err func MsgSizeTooLargeL(l logx.Logger, s ...string) *LibError { e := MsgSizeTooLarge(s...) l.WithCallerSkip(1).Error(e.Error()) return e }