From e1f5b2afe0da6ad3d2e0f0bd966b015d4fdd1acd Mon Sep 17 00:00:00 2001 From: withchao <993506633@qq.com> Date: Thu, 29 Jun 2023 19:43:40 +0800 Subject: [PATCH] error code optimization --- pkg/errs/code.go | 92 +++++++++++++++++++++++++++++++++++ pkg/errs/coderr.go | 109 ++++++++++++++++++++++++++++++++++++++++++ pkg/errs/predefine.go | 67 ++++++++++++++++++++++++++ pkg/errs/relation.go | 43 +++++++++++++++++ 4 files changed, 311 insertions(+) create mode 100644 pkg/errs/code.go create mode 100644 pkg/errs/coderr.go create mode 100644 pkg/errs/predefine.go create mode 100644 pkg/errs/relation.go diff --git a/pkg/errs/code.go b/pkg/errs/code.go new file mode 100644 index 000000000..3104ed729 --- /dev/null +++ b/pkg/errs/code.go @@ -0,0 +1,92 @@ +package errs + +// UnknownCode 没有解析到code或解析的code=0 +const UnknownCode = 1000 + +const ( + FormattingError = 10001 + HasRegistered = 10002 + NotRegistered = 10003 + PasswordErr = 10004 + GetIMTokenErr = 10005 + RepeatSendCode = 10006 + MailSendCodeErr = 10007 + SmsSendCodeErr = 10008 + CodeInvalidOrExpired = 10009 + RegisterFailed = 10010 + ResetPasswordFailed = 10011 + RegisterLimit = 10012 + LoginLimit = 10013 + InvitationError = 10014 +) + +// 通用错误码 +const ( + NoError = 0 //无错误 + DatabaseError = 90002 //redis/mysql等db错误 + NetworkError = 90004 //网络错误 + IdentityError = 90008 // 身份错误 非管理员token,且token中userID与请求userID不一致 + GRPCConnIsNil = 90006 //grpc连接空 + DefaultOtherError = 90006 //其他错误 + DataError = 90007 //数据错误 + ConfigError = 90009 + CallbackError = 80000 + RelationshipAlreadyError = 92001 //已经是好友关系(或者黑名单) + NotRelationshipYetError = 92002 //不是好友关系(或者黑名单) + + //通用错误码 + ServerInternalError = 500 //服务器内部错误 + ArgsError = 1001 //输入参数错误 + NoPermissionError = 1002 //权限不足 + DuplicateKeyError = 1003 + RecordNotFoundError = 1004 //记录不存在 + + // 账号错误码 + UserIDNotFoundError = 1101 //UserID不存在 或未注册 + UserIDExisted = 1102 //UserID已存在 + RegisteredAlreadyError = 1103 //用户已经注册过了 + + // 群组错误码 + GroupIDNotFoundError = 1201 //GroupID不存在 + GroupIDExisted = 1202 //GroupID已存在 + OnlyOneOwnerError = 1203 //只能有一个群主 + InGroupAlreadyError = 1204 //已在群组中 + NotInGroupYetError = 1205 //不在群组中 + DismissedAlreadyError = 1206 //群组已经解散 + OwnerNotAllowedQuitError = 1207 //群主不能退群 + GroupTypeNotSupport = 1208 + GroupNoOwner = 1209 + GroupRequestHandled = 1210 + + // 关系链错误码 + CanNotAddYourselfError = 1301 //不能添加自己为好友 + BlockedByPeer = 1302 //被对方拉黑 + NotPeersFriend = 1303 //不是对方的好友 + + // 消息错误码 + MessageHasReadDisable = 1401 + MutedInGroup = 1402 //群成员被禁言 + MutedGroup = 1403 //群被禁言 + UserNotRecvMsg = 1404 //用户设置了不接收消息 + MsgAlreadyRevoke = 1405 //消息已撤回 + + // token错误码 + TokenExpiredError = 1501 + TokenInvalidError = 1502 + TokenMalformedError = 1503 + TokenNotValidYetError = 1504 + TokenUnknownError = 1505 + TokenKickedError = 1506 + TokenDifferentPlatformIDError = 1507 + TokenDifferentUserIDError = 1508 + TokenNotExistError = 1509 + + // 长连接网关错误码 + ConnOverMaxNumLimit = 1601 + ConnArgsErr = 1602 + ConnUpdateErr = 1603 + + // S3错误码 + FileUploadedCompleteError = 1701 // 文件已上传 + FileUploadedExpiredError = 1702 // 上传过期 +) diff --git a/pkg/errs/coderr.go b/pkg/errs/coderr.go new file mode 100644 index 000000000..b8371bd5b --- /dev/null +++ b/pkg/errs/coderr.go @@ -0,0 +1,109 @@ +package errs + +import ( + "fmt" + "github.com/pkg/errors" + "strings" +) + +type CodeError interface { + Code() int + Msg() string + Detail() string + WithDetail(detail string) CodeError + // Is 判断是否是某个错误, loose为false时, 只有错误码相同就认为是同一个错误, 默认为true + Is(err error, loose ...bool) bool + Wrap(msg ...string) error + error +} + +func NewCodeError(code int, msg string) CodeError { + return &codeError{ + code: code, + msg: msg, + } +} + +type codeError struct { + code int + msg string + detail string +} + +func (e *codeError) Code() int { + return e.code +} + +func (e *codeError) Msg() string { + return e.msg +} + +func (e *codeError) Detail() string { + return e.detail +} + +func (e *codeError) WithDetail(detail string) CodeError { + var d string + if e.detail == "" { + d = detail + } else { + d = e.detail + ", " + detail + } + return &codeError{ + code: e.code, + msg: e.msg, + detail: d, + } +} + +func (e *codeError) Wrap(w ...string) error { + return errors.Wrap(e, strings.Join(w, ", ")) +} + +func (e *codeError) Is(err error, loose ...bool) bool { + if err == nil { + return false + } + var allowSubclasses bool + if len(loose) == 0 { + allowSubclasses = true + } else { + allowSubclasses = loose[0] + } + codeErr, ok := Unwrap(err).(CodeError) + if ok { + if allowSubclasses { + return Relation.Is(e.code, codeErr.Code()) + } else { + return codeErr.Code() == e.code + } + } + return false +} + +func (e *codeError) Error() string { + return fmt.Sprintf("%s", e.msg) +} + +func Unwrap(err error) error { + for err != nil { + unwrap, ok := err.(interface { + Unwrap() error + }) + if !ok { + break + } + err = unwrap.Unwrap() + } + return err +} + +func Wrap(err error, msg ...string) error { + if err == nil { + return nil + } + if len(msg) == 0 { + return errors.WithStack(err) + } + return errors.Wrap(err, strings.Join(msg, ", ")) +} diff --git a/pkg/errs/predefine.go b/pkg/errs/predefine.go new file mode 100644 index 000000000..740875c6f --- /dev/null +++ b/pkg/errs/predefine.go @@ -0,0 +1,67 @@ +package errs + +var ( + ErrArgs = NewCodeError(ArgsError, "ArgsError") + ErrDatabase = NewCodeError(DatabaseError, "DatabaseError") + ErrInternalServer = NewCodeError(ServerInternalError, "ServerInternalError") + ErrNetwork = NewCodeError(NetworkError, "NetworkError") + ErrNoPermission = NewCodeError(NoPermissionError, "NoPermissionError") + ErrIdentity = NewCodeError(IdentityError, "IdentityError") + ErrCallback = NewCodeError(CallbackError, "CallbackError") + ErrCallbackContinue = NewCodeError(CallbackError, "ErrCallbackContinue") + + ErrUserIDNotFound = NewCodeError(UserIDNotFoundError, "UserIDNotFoundError") + ErrGroupIDNotFound = NewCodeError(GroupIDNotFoundError, "GroupIDNotFoundError") + ErrGroupIDExisted = NewCodeError(GroupIDExisted, "GroupIDExisted") + ErrUserIDExisted = NewCodeError(UserIDExisted, "UserIDExisted") + + ErrRecordNotFound = NewCodeError(RecordNotFoundError, "RecordNotFoundError") + + ErrRelationshipAlready = NewCodeError(RelationshipAlreadyError, "RelationshipAlreadyError") + ErrNotRelationshipYet = NewCodeError(NotRelationshipYetError, "NotRelationshipYetError") + ErrCanNotAddYourself = NewCodeError(CanNotAddYourselfError, "CanNotAddYourselfError") + + ErrOnlyOneOwner = NewCodeError(OnlyOneOwnerError, "OnlyOneOwnerError") + ErrInGroupAlready = NewCodeError(InGroupAlreadyError, "InGroupAlreadyError") + ErrNotInGroupYet = NewCodeError(NotInGroupYetError, "NotInGroupYetError") + ErrDismissedAlready = NewCodeError(DismissedAlreadyError, "DismissedAlreadyError") + ErrOwnerNotAllowedQuit = NewCodeError(OwnerNotAllowedQuitError, "OwnerNotAllowedQuitError") + ErrRegisteredAlready = NewCodeError(RegisteredAlreadyError, "RegisteredAlreadyError") + ErrGroupTypeNotSupport = NewCodeError(GroupTypeNotSupport, "") + ErrGroupNoOwner = NewCodeError(GroupNoOwner, "ErrGroupNoOwner") + + ErrDefaultOther = NewCodeError(DefaultOtherError, "DefaultOtherError") + ErrData = NewCodeError(DataError, "DataError") + ErrTokenExpired = NewCodeError(TokenExpiredError, "TokenExpiredError") + ErrTokenInvalid = NewCodeError(TokenInvalidError, "TokenInvalidError") // + ErrTokenMalformed = NewCodeError(TokenMalformedError, "TokenMalformedError") //格式错误 + ErrTokenNotValidYet = NewCodeError(TokenNotValidYetError, "TokenNotValidYetError") //还未生效 + ErrTokenUnknown = NewCodeError(TokenUnknownError, "TokenUnknownError") //未知错误 + ErrTokenKicked = NewCodeError(TokenKickedError, "TokenKickedError") + ErrTokenNotExist = NewCodeError(TokenNotExistError, "TokenNotExistError") //在redis中不存在 + ErrTokenDifferentPlatformID = NewCodeError(TokenDifferentPlatformIDError, "TokenDifferentPlatformIDError") + ErrTokenDifferentUserID = NewCodeError(TokenDifferentUserIDError, "TokenDifferentUserIDError") + ErrDuplicateKey = NewCodeError(DuplicateKeyError, "DuplicateKeyError") + + ErrMessageHasReadDisable = NewCodeError(MessageHasReadDisable, "MessageHasReadDisable") + + ErrBlockedByPeer = NewCodeError(BlockedByPeer, "BlockedByPeer") + //不是对方的好友 + ErrNotPeersFriend = NewCodeError(NotPeersFriend, "NotPeersFriend") + + ErrMutedInGroup = NewCodeError(MutedInGroup, "MutedInGroup") + ErrMutedGroup = NewCodeError(MutedGroup, "MutedGroup") + ErrUserNotRecvMsg = NewCodeError(UserNotRecvMsg, "UserNotRecvMsg") + ErrMsgAlreadyRevoke = NewCodeError(MsgAlreadyRevoke, "MsgAlreadyRevoke") + + ErrConnOverMaxNumLimit = NewCodeError(ConnOverMaxNumLimit, "ConnOverMaxNumLimit") + + ErrConnArgsErr = NewCodeError(ConnArgsErr, "args err, need token, sendID, platformID") + ErrConnUpdateErr = NewCodeError(ConnArgsErr, "upgrade http conn err") + + ErrConfig = NewCodeError(ConfigError, "ConfigError") + + ErrFileUploadedComplete = NewCodeError(FileUploadedCompleteError, "FileUploadedComplete") + ErrFileUploadedExpired = NewCodeError(FileUploadedExpiredError, "FileUploadedExpiredError") + ErrGroupRequestHandled = NewCodeError(GroupRequestHandled, "GroupRequestHandled") +) diff --git a/pkg/errs/relation.go b/pkg/errs/relation.go new file mode 100644 index 000000000..5d87ab59e --- /dev/null +++ b/pkg/errs/relation.go @@ -0,0 +1,43 @@ +package errs + +var Relation = &relation{m: make(map[int]map[int]struct{})} + +func init() { + Relation.Add(RecordNotFoundError, UserIDNotFoundError) + Relation.Add(RecordNotFoundError, GroupIDNotFoundError) + Relation.Add(DuplicateKeyError, UserIDExisted) + Relation.Add(DuplicateKeyError, GroupIDExisted) +} + +type relation struct { + m map[int]map[int]struct{} +} + +func (r *relation) Add(codes ...int) { + if len(codes) < 2 { + panic("codes length must be greater than 2") + } + for i := 1; i < len(codes); i++ { + parent := codes[i-1] + s, ok := r.m[parent] + if !ok { + s = make(map[int]struct{}) + r.m[parent] = s + } + for _, code := range codes[i:] { + s[code] = struct{}{} + } + } +} + +func (r *relation) Is(parent, child int) bool { + if parent == child { + return true + } + s, ok := r.m[parent] + if !ok { + return false + } + _, ok = s[child] + return ok +}