Files
srdb/errors.go

337 lines
9.8 KiB
Go
Raw Permalink Normal View History

package srdb
import (
"errors"
"fmt"
)
// ErrCode 错误码类型
type ErrCode int
// 错误码定义
const (
// 通用错误 (1000-1999)
ErrCodeNotFound ErrCode = 1000 // 数据未找到
ErrCodeClosed ErrCode = 1001 // 对象已关闭
ErrCodeInvalidData ErrCode = 1002 // 无效数据
ErrCodeCorrupted ErrCode = 1003 // 数据损坏
ErrCodeExists ErrCode = 1004 // 对象已存在
ErrCodeInvalidParam ErrCode = 1005 // 无效参数
// 数据库错误 (2000-2999)
ErrCodeDatabaseNotFound ErrCode = 2000 // 数据库不存在
ErrCodeDatabaseExists ErrCode = 2001 // 数据库已存在
ErrCodeDatabaseClosed ErrCode = 2002 // 数据库已关闭
// 表错误 (3000-3999)
ErrCodeTableNotFound ErrCode = 3000 // 表不存在
ErrCodeTableExists ErrCode = 3001 // 表已存在
ErrCodeTableClosed ErrCode = 3002 // 表已关闭
// Schema 错误 (4000-4999)
ErrCodeSchemaNotFound ErrCode = 4000 // Schema 不存在
ErrCodeSchemaInvalid ErrCode = 4001 // Schema 无效
ErrCodeSchemaMismatch ErrCode = 4002 // Schema 不匹配
ErrCodeSchemaValidationFailed ErrCode = 4003 // Schema 验证失败
ErrCodeSchemaChecksumMismatch ErrCode = 4004 // Schema 校验和不匹配
// 字段错误 (5000-5999)
ErrCodeFieldNotFound ErrCode = 5000 // 字段不存在
ErrCodeFieldTypeMismatch ErrCode = 5001 // 字段类型不匹配
ErrCodeFieldRequired ErrCode = 5002 // 必填字段缺失
// 索引错误 (6000-6999)
ErrCodeIndexNotFound ErrCode = 6000 // 索引不存在
ErrCodeIndexExists ErrCode = 6001 // 索引已存在
ErrCodeIndexNotReady ErrCode = 6002 // 索引未就绪
ErrCodeIndexCorrupted ErrCode = 6003 // 索引损坏
// 文件格式错误 (7000-7999)
ErrCodeInvalidFormat ErrCode = 7000 // 无效的文件格式
ErrCodeUnsupportedVersion ErrCode = 7001 // 不支持的版本
ErrCodeInvalidMagicNumber ErrCode = 7002 // 无效的魔数
ErrCodeChecksumMismatch ErrCode = 7003 // 校验和不匹配
// WAL 错误 (8000-8999)
ErrCodeWALCorrupted ErrCode = 8000 // WAL 文件损坏
ErrCodeWALClosed ErrCode = 8001 // WAL 已关闭
// SSTable 错误 (9000-9999)
ErrCodeSSTableNotFound ErrCode = 9000 // SSTable 文件不存在
ErrCodeSSTableCorrupted ErrCode = 9001 // SSTable 文件损坏
// Compaction 错误 (10000-10999)
ErrCodeCompactionInProgress ErrCode = 10000 // Compaction 正在进行
ErrCodeNoCompactionNeeded ErrCode = 10001 // 不需要 Compaction
// 编解码错误 (11000-11999)
ErrCodeEncodeFailed ErrCode = 11000 // 编码失败
ErrCodeDecodeFailed ErrCode = 11001 // 解码失败
)
// 错误码消息映射
var errCodeMessages = map[ErrCode]string{
// 通用错误
ErrCodeNotFound: "not found",
ErrCodeClosed: "already closed",
ErrCodeInvalidData: "invalid data",
ErrCodeCorrupted: "data corrupted",
ErrCodeExists: "already exists",
ErrCodeInvalidParam: "invalid parameter",
// 数据库错误
ErrCodeDatabaseNotFound: "database not found",
ErrCodeDatabaseExists: "database already exists",
ErrCodeDatabaseClosed: "database closed",
// 表错误
ErrCodeTableNotFound: "table not found",
ErrCodeTableExists: "table already exists",
ErrCodeTableClosed: "table closed",
// Schema 错误
ErrCodeSchemaNotFound: "schema not found",
ErrCodeSchemaInvalid: "schema invalid",
ErrCodeSchemaMismatch: "schema mismatch",
ErrCodeSchemaValidationFailed: "schema validation failed",
ErrCodeSchemaChecksumMismatch: "schema checksum mismatch",
// 字段错误
ErrCodeFieldNotFound: "field not found",
ErrCodeFieldTypeMismatch: "field type mismatch",
ErrCodeFieldRequired: "required field missing",
// 索引错误
ErrCodeIndexNotFound: "index not found",
ErrCodeIndexExists: "index already exists",
ErrCodeIndexNotReady: "index not ready",
ErrCodeIndexCorrupted: "index corrupted",
// 文件格式错误
ErrCodeInvalidFormat: "invalid file format",
ErrCodeUnsupportedVersion: "unsupported version",
ErrCodeInvalidMagicNumber: "invalid magic number",
ErrCodeChecksumMismatch: "checksum mismatch",
// WAL 错误
ErrCodeWALCorrupted: "wal corrupted",
ErrCodeWALClosed: "wal closed",
// SSTable 错误
ErrCodeSSTableNotFound: "sstable not found",
ErrCodeSSTableCorrupted: "sstable corrupted",
// Compaction 错误
ErrCodeCompactionInProgress: "compaction in progress",
ErrCodeNoCompactionNeeded: "no compaction needed",
// 编解码错误
ErrCodeEncodeFailed: "encode failed",
ErrCodeDecodeFailed: "decode failed",
}
// Error 错误类型
type Error struct {
Code ErrCode // 错误码
Message string // 错误消息
Cause error // 原始错误
}
// Error 实现 error 接口
func (e *Error) Error() string {
if e.Cause != nil {
return fmt.Sprintf("[%d] %s: %v", e.Code, e.Message, e.Cause)
}
return fmt.Sprintf("[%d] %s", e.Code, e.Message)
}
// Unwrap 支持 errors.Is 和 errors.As
func (e *Error) Unwrap() error {
return e.Cause
}
// Is 判断错误码是否相同
func (e *Error) Is(target error) bool {
t, ok := target.(*Error)
if !ok {
return false
}
return e.Code == t.Code
}
// NewError 创建新错误
func NewError(code ErrCode, cause error) *Error {
msg, ok := errCodeMessages[code]
if !ok {
msg = "unknown error"
}
return &Error{
Code: code,
Message: msg,
Cause: cause,
}
}
// NewErrorf 创建带格式化消息的错误
// 注意:如果 args 中最后一个参数是 error 类型,它会被设置为 Cause
func NewErrorf(code ErrCode, format string, args ...any) *Error {
var cause error
// 检查最后一个参数是否为 error
if len(args) > 0 {
if err, ok := args[len(args)-1].(error); ok {
cause = err
// 从 args 中移除最后一个 error 参数
args = args[:len(args)-1]
}
}
return &Error{
Code: code,
Message: fmt.Sprintf(format, args...),
Cause: cause,
}
}
// 预定义的常用错误(向后兼容)
var (
// ErrNotFound 数据未找到
ErrNotFound = NewError(ErrCodeNotFound, nil)
// ErrClosed 对象已关闭
ErrClosed = NewError(ErrCodeClosed, nil)
// ErrInvalidData 无效数据
ErrInvalidData = NewError(ErrCodeInvalidData, nil)
// ErrCorrupted 数据损坏
ErrCorrupted = NewError(ErrCodeCorrupted, nil)
)
// 数据库错误(向后兼容)
var (
ErrDatabaseNotFound = NewError(ErrCodeDatabaseNotFound, nil)
ErrDatabaseExists = NewError(ErrCodeDatabaseExists, nil)
ErrDatabaseClosed = NewError(ErrCodeDatabaseClosed, nil)
)
// 表错误(向后兼容)
var (
ErrTableNotFound = NewError(ErrCodeTableNotFound, nil)
ErrTableExists = NewError(ErrCodeTableExists, nil)
ErrTableClosed = NewError(ErrCodeTableClosed, nil)
)
// Schema 错误(向后兼容)
var (
ErrSchemaNotFound = NewError(ErrCodeSchemaNotFound, nil)
ErrSchemaInvalid = NewError(ErrCodeSchemaInvalid, nil)
ErrSchemaMismatch = NewError(ErrCodeSchemaMismatch, nil)
ErrSchemaValidationFailed = NewError(ErrCodeSchemaValidationFailed, nil)
ErrSchemaChecksumMismatch = NewError(ErrCodeSchemaChecksumMismatch, nil)
)
// 字段错误(向后兼容)
var (
ErrFieldNotFound = NewError(ErrCodeFieldNotFound, nil)
ErrFieldTypeMismatch = NewError(ErrCodeFieldTypeMismatch, nil)
ErrFieldRequired = NewError(ErrCodeFieldRequired, nil)
)
// 索引错误(向后兼容)
var (
ErrIndexNotFound = NewError(ErrCodeIndexNotFound, nil)
ErrIndexExists = NewError(ErrCodeIndexExists, nil)
ErrIndexNotReady = NewError(ErrCodeIndexNotReady, nil)
ErrIndexCorrupted = NewError(ErrCodeIndexCorrupted, nil)
)
// 文件格式错误(向后兼容)
var (
ErrInvalidFormat = NewError(ErrCodeInvalidFormat, nil)
ErrUnsupportedVersion = NewError(ErrCodeUnsupportedVersion, nil)
ErrInvalidMagicNumber = NewError(ErrCodeInvalidMagicNumber, nil)
ErrChecksumMismatch = NewError(ErrCodeChecksumMismatch, nil)
)
// WAL 错误(向后兼容)
var (
ErrWALCorrupted = NewError(ErrCodeWALCorrupted, nil)
ErrWALClosed = NewError(ErrCodeWALClosed, nil)
)
// SSTable 错误(向后兼容)
var (
ErrSSTableNotFound = NewError(ErrCodeSSTableNotFound, nil)
ErrSSTableCorrupted = NewError(ErrCodeSSTableCorrupted, nil)
)
// Compaction 错误(向后兼容)
var (
ErrCompactionInProgress = NewError(ErrCodeCompactionInProgress, nil)
ErrNoCompactionNeeded = NewError(ErrCodeNoCompactionNeeded, nil)
)
// 编解码错误(向后兼容)
var (
ErrEncodeFailed = NewError(ErrCodeEncodeFailed, nil)
ErrDecodeFailed = NewError(ErrCodeDecodeFailed, nil)
)
// 辅助函数
// GetErrorCode 获取错误码
func GetErrorCode(err error) ErrCode {
var e *Error
if errors.As(err, &e) {
return e.Code
}
return 0
}
// IsError 判断错误是否匹配指定的错误码
func IsError(err error, code ErrCode) bool {
return GetErrorCode(err) == code
}
// IsNotFound 判断是否是 NotFound 错误
func IsNotFound(err error) bool {
code := GetErrorCode(err)
return code == ErrCodeNotFound ||
code == ErrCodeTableNotFound ||
code == ErrCodeDatabaseNotFound ||
code == ErrCodeIndexNotFound ||
code == ErrCodeFieldNotFound ||
code == ErrCodeSchemaNotFound ||
code == ErrCodeSSTableNotFound
}
// IsCorrupted 判断是否是数据损坏错误
func IsCorrupted(err error) bool {
code := GetErrorCode(err)
return code == ErrCodeCorrupted ||
code == ErrCodeWALCorrupted ||
code == ErrCodeSSTableCorrupted ||
code == ErrCodeIndexCorrupted ||
code == ErrCodeChecksumMismatch ||
code == ErrCodeSchemaChecksumMismatch
}
// IsClosed 判断是否是已关闭错误
func IsClosed(err error) bool {
code := GetErrorCode(err)
return code == ErrCodeClosed ||
code == ErrCodeDatabaseClosed ||
code == ErrCodeTableClosed ||
code == ErrCodeWALClosed
}
// WrapError 包装错误并添加上下文
func WrapError(err error, format string, args ...any) error {
if err == nil {
return nil
}
msg := fmt.Sprintf(format, args...)
return fmt.Errorf("%s: %w", msg, err)
}