Files
seqlog/example/topic_processor/main.go

117 lines
3.0 KiB
Go
Raw Normal View History

重构:统一使用索引(Index)替代位置(Position)进行状态判断 ## 主要变更 ### 架构改进 - 明确索引(Index)与偏移(Offset)的职责分离 - Index: 记录序号(逻辑概念),用于状态判断 - Offset: 文件字节位置(物理概念),仅用于 I/O 操作 ### API 变更 - 删除所有 Position 相关方法: - `LogCursor.StartPos()/EndPos()` - `LogTailer.GetStartPos()/GetEndPos()` - `TopicProcessor.GetProcessingPosition()/GetReadPosition()` - `Seqlog.GetProcessingPosition()/GetReadPosition()` - 新增索引方法: - `LogCursor.StartIndex()/EndIndex()` - `LogTailer.GetStartIndex()/GetEndIndex()` - `TopicProcessor.GetProcessingIndex()/GetReadIndex()` - `Seqlog.GetProcessingIndex()/GetReadIndex()` - `Seqlog.GetProcessor()` - 获取 processor 实例以访问 Index ### 查询接口变更 - `RecordQuery.QueryOldest(startIndex, count, startIdx, endIdx)` - 使用索引参数 - `RecordQuery.QueryNewest(endIndex, count, startIdx, endIdx)` - 使用索引参数 - `RecordQuery.QueryAt(position, direction, count, startIdx, endIdx)` - startIdx/endIdx 用于状态判断 ### 性能优化 - 状态判断改用整数比较,不再需要计算偏移量 - 减少不必要的索引到偏移的转换 - 只在实际文件 I/O 时才获取 offset ### 测试更新 - 更新所有测试用例使用新的 Index API - 更新示例代码(topic_processor_example.go, webapp/main.go) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-03 23:48:21 +08:00
package main
import (
"fmt"
"log"
"log/slog"
"code.tczkiot.com/seqlog"
)
func main() {
// ===== TopicProcessor 作为聚合器使用 =====
fmt.Println("=== TopicProcessor 聚合器示例 ===")
重构:统一使用索引(Index)替代位置(Position)进行状态判断 ## 主要变更 ### 架构改进 - 明确索引(Index)与偏移(Offset)的职责分离 - Index: 记录序号(逻辑概念),用于状态判断 - Offset: 文件字节位置(物理概念),仅用于 I/O 操作 ### API 变更 - 删除所有 Position 相关方法: - `LogCursor.StartPos()/EndPos()` - `LogTailer.GetStartPos()/GetEndPos()` - `TopicProcessor.GetProcessingPosition()/GetReadPosition()` - `Seqlog.GetProcessingPosition()/GetReadPosition()` - 新增索引方法: - `LogCursor.StartIndex()/EndIndex()` - `LogTailer.GetStartIndex()/GetEndIndex()` - `TopicProcessor.GetProcessingIndex()/GetReadIndex()` - `Seqlog.GetProcessingIndex()/GetReadIndex()` - `Seqlog.GetProcessor()` - 获取 processor 实例以访问 Index ### 查询接口变更 - `RecordQuery.QueryOldest(startIndex, count, startIdx, endIdx)` - 使用索引参数 - `RecordQuery.QueryNewest(endIndex, count, startIdx, endIdx)` - 使用索引参数 - `RecordQuery.QueryAt(position, direction, count, startIdx, endIdx)` - startIdx/endIdx 用于状态判断 ### 性能优化 - 状态判断改用整数比较,不再需要计算偏移量 - 减少不必要的索引到偏移的转换 - 只在实际文件 I/O 时才获取 offset ### 测试更新 - 更新所有测试用例使用新的 Index API - 更新示例代码(topic_processor_example.go, webapp/main.go) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-03 23:48:21 +08:00
// 创建 TopicProcessor提供空 handler
logger := slog.Default()
tp, err := seqlog.NewTopicProcessor("test_seqlog", "app", logger, &seqlog.TopicConfig{
Handler: func(rec *seqlog.Record) error {
return nil // 示例中不需要处理
},
})
if err != nil {
log.Fatalf("创建 TopicProcessor 失败: %v", err)
}
// ===== 1. 写入数据 =====
fmt.Println("1. 写入数据:")
for i := 1; i <= 5; i++ {
data := fmt.Sprintf("消息 #%d", i)
offset, err := tp.Write([]byte(data))
if err != nil {
log.Fatal(err)
}
fmt.Printf(" 写入成功: offset=%d, data=%s\n", offset, data)
}
fmt.Println()
// ===== 2. 获取记录总数 =====
fmt.Println("2. 查询记录总数:")
count := tp.GetRecordCount()
fmt.Printf(" 总共 %d 条记录\n\n", count)
// ===== 3. 获取索引 =====
fmt.Println("3. 使用索引:")
index := tp.Index()
fmt.Printf(" 索引记录数: %d\n", index.Count())
fmt.Printf(" 最后偏移: %d\n\n", index.LastOffset())
// ===== 4. 使用查询器查询 =====
fmt.Println("4. 查询记录:")
// 查询最老的 3 条记录(从索引 0 开始)
oldest, err := tp.QueryOldest(0, 3)
if err != nil {
log.Fatal(err)
}
fmt.Println(" 查询最老的 3 条:")
for i, rws := range oldest {
fmt.Printf(" [%d] 状态=%s, 数据=%s\n", i, rws.Status, string(rws.Record.Data))
}
// 查询最新的 2 条记录(从最后一条开始)
totalCount := tp.GetRecordCount()
newest, err := tp.QueryNewest(totalCount-1, 2)
if err != nil {
log.Fatal(err)
}
fmt.Println(" 查询最新的 2 条:")
for i, rws := range newest {
fmt.Printf(" [%d] 状态=%s, 数据=%s\n", i, rws.Status, string(rws.Record.Data))
}
fmt.Println()
// ===== 5. 使用游标读取 =====
fmt.Println("5. 使用游标读取:")
cursor, err := tp.Cursor()
if err != nil {
log.Fatal(err)
}
defer cursor.Close()
// 读取 3 条记录
records, err := cursor.NextRange(3)
if err != nil {
log.Fatal(err)
}
fmt.Printf(" 读取了 %d 条记录:\n", len(records))
for i, rec := range records {
fmt.Printf(" [%d] %s\n", i, string(rec.Data))
}
// 提交游标位置
cursor.Commit()
fmt.Printf(" 游标位置: start=%d, end=%d\n\n", cursor.StartIndex(), cursor.EndIndex())
// ===== 6. 继续写入 =====
fmt.Println("6. 继续写入:")
for i := 6; i <= 8; i++ {
data := fmt.Sprintf("消息 #%d", i)
offset, _ := tp.Write([]byte(data))
fmt.Printf(" 写入成功: offset=%d, data=%s\n", offset, data)
}
fmt.Println()
// ===== 7. 再次查询总数 =====
fmt.Println("7. 更新后的记录总数:")
count = tp.GetRecordCount()
fmt.Printf(" 总共 %d 条记录\n\n", count)
// ===== 8. 获取统计信息 =====
fmt.Println("8. 统计信息:")
stats := tp.GetStats()
fmt.Printf(" 写入: %d 条, %d 字节\n", stats.WriteCount, stats.WriteBytes)
fmt.Println("\n=== 所有示例完成 ===")
}