Files
go-trustlog/api/persistence/sql/mysql.sql
ryan 88f80ffa5e feat: 新增数据库持久化模块(Persistence),实现 Cursor + Retry 双层架构
## 核心功能

### 1. 数据库持久化支持
- 新增完整的 Persistence 模块 (api/persistence/)
- 支持三种持久化策略:
  * StrategyDBOnly - 仅落库,不存证
  * StrategyDBAndTrustlog - 既落库又存证(推荐)
  * StrategyTrustlogOnly - 仅存证,不落库
- 支持多数据库:PostgreSQL, MySQL, SQLite

### 2. Cursor + Retry 双层架构
- CursorWorker:第一道防线,快速发现新记录并尝试存证
  * 增量扫描 operation 表(基于时间戳游标)
  * 默认 10 秒扫描间隔,批量处理 100 条
  * 成功更新状态,失败转入重试队列
- RetryWorker:第二道防线,处理失败记录
  * 指数退避重试(1m → 2m → 4m → 8m → 16m)
  * 默认最多重试 5 次
  * 超限自动标记为死信

### 3. 数据库表设计
- operation 表:存储操作记录,支持可空 IP 字段
- trustlog_cursor 表:Key-Value 模式,支持多游标
- trustlog_retry 表:重试队列,支持指数退避

### 4. 异步最终一致性
- 应用调用立即返回(仅落库)
- CursorWorker 异步扫描并存证
- RetryWorker 保障失败重试
- 完整的监控和死信处理机制

## 修改文件

### 核心代码(11个文件)
- api/persistence/cursor_worker.go - Cursor 工作器(新增)
- api/persistence/repository.go - 数据仓储层(新增)
- api/persistence/schema.go - 数据库 Schema(新增)
- api/persistence/strategy.go - 策略管理器(新增)
- api/persistence/client.go - 客户端封装(新增)
- api/persistence/retry_worker.go - Retry 工作器(新增)
- api/persistence/config.go - 配置管理(新增)

### 修复内部包引用(5个文件)
- api/adapter/publisher.go - 修复 internal 包引用
- api/adapter/subscriber.go - 修复 internal 包引用
- api/model/envelope.go - 修复 internal 包引用
- api/model/operation.go - 修复 internal 包引用
- api/model/record.go - 修复 internal 包引用

### 单元测试(8个文件)
- api/persistence/*_test.go - 完整的单元测试
- 测试覆盖率:28.5%
- 测试通过率:49/49 (100%)

### SQL 脚本(4个文件)
- api/persistence/sql/postgresql.sql - PostgreSQL 建表脚本
- api/persistence/sql/mysql.sql - MySQL 建表脚本
- api/persistence/sql/sqlite.sql - SQLite 建表脚本
- api/persistence/sql/test_data.sql - 测试数据

### 文档(2个文件)
- README.md - 更新主文档,新增 Persistence 使用指南
- api/persistence/README.md - 完整的 Persistence 文档
- api/persistence/sql/README.md - SQL 脚本说明

## 技术亮点

1. **充分利用 Cursor 游标表**
   - 作为任务发现队列,非简单的位置记录
   - Key-Value 模式,支持多游标并发扫描
   - 时间戳天然有序,增量扫描高效

2. **双层保障机制**
   - Cursor:正常流程,快速处理
   - Retry:异常流程,可靠重试
   - 职责分离,监控清晰

3. **可空 IP 字段支持**
   - ClientIP 和 ServerIP 使用 *string 类型
   - 支持 NULL 值,符合数据库最佳实践
   - 使用 sql.NullString 正确处理

4. **完整的监控支持**
   - 未存证记录数监控
   - Cursor 延迟监控
   - 重试队列长度监控
   - 死信队列监控

## 测试结果

-  单元测试:49/49 通过 (100%)
-  代码覆盖率:28.5%
-  编译状态:无错误
-  支持数据库:PostgreSQL, MySQL, SQLite

## Breaking Changes

无破坏性变更。Persistence 模块作为可选功能,不影响现有代码。

## 版本信息

- 版本:v2.1.0
- Go 版本要求:1.21+
- 更新日期:2025-12-23
2025-12-23 18:59:43 +08:00

85 lines
3.5 KiB
SQL
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.
-- MySQL 建表脚本
-- 用于 go-trustlog 数据库持久化模块
-- MySQL 8.0+ / MariaDB 10+ 版本
-- ============================================
-- 1. operation 表 - 操作记录表
-- ============================================
CREATE TABLE IF NOT EXISTS operation (
op_id VARCHAR(32) NOT NULL PRIMARY KEY,
op_actor VARCHAR(64),
doid VARCHAR(512),
producer_id VARCHAR(32),
request_body_hash VARCHAR(128),
response_body_hash VARCHAR(128),
sign VARCHAR(512),
op_source VARCHAR(10),
op_type VARCHAR(30),
do_prefix VARCHAR(128),
do_repository VARCHAR(64),
client_ip VARCHAR(32) COMMENT '客户端IP可空仅落库不存证',
server_ip VARCHAR(32) COMMENT '服务端IP可空仅落库不存证',
trustlog_status VARCHAR(32) COMMENT '存证状态NOT_TRUSTLOGGED / TRUSTLOGGED',
timestamp DATETIME,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_operation_timestamp (timestamp),
INDEX idx_operation_status (trustlog_status),
INDEX idx_operation_doid (doid(255))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='操作记录表';
-- ============================================
-- 2. trustlog_cursor 表 - 游标表(任务发现队列)
-- ============================================
CREATE TABLE IF NOT EXISTS trustlog_cursor (
cursor_key VARCHAR(64) NOT NULL PRIMARY KEY COMMENT '游标键operation_scan',
cursor_value VARCHAR(128) NOT NULL COMMENT '游标值最后处理的时间戳RFC3339Nano格式',
last_updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
INDEX idx_cursor_updated_at (last_updated_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='游标表记录扫描位置Cursor + Retry 双层模式)';
-- ============================================
-- 3. trustlog_retry 表 - 重试表
-- ============================================
CREATE TABLE IF NOT EXISTS trustlog_retry (
op_id VARCHAR(32) NOT NULL PRIMARY KEY,
retry_count INT DEFAULT 0 COMMENT '重试次数',
retry_status VARCHAR(32) DEFAULT 'PENDING' COMMENT '重试状态PENDING / RETRYING / DEAD_LETTER',
last_retry_at DATETIME COMMENT '上次重试时间',
next_retry_at DATETIME COMMENT '下次重试时间(用于指数退避)',
error_message TEXT COMMENT '错误信息',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_retry_status (retry_status),
INDEX idx_retry_next_retry_at (next_retry_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='重试表,用于管理失败的存证操作';
-- ============================================
-- 验证查询
-- ============================================
-- 查询所有表
SHOW TABLES LIKE 'operation%';
SHOW TABLES LIKE 'trustlog_%';
-- 查询 operation 表结构
DESCRIBE operation;
-- 查询所有索引
SHOW INDEX FROM operation;
SHOW INDEX FROM trustlog_cursor;
SHOW INDEX FROM trustlog_retry;
-- 查询表注释
SELECT
TABLE_NAME,
TABLE_COMMENT
FROM
INFORMATION_SCHEMA.TABLES
WHERE
TABLE_SCHEMA = DATABASE()
AND TABLE_NAME IN ('operation', 'trustlog_cursor', 'trustlog_retry');