# Stats Buffer

## Purpose

TBD - 为统计数据提供内存缓冲，优化写入性能。

## Requirements

### Requirement: StatsBuffer 内存缓冲

系统 SHALL 为统计数据提供内存缓冲，使用 sync.Map + atomic.Int64 进行计数。

#### Scenario: 缓冲数据结构

- **WHEN** 创建 StatsBuffer
- **THEN** SHALL 使用 sync.Map 存储计数器（key = providerID/modelName/date）
- **THEN** SHALL 使用 atomic.Int64 进行计数
- **THEN** SHALL 支持配置刷新间隔和阈值

### Requirement: 原子计数

StatsBuffer SHALL 使用原子操作进行计数。

#### Scenario: Increment 计数

- **WHEN** 调用 StatsBuffer.Increment
- **THEN** SHALL 使用 atomic.AddInt64 增加计数
- **THEN** SHALL 无锁操作
- **THEN** SHALL 线程安全

#### Scenario: Increment 创建计数器

- **WHEN** 调用 StatsBuffer.Increment 且计数器不存在
- **THEN** SHALL 使用 sync.Map.LoadOrStore 创建计数器
- **THEN** SHALL 初始化计数器为 0
- **THEN** SHALL 原子增加计数

#### Scenario: 并发计数

- **WHEN** 多个 goroutine 并发 Increment
- **THEN** SHALL 计数准确
- **THEN** SHALL 无竞态条件

### Requirement: 定时刷新

StatsBuffer SHALL 支持定时刷新到数据库。

#### Scenario: 定时刷新触发

- **WHEN** 后台刷新协程运行
- **THEN** SHALL 每隔 flushInterval 触发刷新
- **THEN** SHALL 调用 StatsRepository.BatchUpdate 写入数据库

#### Scenario: 刷新间隔配置

- **WHEN** 创建 StatsBuffer
- **THEN** 默认 flushInterval 为 5 秒
- **THEN** 可通过 WithFlushInterval 选项配置

### Requirement: 阈值触发刷新

StatsBuffer SHALL 支持累计阈值触发刷新。

#### Scenario: 阈值触发

- **WHEN** 累计计数达到 flushThreshold
- **THEN** SHALL 异步触发刷新
- **THEN** SHALL 不阻塞请求

#### Scenario: 阈值配置

- **WHEN** 创建 StatsBuffer
- **THEN** 默认 flushThreshold 为 100
- **THEN** 可通过 WithFlushThreshold 选项配置

### Requirement: 批量写入数据库

StatsBuffer SHALL 批量写入统计数据到数据库。

#### Scenario: 批量写入

- **WHEN** 刷新触发
- **THEN** SHALL 遍历所有计数器
- **THEN** SHALL 使用 atomic.SwapInt64(counter, 0) 获取并清零计数器
- **THEN** SHALL 调用 StatsRepository.BatchUpdate 批量写入
- **THEN** SHALL 重置 totalCount 为 0

#### Scenario: SwapInt64 清零计数器

- **WHEN** flush 收集计数器
- **THEN** SHALL 使用 SwapInt64 原子操作获取当前计数并清零
- **THEN** SHALL 保证计数不丢失（新计数会累加到已清零的计数器）
- **THEN** SHALL 不阻塞后续 Increment 操作

#### Scenario: 写入失败保留计数器

- **WHEN** BatchUpdate 失败
- **THEN** SHALL 将计数加回计数器（使用 atomic.AddInt64）
- **THEN** SHALL 记录错误日志
- **THEN** SHALL 继续处理其他条目

### Requirement: 优雅关闭

StatsBuffer SHALL 支持优雅关闭，确保最后的统计写入数据库。

#### Scenario: Stop 等待刷新完成

- **WHEN** 调用 StatsBuffer.Stop
- **THEN** SHALL 停止后台刷新协程
- **THEN** SHALL 执行最后一次刷新
- **THEN** SHALL 等待刷新完成
- **THEN** SHALL 保证统计数据不丢失

#### Scenario: 无超时

- **WHEN** Stop 等待刷新
- **THEN** SHALL 无超时限制
- **THEN** SHALL 等待刷新完成

### Requirement: StatsService 使用缓冲

StatsService SHALL 使用 StatsBuffer 进行统计记录。

#### Scenario: Record 使用缓冲

- **WHEN** 调用 StatsService.Record
- **THEN** SHALL 调用 StatsBuffer.Increment
- **THEN** SHALL 不直接调用 StatsRepository.Record
- **THEN** SHALL 立即返回，不阻塞

### Requirement: StatsRepository 扩展

StatsRepository SHALL 新增 BatchUpdate 方法。

#### Scenario: BatchUpdate 方法

- **WHEN** 调用 StatsRepository.BatchUpdate
- **THEN** SHALL 使用事务更新或创建统计记录
- **THEN** SHALL 使用 request_count + delta 更新
- **THEN** SHALL 支持批量增量更新

### Requirement: 并发安全

StatsBuffer SHALL 支持并发访问。

#### Scenario: 并发 Increment 和 flush

- **WHEN** 并发 Increment 和 flush
- **THEN** SHALL 无竞态条件
- **THEN** SHALL 计数准确（可能延迟到下次 flush）

#### Scenario: flush 期间 Increment

- **WHEN** flush 正在执行
- **THEN** 新的 Increment SHALL 继续计数
- **THEN** SHALL 不会丢失计数
