Files
seqlog/example/index/main.go
bourdon 90cc9e21c9 重构:重命名核心组件并增强查询功能
主要更改:

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>
2025-10-04 13:26:21 +08:00

151 lines
3.8 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 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=== 所有示例完成 ===")
}