Files
seqlog/errors.go
bourdon 6862de12ff 新增:统一的错误类型系统 (errors.go)
主要功能:
- 定义哨兵错误(Sentinel Errors):ErrNilParameter, ErrInvalidCount,
  ErrInvalidRange, ErrAlreadyRunning, ErrNotFound, ErrCRCMismatch 等
- 实现结构化错误类型:TopicError, FileError, IndexError, ValidationError
- 提供错误检查辅助函数:IsTopicNotFound, IsIndexOutOfRange, IsCRCMismatch
- 支持 errors.Is 和 errors.As 进行错误判断

更新相关文件使用新错误类型:
- cursor.go: 使用 ValidationError 和 ErrCRCMismatch
- index.go: 使用 IndexError 处理索引越界
- query.go: 使用 ValidationError 验证参数
- seqlog_manager.go: 使用 TopicError 和 ErrAlreadyRegistered
- topic_processor.go: 使用 ErrAlreadyRunning 和 ErrInvalidConfig

测试覆盖:
- errors_test.go 提供完整的错误类型测试
- 所有现有测试继续通过

使用示例:
```go
// 检查 topic 是否存在
if IsTopicNotFound(err) {
    // 处理 topic 不存在的情况
}

// 检查索引越界
if IsIndexOutOfRange(err) {
    var indexErr *IndexError
    errors.As(err, &indexErr)
    fmt.Printf("index %d out of range\n", indexErr.Index)
}
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 01:56:22 +08:00

168 lines
4.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package seqlog
import (
"errors"
"fmt"
)
// 哨兵错误Sentinel Errors- 可以使用 errors.Is 进行判断
var (
// ErrNilParameter 表示必需的参数为 nil
ErrNilParameter = errors.New("required parameter is nil")
// ErrInvalidCount 表示 count 参数必须大于 0
ErrInvalidCount = errors.New("count must be greater than 0")
// ErrInvalidRange 表示索引或范围参数无效
ErrInvalidRange = errors.New("invalid index or range")
// ErrAlreadyRunning 表示组件已经在运行
ErrAlreadyRunning = errors.New("already running")
// ErrNotRunning 表示组件未运行
ErrNotRunning = errors.New("not running")
// ErrAlreadyRegistered 表示资源已经注册
ErrAlreadyRegistered = errors.New("already registered")
// ErrNotFound 表示资源未找到
ErrNotFound = errors.New("not found")
// ErrCRCMismatch 表示 CRC 校验失败
ErrCRCMismatch = errors.New("crc mismatch")
// ErrInvalidUUID 表示 UUID 格式无效
ErrInvalidUUID = errors.New("invalid uuid")
// ErrInvalidConfig 表示配置无效
ErrInvalidConfig = errors.New("invalid config")
)
// TopicError 表示与 topic 相关的错误
type TopicError struct {
Topic string // topic 名称
Op string // 操作名称(如 "write", "query", "start"
Err error // 底层错误
}
func (e *TopicError) Error() string {
if e.Err != nil {
return fmt.Sprintf("topic %s: %s: %v", e.Topic, e.Op, e.Err)
}
return fmt.Sprintf("topic %s: %s", e.Topic, e.Op)
}
func (e *TopicError) Unwrap() error {
return e.Err
}
// NewTopicError 创建一个 topic 相关的错误
func NewTopicError(topic, op string, err error) *TopicError {
return &TopicError{
Topic: topic,
Op: op,
Err: err,
}
}
// FileError 表示文件操作相关的错误
type FileError struct {
Path string // 文件路径
Op string // 操作名称(如 "open", "read", "write"
Err error // 底层错误
}
func (e *FileError) Error() string {
if e.Err != nil {
return fmt.Sprintf("file %s: %s: %v", e.Path, e.Op, e.Err)
}
return fmt.Sprintf("file %s: %s", e.Path, e.Op)
}
func (e *FileError) Unwrap() error {
return e.Err
}
// NewFileError 创建一个文件操作相关的错误
func NewFileError(path, op string, err error) *FileError {
return &FileError{
Path: path,
Op: op,
Err: err,
}
}
// IndexError 表示索引相关的错误
type IndexError struct {
Index int // 请求的索引
Max int // 最大有效索引
Err error // 底层错误(通常是 ErrInvalidRange
}
func (e *IndexError) Error() string {
if e.Err != nil {
return fmt.Sprintf("index %d out of range [0, %d): %v", e.Index, e.Max, e.Err)
}
return fmt.Sprintf("index %d out of range [0, %d)", e.Index, e.Max)
}
func (e *IndexError) Unwrap() error {
return e.Err
}
// NewIndexError 创建一个索引越界错误
func NewIndexError(index, max int) *IndexError {
return &IndexError{
Index: index,
Max: max,
Err: ErrInvalidRange,
}
}
// ValidationError 表示参数验证错误
type ValidationError struct {
Field string // 字段名称
Message string // 错误消息
Err error // 底层错误
}
func (e *ValidationError) Error() string {
if e.Err != nil {
return fmt.Sprintf("validation error: %s: %s: %v", e.Field, e.Message, e.Err)
}
return fmt.Sprintf("validation error: %s: %s", e.Field, e.Message)
}
func (e *ValidationError) Unwrap() error {
return e.Err
}
// NewValidationError 创建一个参数验证错误
func NewValidationError(field, message string, err error) *ValidationError {
return &ValidationError{
Field: field,
Message: message,
Err: err,
}
}
// IsTopicNotFound 检查错误是否为 topic 不存在
func IsTopicNotFound(err error) bool {
var topicErr *TopicError
if errors.As(err, &topicErr) {
return errors.Is(topicErr.Err, ErrNotFound)
}
return errors.Is(err, ErrNotFound)
}
// IsIndexOutOfRange 检查错误是否为索引越界
func IsIndexOutOfRange(err error) bool {
var indexErr *IndexError
return errors.As(err, &indexErr)
}
// IsCRCMismatch 检查错误是否为 CRC 校验失败
func IsCRCMismatch(err error) bool {
return errors.Is(err, ErrCRCMismatch)
}