Files
go-trustlog/api/persistence/example_test.go
ryan a90d853a6e refactor: 将 OpType 字段从枚举类型改为 string 类型
主要变更:
- Operation.OpType: Type → string
- NewFullOperation 参数: opType Type → opType string
- IsValidOpType 参数: opType Type → opType string
- operationMeta.OpType: *Type → *string
- queryclient.ListRequest.OpType: model.Type → string

优点:
- 更灵活,支持动态扩展操作类型
- 不再受限于预定义的枚举常量
- 简化类型转换逻辑

兼容性:
- Type 常量定义保持不变 (OpTypeCreate, OpTypeUpdate 等)
- 使用时需要 string() 转换: string(model.OpTypeCreate)
- 所有单元测试已更新并通过 (100%)

测试结果:
 api/adapter - PASS
 api/highclient - PASS
 api/logger - PASS
 api/model - PASS
 api/persistence - PASS
 api/queryclient - PASS
 internal/* - PASS
2025-12-24 16:48:00 +08:00

379 lines
9.4 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 persistence_test
import (
"context"
"fmt"
"time"
"github.com/go-logr/logr"
"go.yandata.net/iod/iod/go-trustlog/api/adapter"
"go.yandata.net/iod/iod/go-trustlog/api/logger"
"go.yandata.net/iod/iod/go-trustlog/api/model"
"go.yandata.net/iod/iod/go-trustlog/api/persistence"
)
// Example_dbOnly 演示仅落库策略
func Example_dbOnly() {
ctx := context.Background()
// 1. 创建 Logger
myLogger := logger.NewLogger(logr.Discard())
// 2. 创建 Pulsar Publisher
pub, err := adapter.NewPublisher(
adapter.PublisherConfig{
URL: "pulsar://localhost:6650",
},
myLogger,
)
if err != nil {
panic(err)
}
defer pub.Close()
// 3. 准备 SM2 密钥配置
privateKeyHex := []byte("私钥D的十六进制字符串")
publicKeyHex := []byte("04 + x坐标 + y坐标的十六进制字符串")
envelopeConfig := model.NewSM2EnvelopeConfig(privateKeyHex, publicKeyHex)
// 4. 创建支持数据库持久化的客户端(仅落库策略)
client, err := persistence.NewPersistenceClient(ctx, persistence.PersistenceClientConfig{
Publisher: pub,
Logger: myLogger,
EnvelopeConfig: envelopeConfig,
DBConfig: persistence.DefaultDBConfig(
"postgres",
"postgres://user:pass@localhost:5432/trustlog?sslmode=disable",
),
PersistenceConfig: persistence.DefaultPersistenceConfig(persistence.StrategyDBOnly),
EnableRetryWorker: false, // 仅落库不需要重试
})
if err != nil {
panic(err)
}
defer client.Close()
// 5. 构造 Operation包含 IP 信息)
op, err := model.NewFullOperation(
model.OpSourceDOIP,
string(model.OpTypeCreate),
"10.1000",
"my-repo",
"10.1000/my-repo/doc001",
"producer-001",
"admin",
[]byte(`{"action":"create"}`),
[]byte(`{"status":"success"}`),
time.Now(),
)
if err != nil {
panic(err)
}
// 设置 IP 信息(仅落库字段,可空)
clientIP := "192.168.1.100"
serverIP := "10.0.0.50"
op.ClientIP = &clientIP
op.ServerIP = &serverIP
// 6. 发布操作(仅落库,不存证)
if err := client.OperationPublish(ctx, op); err != nil {
panic(err)
}
fmt.Printf("Operation saved to database only: %s\n", op.OpID)
}
// Example_dbAndTrustlog 演示既落库又存证策略
func Example_dbAndTrustlog() {
ctx := context.Background()
// 1. 创建 Logger
myLogger := logger.NewLogger(logr.Discard())
// 2. 创建 Pulsar Publisher
pub, err := adapter.NewPublisher(
adapter.PublisherConfig{
URL: "pulsar://localhost:6650",
},
myLogger,
)
if err != nil {
panic(err)
}
defer pub.Close()
// 3. 准备 SM2 密钥配置
privateKeyHex := []byte("私钥D的十六进制字符串")
publicKeyHex := []byte("04 + x坐标 + y坐标的十六进制字符串")
envelopeConfig := model.NewSM2EnvelopeConfig(privateKeyHex, publicKeyHex)
// 4. 创建支持数据库持久化的客户端(既落库又存证策略)
retryConfig := persistence.DefaultRetryWorkerConfig()
retryConfig.MaxRetryCount = 5
retryConfig.RetryInterval = 30 * time.Second
client, err := persistence.NewPersistenceClient(ctx, persistence.PersistenceClientConfig{
Publisher: pub,
Logger: myLogger,
EnvelopeConfig: envelopeConfig,
DBConfig: persistence.DefaultDBConfig(
"postgres",
"postgres://user:pass@localhost:5432/trustlog?sslmode=disable",
),
PersistenceConfig: persistence.PersistenceConfig{
Strategy: persistence.StrategyDBAndTrustlog,
EnableRetry: true,
MaxRetryCount: 5,
RetryBatchSize: 100,
},
RetryWorkerConfig: &retryConfig,
EnableRetryWorker: true, // 启用重试工作器保证最终一致性
})
if err != nil {
panic(err)
}
defer client.Close()
// 5. 构造 Operation
op, err := model.NewFullOperation(
model.OpSourceDOIP,
string(model.OpTypeCreate),
"10.1000",
"my-repo",
"10.1000/my-repo/doc002",
"producer-001",
"admin",
[]byte(`{"action":"create"}`),
[]byte(`{"status":"success"}`),
time.Now(),
)
if err != nil {
panic(err)
}
// 设置 IP 信息(可空)
clientIP := "192.168.1.100"
serverIP := "10.0.0.50"
op.ClientIP = &clientIP
op.ServerIP = &serverIP
// 6. 发布操作(既落库又存证,保证最终一致性)
if err := client.OperationPublish(ctx, op); err != nil {
panic(err)
}
fmt.Printf("Operation saved to database and published to trustlog: %s\n", op.OpID)
fmt.Println("If publish fails, retry worker will handle it automatically")
}
// Example_trustlogOnly 演示仅存证策略
func Example_trustlogOnly() {
ctx := context.Background()
// 1. 创建 Logger
myLogger := logger.NewLogger(logr.Discard())
// 2. 创建 Pulsar Publisher
pub, err := adapter.NewPublisher(
adapter.PublisherConfig{
URL: "pulsar://localhost:6650",
},
myLogger,
)
if err != nil {
panic(err)
}
defer pub.Close()
// 3. 准备 SM2 密钥配置
privateKeyHex := []byte("私钥D的十六进制字符串")
publicKeyHex := []byte("04 + x坐标 + y坐标的十六进制字符串")
envelopeConfig := model.NewSM2EnvelopeConfig(privateKeyHex, publicKeyHex)
// 4. 创建支持数据库持久化的客户端(仅存证策略)
client, err := persistence.NewPersistenceClient(ctx, persistence.PersistenceClientConfig{
Publisher: pub,
Logger: myLogger,
EnvelopeConfig: envelopeConfig,
DBConfig: persistence.DefaultDBConfig(
"postgres",
"postgres://user:pass@localhost:5432/trustlog?sslmode=disable",
),
PersistenceConfig: persistence.DefaultPersistenceConfig(persistence.StrategyTrustlogOnly),
EnableRetryWorker: false, // 仅存证不需要重试工作器
})
if err != nil {
panic(err)
}
defer client.Close()
// 5. 构造 Operation
op, err := model.NewFullOperation(
model.OpSourceDOIP,
string(model.OpTypeCreate),
"10.1000",
"my-repo",
"10.1000/my-repo/doc003",
"producer-001",
"admin",
[]byte(`{"action":"create"}`),
[]byte(`{"status":"success"}`),
time.Now(),
)
if err != nil {
panic(err)
}
// 6. 发布操作(仅存证,不落库)
if err := client.OperationPublish(ctx, op); err != nil {
panic(err)
}
fmt.Printf("Operation published to trustlog only: %s\n", op.OpID)
}
// Example_mysqlDatabase 演示使用 MySQL 数据库
func Example_mysqlDatabase() {
ctx := context.Background()
// 1. 创建 Logger
myLogger := logger.NewLogger(logr.Discard())
// 2. 创建 Pulsar Publisher
pub, err := adapter.NewPublisher(
adapter.PublisherConfig{
URL: "pulsar://localhost:6650",
},
myLogger,
)
if err != nil {
panic(err)
}
defer pub.Close()
// 3. 准备 SM2 密钥配置
privateKeyHex := []byte("私钥D的十六进制字符串")
publicKeyHex := []byte("04 + x坐标 + y坐标的十六进制字符串")
envelopeConfig := model.NewSM2EnvelopeConfig(privateKeyHex, publicKeyHex)
// 4. 创建支持 MySQL 数据库的客户端
client, err := persistence.NewPersistenceClient(ctx, persistence.PersistenceClientConfig{
Publisher: pub,
Logger: myLogger,
EnvelopeConfig: envelopeConfig,
DBConfig: persistence.DefaultDBConfig(
"mysql",
"user:pass@tcp(localhost:3306)/trustlog?parseTime=true",
),
PersistenceConfig: persistence.DefaultPersistenceConfig(persistence.StrategyDBAndTrustlog),
EnableRetryWorker: true,
})
if err != nil {
panic(err)
}
defer client.Close()
// 5. 构造并发布 Operation
op, err := model.NewFullOperation(
model.OpSourceDOIP,
string(model.OpTypeCreate),
"10.1000",
"my-repo",
"10.1000/my-repo/doc004",
"producer-001",
"admin",
[]byte(`{"action":"create"}`),
[]byte(`{"status":"success"}`),
time.Now(),
)
if err != nil {
panic(err)
}
// 设置 IP 信息(可空)
clientIP := "192.168.1.100"
serverIP := "10.0.0.50"
op.ClientIP = &clientIP
op.ServerIP = &serverIP
if err := client.OperationPublish(ctx, op); err != nil {
panic(err)
}
fmt.Printf("Operation saved to MySQL and published: %s\n", op.OpID)
}
// Example_sqliteDatabase 演示使用 SQLite 数据库
func Example_sqliteDatabase() {
ctx := context.Background()
// 1. 创建 Logger
myLogger := logger.NewLogger(logr.Discard())
// 2. 创建 Pulsar Publisher
pub, err := adapter.NewPublisher(
adapter.PublisherConfig{
URL: "pulsar://localhost:6650",
},
myLogger,
)
if err != nil {
panic(err)
}
defer pub.Close()
// 3. 准备 SM2 密钥配置
privateKeyHex := []byte("私钥D的十六进制字符串")
publicKeyHex := []byte("04 + x坐标 + y坐标的十六进制字符串")
envelopeConfig := model.NewSM2EnvelopeConfig(privateKeyHex, publicKeyHex)
// 4. 创建支持 SQLite 数据库的客户端
client, err := persistence.NewPersistenceClient(ctx, persistence.PersistenceClientConfig{
Publisher: pub,
Logger: myLogger,
EnvelopeConfig: envelopeConfig,
DBConfig: persistence.DefaultDBConfig(
"sqlite3",
"./trustlog.db",
),
PersistenceConfig: persistence.DefaultPersistenceConfig(persistence.StrategyDBOnly),
EnableRetryWorker: false,
})
if err != nil {
panic(err)
}
defer client.Close()
// 5. 构造并发布 Operation
op, err := model.NewFullOperation(
model.OpSourceDOIP,
string(model.OpTypeCreate),
"10.1000",
"my-repo",
"10.1000/my-repo/doc005",
"producer-001",
"admin",
[]byte(`{"action":"create"}`),
[]byte(`{"status":"success"}`),
time.Now(),
)
if err != nil {
panic(err)
}
// 设置 IP 信息(可空)
clientIP := "192.168.1.100"
serverIP := "10.0.0.50"
op.ClientIP = &clientIP
op.ServerIP = &serverIP
if err := client.OperationPublish(ctx, op); err != nil {
panic(err)
}
fmt.Printf("Operation saved to SQLite: %s\n", op.OpID)
}