17 Commits

Author SHA1 Message Date
6fb0731935 重构:为核心组件实现 Reset 方法优化重置机制
为所有核心组件添加 Reset() 方法:
- LogWriter.Reset(): 删除并重新创建日志文件,保持 index 和 wbuf 引用不变
- RecordIndex.Reset(): 清空索引数据并重新创建索引文件
- RecordQuery.Reset(): 关闭并重新打开日志文件
- ProcessCursor.Reset(): 删除位置文件并重置游标位置
- LogTailer.Reset(): 重置内部 channel 状态

优化 TopicProcessor.Reset() 实现:
- 不再销毁和重建组件对象
- 通过调用各组件的 Reset() 方法重置状态
- 保持组件间引用关系稳定
- 减少代码行数约 20 行
- 避免空指针风险和内存分配开销

代码改进:
- LogWriter 添加 path 字段用于重置
- 移除 topic_processor.go 中未使用的 os import
- 职责分离更清晰,每个组件管理自己的重置逻辑

测试结果:
- TestTopicReset: PASS
- TestTopicResetWithPendingRecords: PASS
- 所有 TopicProcessor 相关测试通过

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 21:58:54 +08:00
bcc328b129 重构:TopicProcessor 状态管理系统与 Reset 方法优化
新增功能:
- 添加 ProcessorState 状态类型(Idle/Starting/Running/Stopping/Stopped/Resetting/Error)
- 添加 ProcessorStatus 结构体和状态管理方法(GetState/GetStatus/setState)
- 实现状态转换逻辑和访问控制(CanWrite/CanQuery)
- 新增 CanReset() 方法检查是否可执行重置操作

Reset 方法优化:
- 重写 Reset() 方法,不再停止 processor
- 只有在无待处理记录时才能执行重置
- 进入 Resetting 状态期间阻止所有读写操作
- 重置后自动恢复到之前的运行状态
- 正确关闭并重置 cursor 和 stats 组件
- 调整执行顺序:先关闭组件,再删除文件,后重新初始化

错误处理增强:
- 添加 ErrProcessorResetting 和 ErrInvalidState 错误类型
- 添加 EventStateChanged 事件类型
- 修复 writer/index 为 nil 时的空指针问题

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 18:56:52 +08:00
810664eb12 重构:优化记录格式并修复核心功能
- 修改记录存储格式为 [4B len][8B offset][4B CRC][16B UUID][data]
- 修复 TopicProcessor 中 WaitGroup 使用错误导致 handler 不执行的问题
- 修复写入保护逻辑,避免 dirtyOffset=-1 时误判为写入中
- 添加统计信息定期持久化功能
- 改进 UTF-8 字符截断处理,防止 CJK 字符乱码
- 优化 Web UI:显示人类可读的文件大小,支持点击外部关闭弹窗
- 重构示例代码,添加 webui 和 webui_integration 示例

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 17:54:49 +08:00
955a467248 优化:减少代码重复和内存分配
主要优化:

1. 提取重复代码(topic_processor.go)
   - 新增 addStatusToRecords() 辅助方法
   - QueryOldest 和 QueryNewest 中的状态添加逻辑重复,已提取
   - 减少 38 行重复代码

2. 优化内存分配(index.go)
   - 在 RecordIndex 结构体中添加可重用的 entryBuf
   - Append 方法不再每次都分配 8 字节 buffer
   - 高频写入场景下可显著减少 GC 压力

性能提升:
- 减少内存分配次数(每次写入索引节省 1 次分配)
- 提高代码可维护性(消除重复代码)
- 所有测试通过 

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 13:32:44 +08:00
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
dfdc27c67f 修复:统一查询方法的返回顺序为索引递增
重要变更:
- QueryOldest 和 QueryNewest 现在都返回按索引递增排序的结果
- 移除了 QueryNewest 中的结果反转操作(line 184-187)

方法行为说明:
- QueryOldest(startIndex, count): 从 startIndex 向索引递增方向查询
- QueryNewest(endIndex, count): 从 endIndex 向索引递减方向查询
- 两者返回结果都按索引递增方向排序(一致性)

更新内容:
1. query.go:
   - 移除 QueryNewest 的反转操作
   - 更新两个方法的注释
2. topic_processor.go: 更新注释与实现一致
3. seqlog_test.go: 更新测试预期结果
4. example/index/main.go: 更新注释和输出说明

测试验证:
- 所有测试通过(go test ./... -short)
- 示例编译成功

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 11:55:44 +08:00
9b7a9c2734 更新:.gitignore 添加示例程序的编译产物
添加忽略规则:
- example/concurrent/concurrent
- example/index/index
- example/topic_processor/topic_processor

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 11:49:21 +08:00
5379ec3e90 修复:webapp 翻页逻辑和编译错误
前端改进:
- 添加 direction 追踪翻页方向(forward/backward)
- 使用 startIndex/endIndex 追踪当前显示范围
- topics 列表自动排序
- 移除 currentCenterIndex,改用更清晰的边界索引

后端改进:
- 支持 direction 参数控制查询方向
- backward:从 startIndex 向前查询(更早的记录)
- forward:从 endIndex 向后查询(更新的记录)
- 修复 QueryNewest/QueryOldest 返回值处理
- 正确计算 startRecordIndex(基于查询结果)

修复编译错误:
- example/index/main.go:修正 QueryNewest/QueryOldest 返回值数量
- example/webapp/main.go:修正变量重复定义和未定义错误

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 11:48:36 +08:00
92063e581f 清理:移除冗余的 RUN_CONCURRENT.md
该文件内容已合并到 example/README.md 中,不再需要单独维护。

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 02:05:24 +08:00
6862de12ff 新增:统一的错误类型系统 (errors.go)
主要功能:
- 定义哨兵错误(Sentinel Errors):ErrNilParameter, ErrInvalidCount,
  ErrInvalidRange, ErrAlreadyRunning, ErrNotFound, ErrCRCMismatch 等
- 实现结构化错误类型:TopicError, FileError, IndexError, ValidationError
- 提供错误检查辅助函数:IsTopicNotFound, IsIndexOutOfRange, IsCRCMismatch
- 支持 errors.Is 和 errors.As 进行错误判断

更新相关文件使用新错误类型:
- cursor.go: 使用 ValidationError 和 ErrCRCMismatch
- index.go: 使用 IndexError 处理索引越界
- query.go: 使用 ValidationError 验证参数
- seqlog_manager.go: 使用 TopicError 和 ErrAlreadyRegistered
- topic_processor.go: 使用 ErrAlreadyRunning 和 ErrInvalidConfig

测试覆盖:
- errors_test.go 提供完整的错误类型测试
- 所有现有测试继续通过

使用示例:
```go
// 检查 topic 是否存在
if IsTopicNotFound(err) {
    // 处理 topic 不存在的情况
}

// 检查索引越界
if IsIndexOutOfRange(err) {
    var indexErr *IndexError
    errors.As(err, &indexErr)
    fmt.Printf("index %d out of range\n", indexErr.Index)
}
```

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 01:56:22 +08:00
7a5d5df28b 修改:webapp 只自动刷新统计信息,日志需手动刷新
- 定时器只更新统计信息,不自动加载日志记录
- 日志需要用户手动点击「刷新日志」或翻页按钮查看
- 避免在用户浏览历史记录时被自动刷新打断

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 01:48:35 +08:00
48b0b56ce7 功能:实现 webapp 基于索引的日志导航
主要改进:
- 添加索引导航支持:前进/后退按钮现在基于记录索引加载数据
- 后端 API 支持可选的 index 参数,返回包含 centerIndex 的响应
- 前端追踪 currentCenterIndex,实现精确的页面跳转
- 在状态徽章中显示记录索引号 [#索引]
- 修复日志显示逻辑:从追加模式改为完全重新渲染

代码优化:
- concurrent: 使用 Go 1.25 range 语法和 min 函数
- concurrent: 使用 WaitGroup.Go 方法简化 goroutine 启动
- topic_processor: 修正格式化输出

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 01:43:48 +08:00
3d82a6845e 重构:将示例文件组织到子目录
修复 Go 规范问题:一个目录不能有多个 package main

文件结构调整:
- example/concurrent_example.go → example/concurrent/main.go
- example/index_example.go → example/index/main.go
- example/topic_processor_example.go → example/topic_processor/main.go

修复 API 适配:
- index/main.go: 更新为新的查询 API(移除 startIdx/endIdx 参数)
- webapp/main.go: 使用 processor.Query 方法替代 RecordQuery
  - 移除 queryCache,直接使用 processor
  - 更新查询调用,移除状态参数

文档更新:
- example/README.md: 更新所有示例的运行路径
- example/RUN_CONCURRENT.md: 更新运行命令

所有示例编译测试通过 
2025-10-04 01:27:56 +08:00
4ec153c1ac 新增:高并发示例和文档
新增文件:
- example/concurrent_example.go: 5 分钟高并发测试示例
  - 场景 1: 并发写入 6000 条消息
  - 场景 2: 并发查询 4000 次
  - 场景 3: 混合读写测试
  - 场景 4: 持续压测 4 分钟(实时进度显示)
  - 场景 5: 统计信息汇总

- example/README.md: 完整的示例文档
  - 所有示例的使用说明
  - 最佳实践和性能优化建议
  - 常见问题排查

- example/RUN_CONCURRENT.md: 快速运行指南
  - 运行方式和时间预估
  - 后台运行方法
  - 自定义参数说明

修改文件:
- .gitignore: 修正 example 目录的忽略规则
  - 移除对整个 example/ 的忽略
  - 只忽略 example/test_*/ 测试目录

性能指标:
- 写入吞吐量:~220 msg/s
- 查询吞吐量:~400-1500 query/s
- 总数据量:53661 条消息,1.1 MB
2025-10-04 01:08:37 +08:00
5c028a55b3 重构:简化查询接口
- RecordQuery.QueryOldest 和 QueryNewest 不再接收 startIdx/endIdx 参数
- 查询方法返回纯 Record 列表,状态判断移到调用方
- TopicProcessor 的查询方法负责添加状态信息
- 更新所有测试文件以适配新接口
2025-10-04 00:23:09 +08:00
a421ca1d85 重构:简化 RecordIndex 结构体
删除独立的 IndexHeader 结构体,将 magic 和 version 字段直接放入 RecordIndex,减少不必要的嵌套层级。

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-03 23:55:45 +08:00
de39339620 重构:统一使用索引(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:50:53 +08:00