主要更改: 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>
107 lines
2.9 KiB
Go
107 lines
2.9 KiB
Go
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"log"
|
||
"log/slog"
|
||
|
||
"code.tczkiot.com/seqlog"
|
||
)
|
||
|
||
func main() {
|
||
// ===== TopicProcessor 作为聚合器使用 =====
|
||
fmt.Println("=== TopicProcessor 聚合器示例 ===")
|
||
|
||
// 创建 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. 查看记录统计:")
|
||
totalCount := tp.GetRecordCount()
|
||
fmt.Printf(" 记录总数: %d\n\n", totalCount)
|
||
|
||
// ===== 4. 使用查询器查询 =====
|
||
fmt.Println("4. 查询记录:")
|
||
|
||
// 查询最老的 3 条记录(从索引 0 开始)
|
||
oldest, err := tp.QueryOldest(3, 3)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
fmt.Println(" 查询最老的 3 条:")
|
||
for i, rws := range oldest {
|
||
fmt.Printf(" [%d] 索引=%d, 状态=%s, 数据=%s\n", i, rws.Index, rws.Status, string(rws.Record.Data))
|
||
}
|
||
|
||
// 查询最新的 2 条记录(从最后一条开始)
|
||
newest, err := tp.QueryNewest(totalCount-3, 2)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
fmt.Println(" 查询最新的 2 条:")
|
||
for i, rws := range newest {
|
||
fmt.Printf(" [%d] 索引=%d, 状态=%s, 数据=%s\n", i, rws.Index, rws.Status, string(rws.Record.Data))
|
||
}
|
||
fmt.Println()
|
||
|
||
// ===== 5. 从处理窗口查询 =====
|
||
fmt.Println("5. 从处理窗口查询:")
|
||
|
||
// 从处理窗口开始位置查询 3 条记录
|
||
processing, err := tp.QueryFromProcessing(3)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
fmt.Printf(" 从处理窗口查询到 %d 条记录:\n", len(processing))
|
||
for i, rec := range processing {
|
||
fmt.Printf(" [%d] 索引=%d, 状态=%s, 数据=%s\n", i, rec.Index, rec.Status, string(rec.Record.Data))
|
||
}
|
||
fmt.Println()
|
||
|
||
// ===== 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=== 所有示例完成 ===")
|
||
}
|