主要更改: 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>
151 lines
3.8 KiB
Go
151 lines
3.8 KiB
Go
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"log"
|
||
|
||
"code.tczkiot.com/seqlog"
|
||
)
|
||
|
||
func main() {
|
||
logPath := "test_seqlog/app.log"
|
||
|
||
// ===== 示例 1:使用带索引的写入器 =====
|
||
fmt.Println("=== 示例 1:带索引的写入器 ===")
|
||
|
||
// 创建索引
|
||
index, err := seqlog.NewRecordIndex(logPath)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
defer index.Close()
|
||
|
||
// 创建写入器(使用共享索引)
|
||
writer, err := seqlog.NewLogWriter(logPath, index)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
|
||
// 写入日志时,索引会自动更新
|
||
var lastOffset int64
|
||
for i := 1; i <= 10; i++ {
|
||
data := fmt.Sprintf("日志记录 #%d", i)
|
||
offset, err := writer.Append([]byte(data))
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
lastOffset = offset
|
||
fmt.Printf("写入: offset=%d, data=%s\n", offset, data)
|
||
}
|
||
|
||
writer.Close()
|
||
fmt.Printf("索引文件已创建: %s.idx\n\n", logPath)
|
||
|
||
// ===== 示例 2:使用索引进行快速查询 =====
|
||
fmt.Println("=== 示例 2:带索引的查询器 ===")
|
||
|
||
// 先获取索引(由 writer 创建)
|
||
index2, err := seqlog.NewRecordIndex(logPath)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
defer index2.Close()
|
||
|
||
// 创建查询器(使用外部索引)
|
||
query, err := seqlog.NewRecordQuery(logPath, index2)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
defer query.Close()
|
||
|
||
// 获取记录总数(直接从索引读取,O(1))
|
||
count, err := query.GetRecordCount()
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
fmt.Printf("记录总数: %d\n", count)
|
||
|
||
// 从第 5 条记录开始查询
|
||
startIndex := 5
|
||
fmt.Printf("从第 %d 条记录开始查询\n", startIndex)
|
||
|
||
// 向索引递减方向查询(查询更早的记录)
|
||
// QueryOldest(5, 3) 查询索引 2, 3, 4(不包含 5),返回按索引递增排序
|
||
backward, err := query.QueryOldest(startIndex, 3)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
fmt.Printf("向索引递减方向查询 3 条记录:\n")
|
||
for _, rec := range backward {
|
||
fmt.Printf(" [索引 %d] 数据=%s\n", rec.Index, string(rec.Record.Data))
|
||
}
|
||
|
||
// 向索引递增方向查询(查询更新的记录)
|
||
// QueryNewest(5, 3) 查询索引 6, 7, 8(不包含 5),返回按索引递增排序
|
||
forward, err := query.QueryNewest(startIndex, 3)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
fmt.Printf("向索引递增方向查询 3 条记录:\n")
|
||
for _, rec := range forward {
|
||
fmt.Printf(" [索引 %d] 数据=%s\n", rec.Index, string(rec.Record.Data))
|
||
}
|
||
|
||
fmt.Println()
|
||
|
||
// ===== 示例 3:索引的自动恢复和重建 =====
|
||
fmt.Println("=== 示例 3:索引恢复 ===")
|
||
|
||
// 如果索引文件存在,会自动加载
|
||
// 如果索引文件不存在或损坏,会自动重建
|
||
index3, err := seqlog.NewRecordIndex(logPath)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
|
||
fmt.Printf("索引已加载: %d 条记录\n", index3.Count())
|
||
fmt.Printf("最后一条记录偏移: %d\n", index3.LastOffset())
|
||
|
||
// 二分查找:根据偏移量查找索引位置
|
||
idx := index3.FindIndex(lastOffset)
|
||
fmt.Printf("偏移量 %d 对应的索引位置: %d\n\n", lastOffset, idx)
|
||
index3.Close()
|
||
|
||
// ===== 示例 4:追加写入(索引自动更新)=====
|
||
fmt.Println("=== 示例 4:追加写入 ===")
|
||
|
||
// 重新打开索引和写入器,追加新数据
|
||
index5, err := seqlog.NewRecordIndex(logPath)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
defer index5.Close()
|
||
|
||
writer, err = seqlog.NewLogWriter(logPath, index5)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
|
||
for i := 11; i <= 15; i++ {
|
||
data := fmt.Sprintf("追加记录 #%d", i)
|
||
offset, err := writer.Append([]byte(data))
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
fmt.Printf("追加: offset=%d, data=%s\n", offset, data)
|
||
}
|
||
|
||
writer.Close()
|
||
|
||
// 验证索引已更新
|
||
index4, err := seqlog.NewRecordIndex(logPath)
|
||
if err != nil {
|
||
log.Fatal(err)
|
||
}
|
||
defer index4.Close()
|
||
|
||
fmt.Printf("索引已更新: 现有 %d 条记录\n", index4.Count())
|
||
|
||
fmt.Println("\n=== 所有示例完成 ===")
|
||
}
|