重构:重命名核心组件并增强查询功能

主要更改:

1. 核心重命名
   - Seqlog -> LogHub (更准确地反映其作为日志中枢的角色)
   - NewSeqlog() -> NewLogHub()
   - LogCursor -> ProcessCursor (更准确地反映其用于处理场景)
   - seqlog_manager.go -> loghub.go (文件名与结构体名对应)

2. TopicProcessor.Reset 增强
   - 如果正在运行且没有待处理的日志,会自动停止后重置
   - 如果有待处理的日志,返回详细错误(显示已处理/总记录数)
   - 简化了 LogHub.ResetTopic,移除显式 Stop 调用

3. 新增查询方法
   - TopicProcessor.QueryFromFirst(count) - 从第一条记录向索引递增方向查询
   - TopicProcessor.QueryFromLast(count) - 从最后一条记录向索引递减方向查询
   - LogHub.QueryFromFirst(topic, count)
   - LogHub.QueryFromLast(topic, count)

4. 测试覆盖
   - 添加 query_test.go - QueryFromProcessing 测试
   - 添加 TestQueryFromFirstAndLast - TopicProcessor 查询测试
   - 添加 TestLogHubQueryFromFirstAndLast - LogHub 查询测试
   - 添加 TestTopicResetWithPendingRecords - Reset 增强功能测试

5. 示例代码
   - 添加 example/get_record/ - 演示 QueryFromProcessing 用法
   - 更新所有示例以使用 LogHub 和新 API

所有测试通过 

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-04 13:26:21 +08:00
parent dfdc27c67f
commit 90cc9e21c9
14 changed files with 795 additions and 275 deletions

119
query.go
View File

@@ -36,7 +36,14 @@ func (s RecordStatus) String() string {
// RecordWithStatus 带状态的记录
type RecordWithStatus struct {
Record *Record
Status RecordStatus
Index int // 记录在日志文件中的索引位置
Status RecordStatus // 记录的处理状态
}
// RecordWithIndex 带索引的记录
type RecordWithIndex struct {
Record *Record
Index int // 记录在日志文件中的索引位置
}
// RecordQuery 记录查询器
@@ -115,26 +122,80 @@ func (rq *RecordQuery) readRecordsForward(startIndex, count int) ([]*Record, err
return results, nil
}
// QueryOldest 从指定索引向索引递方向查询记录
// startIndex: 查询起始索引
// QueryOldest 从参考索引向索引递方向查询记录(查询更早的记录)
// refIndex: 参考索引位置
// count: 查询数量
// 返回的记录按索引递增方向排序
func (rq *RecordQuery) QueryOldest(startIndex, count int) ([]*Record, error) {
// 返回的记录按索引递增方向排序,包含索引信息
// 例如QueryOldest(5, 3) 查询索引 2, 3, 4不包含 5返回 [2, 3, 4]
func (rq *RecordQuery) QueryOldest(refIndex, count int) ([]*RecordWithIndex, error) {
if count <= 0 {
return nil, NewValidationError("count", "count must be greater than 0", ErrInvalidCount)
}
totalCount := rq.index.Count()
if totalCount == 0 {
return []*Record{}, nil
return []*RecordWithIndex{}, nil
}
// 校验起始索引
// 验证参考索引范围(严格模式)
if refIndex < 0 || refIndex > totalCount {
return nil, NewValidationError("refIndex", fmt.Sprintf("refIndex %d out of range [0, %d]", refIndex, totalCount), ErrInvalidRange)
}
// 计算实际起始索引(向索引递减方向)
startIndex := refIndex - count
if startIndex < 0 {
startIndex = 0
count = refIndex // 调整实际数量
}
if count <= 0 {
return []*RecordWithIndex{}, nil
}
// 读取记录
records, err := rq.readRecordsForward(startIndex, count)
if err != nil {
return nil, err
}
// 转换为带索引的记录
results := make([]*RecordWithIndex, len(records))
for i, rec := range records {
results[i] = &RecordWithIndex{
Record: rec,
Index: startIndex + i,
}
}
return results, nil
}
// QueryNewest 从参考索引向索引递增方向查询记录(查询更新的记录)
// refIndex: 参考索引位置
// count: 查询数量
// 返回的记录按索引递增方向排序,包含索引信息
// 例如QueryNewest(5, 3) 查询索引 6, 7, 8不包含 5返回 [6, 7, 8]
func (rq *RecordQuery) QueryNewest(refIndex, count int) ([]*RecordWithIndex, error) {
if count <= 0 {
return nil, NewValidationError("count", "count must be greater than 0", ErrInvalidCount)
}
totalCount := rq.index.Count()
if totalCount == 0 {
return []*RecordWithIndex{}, nil
}
// 验证参考索引范围(严格模式)
// QueryNewest 允许 refIndex = -1从头开始查询
if refIndex < -1 || refIndex >= totalCount {
return nil, NewValidationError("refIndex", fmt.Sprintf("refIndex %d out of range [-1, %d)", refIndex, totalCount), ErrInvalidRange)
}
// 计算实际起始索引(向索引递增方向)
startIndex := refIndex + 1
if startIndex >= totalCount {
return []*Record{}, nil
return []*RecordWithIndex{}, nil
}
// 限制查询数量
@@ -143,40 +204,22 @@ func (rq *RecordQuery) QueryOldest(startIndex, count int) ([]*Record, error) {
count = remainCount
}
return rq.readRecordsForward(startIndex, count)
}
// QueryNewest 从指定索引向索引递减方向查询记录
// endIndex: 查询的最大索引(向前查询更早的记录)
// count: 查询数量
// 返回的记录按索引递增方向排序(与 QueryOldest 一致)
func (rq *RecordQuery) QueryNewest(endIndex, count int) ([]*Record, error) {
if count <= 0 {
return nil, NewValidationError("count", "count must be greater than 0", ErrInvalidCount)
// 读取记录
records, err := rq.readRecordsForward(startIndex, count)
if err != nil {
return nil, err
}
totalCount := rq.index.Count()
if totalCount == 0 {
return []*Record{}, nil
// 转换为带索引的记录
results := make([]*RecordWithIndex, len(records))
for i, rec := range records {
results[i] = &RecordWithIndex{
Record: rec,
Index: startIndex + i,
}
}
// 校验结束索引
if endIndex < 0 {
return []*Record{}, nil
}
if endIndex >= totalCount {
endIndex = totalCount - 1
}
// 计算实际起始索引(向索引递减方向查询 count 条)
queryStartIdx := endIndex - count + 1
if queryStartIdx < 0 {
queryStartIdx = 0
count = endIndex + 1 // 调整实际数量
}
// 向前读取,返回按索引递增排序的结果
return rq.readRecordsForward(queryStartIdx, count)
return results, nil
}
// GetRecordCount 获取记录总数