gomog/pkg/errors/errors.go

326 lines
8.8 KiB
Go

package errors
import (
"fmt"
"net/http"
)
// ErrorCode 错误码
type ErrorCode int
const (
// 成功
ErrOK ErrorCode = iota
// 通用错误 (1000-1999)
ErrInternalError
ErrInvalidRequest
ErrNotImplemented
// 数据库错误 (2000-2999)
ErrDatabaseError
ErrCollectionNotFound
ErrDocumentNotFound
ErrDuplicateKey
ErrWriteConflict
ErrReadConflict
// 查询错误 (3000-3999)
ErrQueryParseError
ErrQueryExecutionError
ErrInvalidOperator
ErrInvalidExpression
ErrTypeMismatch
// 聚合错误 (4000-4999)
ErrAggregationError
ErrPipelineError
ErrStageError
ErrGroupError
ErrSortError
// 索引错误 (5000-5999)
ErrIndexError
ErrIndexNotFound
ErrIndexOptionsError
// 事务错误 (6000-6999)
ErrTransactionError
ErrTransactionAbort
ErrTransactionCommit
// 认证授权错误 (7000-7999)
ErrAuthenticationError
ErrAuthorizationError
ErrPermissionDenied
// 资源错误 (8000-8999)
ErrResourceNotFound
ErrResourceExhausted
ErrTimeout
ErrUnavailable
)
// GomogError Gomog 错误类型
type GomogError struct {
Code ErrorCode `json:"code"`
Message string `json:"message"`
Details string `json:"details,omitempty"`
Cause error `json:"-"`
Metadata map[string]string `json:"metadata,omitempty"`
HTTPStatus int `json:"-"`
}
func (e *GomogError) Error() string {
if e.Cause != nil {
return fmt.Sprintf("[%d] %s: %v", e.Code, e.Message, e.Cause)
}
if e.Details != "" {
return fmt.Sprintf("[%d] %s: %s", e.Code, e.Message, e.Details)
}
return fmt.Sprintf("[%d] %s", e.Code, e.Message)
}
func (e *GomogError) Unwrap() error {
return e.Cause
}
// WithDetails 添加详细信息
func (e *GomogError) WithDetails(details string) *GomogError {
e.Details = details
return e
}
// WithMetadata 添加元数据
func (e *GomogError) WithMetadata(key, value string) *GomogError {
if e.Metadata == nil {
e.Metadata = make(map[string]string)
}
e.Metadata[key] = value
return e
}
// WithHTTPStatus 设置 HTTP 状态码
func (e *GomogError) WithHTTPStatus(status int) *GomogError {
e.HTTPStatus = status
return e
}
// GetHTTPStatus 获取 HTTP 状态码
func (e *GomogError) GetHTTPStatus() int {
if e.HTTPStatus != 0 {
return e.HTTPStatus
}
// 根据错误码返回默认 HTTP 状态码
switch e.Code {
case ErrOK:
return http.StatusOK
case ErrInternalError, ErrDatabaseError, ErrAggregationError:
return http.StatusInternalServerError
case ErrInvalidRequest, ErrQueryParseError, ErrInvalidOperator, ErrTypeMismatch:
return http.StatusBadRequest
case ErrCollectionNotFound, ErrDocumentNotFound, ErrResourceNotFound:
return http.StatusNotFound
case ErrDuplicateKey, ErrWriteConflict:
return http.StatusConflict
case ErrPermissionDenied, ErrAuthorizationError:
return http.StatusForbidden
case ErrAuthenticationError:
return http.StatusUnauthorized
case ErrTimeout:
return http.StatusRequestTimeout
case ErrUnavailable:
return http.StatusServiceUnavailable
default:
return http.StatusInternalServerError
}
}
// 预定义错误 - 通用错误 (1000-1999)
var (
ErrInternal = &GomogError{Code: ErrInternalError, Message: "internal error"}
ErrInvalidReq = &GomogError{Code: ErrInvalidRequest, Message: "invalid request"}
ErrNotImpl = &GomogError{Code: ErrNotImplemented, Message: "not implemented"}
)
// 预定义错误 - 数据库错误 (2000-2999)
var (
ErrCollectionNotFnd = &GomogError{Code: ErrCollectionNotFound, Message: "collection not found"}
ErrDocumentNotFnd = &GomogError{Code: ErrDocumentNotFound, Message: "document not found"}
ErrDuplicate = &GomogError{Code: ErrDuplicateKey, Message: "duplicate key"}
ErrDatabase = &GomogError{Code: ErrDatabaseError, Message: "database error"}
ErrWriteConf = &GomogError{Code: ErrWriteConflict, Message: "write conflict"}
ErrReadConf = &GomogError{Code: ErrReadConflict, Message: "read conflict"}
)
// 预定义错误 - 查询错误 (3000-3999)
var (
ErrQueryParse = &GomogError{Code: ErrQueryParseError, Message: "query parse error"}
ErrQueryExec = &GomogError{Code: ErrQueryExecutionError, Message: "query execution error"}
ErrInvalidOp = &GomogError{Code: ErrInvalidOperator, Message: "invalid operator"}
ErrInvalidExpr = &GomogError{Code: ErrInvalidExpression, Message: "invalid expression"}
ErrTypeMis = &GomogError{Code: ErrTypeMismatch, Message: "type mismatch"}
)
// 预定义错误 - 聚合错误 (4000-4999)
var (
ErrAggregation = &GomogError{Code: ErrAggregationError, Message: "aggregation error"}
ErrPipeline = &GomogError{Code: ErrPipelineError, Message: "pipeline error"}
ErrStage = &GomogError{Code: ErrStageError, Message: "stage error"}
ErrGroup = &GomogError{Code: ErrGroupError, Message: "group error"}
ErrSort = &GomogError{Code: ErrSortError, Message: "sort error"}
)
// 预定义错误 - 索引错误 (5000-5999)
var (
ErrIndex = &GomogError{Code: ErrIndexError, Message: "index error"}
ErrIndexNotFnd = &GomogError{Code: ErrIndexNotFound, Message: "index not found"}
ErrIndexOpts = &GomogError{Code: ErrIndexOptionsError, Message: "index options error"}
)
// 预定义错误 - 事务错误 (6000-6999)
var (
ErrTransaction = &GomogError{Code: ErrTransactionError, Message: "transaction error"}
ErrTransAbort = &GomogError{Code: ErrTransactionAbort, Message: "transaction aborted"}
ErrTransCommit = &GomogError{Code: ErrTransactionCommit, Message: "transaction commit error"}
)
// 预定义错误 - 认证授权错误 (7000-7999)
var (
ErrAuthentication = &GomogError{Code: ErrAuthenticationError, Message: "authentication error"}
ErrAuthorization = &GomogError{Code: ErrAuthorizationError, Message: "authorization error"}
ErrPermDenied = &GomogError{Code: ErrPermissionDenied, Message: "permission denied"}
)
// 预定义错误 - 资源错误 (8000-8999)
var (
ErrResourceNotFnd = &GomogError{Code: ErrResourceNotFound, Message: "resource not found"}
ErrResourceExhaust = &GomogError{Code: ErrResourceExhausted, Message: "resource exhausted"}
ErrTimeoutErr = &GomogError{Code: ErrTimeout, Message: "timeout"}
ErrUnavailableErr = &GomogError{Code: ErrUnavailable, Message: "service unavailable"}
)
// New 创建新错误
func New(code ErrorCode, message string) *GomogError {
return &GomogError{
Code: code,
Message: message,
}
}
// Newf 创建带格式化的新错误
func Newf(code ErrorCode, format string, args ...interface{}) *GomogError {
return &GomogError{
Code: code,
Message: fmt.Sprintf(format, args...),
}
}
// Wrap 包装错误
func Wrap(err error, code ErrorCode, message string) *GomogError {
return &GomogError{
Code: code,
Message: message,
Cause: err,
}
}
// Wrapf 包装错误并添加格式化消息
func Wrapf(err error, code ErrorCode, format string, args ...interface{}) *GomogError {
return &GomogError{
Code: code,
Message: fmt.Sprintf(format, args...),
Cause: err,
}
}
// Is 判断错误是否为目标类型
func (e *GomogError) Is(target error) bool {
if te, ok := target.(*GomogError); ok {
return e.Code == te.Code
}
return false
}
// IsCollectionNotFound 判断是否是集合不存在错误
func IsCollectionNotFound(err error) bool {
if e, ok := err.(*GomogError); ok {
return e.Code == ErrCollectionNotFound
}
return false
}
// IsDocumentNotFound 判断是否是文档不存在错误
func IsDocumentNotFound(err error) bool {
if e, ok := err.(*GomogError); ok {
return e.Code == ErrDocumentNotFound
}
return false
}
// IsDuplicateKey 判断是否是重复键错误
func IsDuplicateKey(err error) bool {
if e, ok := err.(*GomogError); ok {
return e.Code == ErrDuplicateKey
}
return false
}
// IsInvalidRequest 判断是否是无效请求错误
func IsInvalidRequest(err error) bool {
if e, ok := err.(*GomogError); ok {
return e.Code == ErrInvalidRequest
}
return false
}
// IsTypeMismatch 判断是否是类型不匹配错误
func IsTypeMismatch(err error) bool {
if e, ok := err.(*GomogError); ok {
return e.Code == ErrTypeMismatch
}
return false
}
// IsTimeout 判断是否是超时错误
func IsTimeout(err error) bool {
if e, ok := err.(*GomogError); ok {
return e.Code == ErrTimeout
}
return false
}
// GetErrorCode 获取错误码
func GetErrorCode(err error) ErrorCode {
if e, ok := err.(*GomogError); ok {
return e.Code
}
return ErrInternalError
}
// GetErrorMessage 获取错误消息
func GetErrorMessage(err error) string {
if e, ok := err.(*GomogError); ok {
return e.Message
}
return err.Error()
}
// ToHTTPStatus 将错误转换为 HTTP 状态码
func ToHTTPStatus(err error) int {
if e, ok := err.(*GomogError); ok {
return e.GetHTTPStatus()
}
return http.StatusInternalServerError
}
// Equal 判断两个错误是否相等
func Equal(err1, err2 error) bool {
if e1, ok := err1.(*GomogError); ok {
if e2, ok := err2.(*GomogError); ok {
return e1.Code == e2.Code && e1.Message == e2.Message
}
}
return err1 == err2
}