Files
go-trustlog/api/persistence/sql/postgresql.sql
ryan 4b72a37120 feat: 完善数据库持久化与存证功能
主要更新:

1. 数据库持久化功能
   - 支持三种策略:仅落库、既落库又存证、仅存证
   - 实现 Cursor Worker 异步扫描和存证机制
   - 实现 Retry Worker 失败重试机制
   - 支持 PostgreSQL、MySQL、SQLite 等多种数据库
   - 添加 ClientIP 和 ServerIP 字段(可空,仅落库)

2. 集群并发安全
   - 使用 SELECT FOR UPDATE SKIP LOCKED 防止重复处理
   - 实现 CAS (Compare-And-Set) 原子状态更新
   - 添加 updated_at 字段支持并发控制

3. Cursor 初始化优化
   - 自动基于历史数据初始化 cursor
   - 确保不遗漏任何历史记录
   - 修复 UPSERT 逻辑

4. 测试完善
   - 添加 E2E 集成测试(含 Pulsar 消费者验证)
   - 添加 PostgreSQL 集成测试
   - 添加 Pulsar 集成测试
   - 添加集群并发安全测试
   - 添加 Cursor 初始化验证测试
   - 补充大量单元测试,提升覆盖率

5. 工具脚本
   - 添加数据库迁移脚本
   - 添加 Cursor 状态检查工具
   - 添加 Cursor 初始化工具
   - 添加 Pulsar 消息验证工具

6. 文档清理
   - 删除冗余文档,只保留根目录 README

测试结果:
- 所有 E2E 测试通过(100%)
- 数据库持久化与异步存证流程验证通过
- 集群环境下的并发安全性验证通过
- Cursor 自动初始化和历史数据处理验证通过
2025-12-24 15:31:11 +08:00

102 lines
4.4 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.
-- PostgreSQL 建表脚本
-- 用于 go-trustlog 数据库持久化模块
-- PostgreSQL 12+ 版本
-- ============================================
-- 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),
op_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), -- 客户端IP可空仅落库
server_ip VARCHAR(32), -- 服务端IP可空仅落库
trustlog_status VARCHAR(32), -- 存证状态NOT_TRUSTLOGGED / TRUSTLOGGED
timestamp TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 更新时间用于CAS
);
-- 创建索引
CREATE INDEX IF NOT EXISTS idx_operation_timestamp ON operation(timestamp);
CREATE INDEX IF NOT EXISTS idx_operation_status ON operation(trustlog_status);
CREATE INDEX IF NOT EXISTS idx_operation_doid ON operation(doid);
-- 添加注释
COMMENT ON TABLE operation IS '操作记录表';
COMMENT ON COLUMN operation.op_id IS '操作ID主键';
COMMENT ON COLUMN operation.client_ip IS '客户端IP可空仅落库不存证';
COMMENT ON COLUMN operation.server_ip IS '服务端IP可空仅落库不存证';
COMMENT ON COLUMN operation.trustlog_status IS '存证状态NOT_TRUSTLOGGED未存证/ TRUSTLOGGED已存证';
-- ============================================
-- 2. trustlog_cursor 表 - 游标表(任务发现队列)
-- ============================================
CREATE TABLE IF NOT EXISTS trustlog_cursor (
cursor_key VARCHAR(64) NOT NULL PRIMARY KEY,
cursor_value VARCHAR(128) NOT NULL, -- 存储时间戳RFC3339Nano格式
last_updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 创建索引
CREATE INDEX IF NOT EXISTS idx_cursor_updated_at ON trustlog_cursor(last_updated_at);
-- 添加注释
COMMENT ON TABLE trustlog_cursor IS '游标表记录扫描位置Cursor + Retry 双层模式)';
COMMENT ON COLUMN trustlog_cursor.cursor_key IS '游标键operation_scan';
COMMENT ON COLUMN trustlog_cursor.cursor_value IS '游标值最后处理的时间戳RFC3339Nano格式';
COMMENT ON COLUMN trustlog_cursor.last_updated_at IS '最后更新时间';
-- ============================================
-- 3. trustlog_retry 表 - 重试表
-- ============================================
CREATE TABLE IF NOT EXISTS trustlog_retry (
op_id VARCHAR(32) NOT NULL PRIMARY KEY,
retry_count INTEGER DEFAULT 0,
retry_status VARCHAR(32) DEFAULT 'PENDING',
last_retry_at TIMESTAMP,
next_retry_at TIMESTAMP,
error_message TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 创建索引
CREATE INDEX IF NOT EXISTS idx_retry_status ON trustlog_retry(retry_status);
CREATE INDEX IF NOT EXISTS idx_retry_next_retry_at ON trustlog_retry(next_retry_at);
-- 添加注释
COMMENT ON TABLE trustlog_retry IS '重试表,用于管理失败的存证操作';
COMMENT ON COLUMN trustlog_retry.retry_status IS '重试状态PENDING待重试/ RETRYING重试中/ DEAD_LETTER死信';
COMMENT ON COLUMN trustlog_retry.retry_count IS '重试次数';
COMMENT ON COLUMN trustlog_retry.next_retry_at IS '下次重试时间(用于指数退避)';
-- ============================================
-- 验证查询
-- ============================================
-- 查询所有表
SELECT tablename FROM pg_tables WHERE schemaname = 'public'
AND tablename IN ('operation', 'trustlog_cursor', 'trustlog_retry');
-- 查询 operation 表结构
SELECT column_name, data_type, is_nullable
FROM information_schema.columns
WHERE table_name = 'operation'
ORDER BY ordinal_position;
-- 查询所有索引
SELECT indexname, tablename FROM pg_indexes
WHERE tablename IN ('operation', 'trustlog_cursor', 'trustlog_retry')
ORDER BY tablename, indexname;