主要变更: - 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
201 lines
5.4 KiB
Go
201 lines
5.4 KiB
Go
package model
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
|
||
"google.golang.org/protobuf/types/known/timestamppb"
|
||
|
||
"go.yandata.net/iod/iod/go-trustlog/api/grpc/pb"
|
||
)
|
||
|
||
// FromProtobuf 将protobuf的OperationData转换为model.Operation.
|
||
func FromProtobuf(pbOp *pb.OperationData) (*Operation, error) {
|
||
if pbOp == nil {
|
||
return nil, errors.New("protobuf operation data is nil")
|
||
}
|
||
|
||
// 转换时间戳
|
||
if pbOp.GetTimestamp() == nil {
|
||
return nil, errors.New("timestamp is required")
|
||
}
|
||
timestamp := pbOp.GetTimestamp().AsTime()
|
||
|
||
// 构建Operation
|
||
operation := &Operation{
|
||
OpID: pbOp.GetOpId(),
|
||
Timestamp: timestamp,
|
||
OpSource: Source(pbOp.GetOpSource()),
|
||
OpType: pbOp.GetOpType(),
|
||
DoPrefix: pbOp.GetDoPrefix(),
|
||
DoRepository: pbOp.GetDoRepository(),
|
||
Doid: pbOp.GetDoid(),
|
||
ProducerID: pbOp.GetProducerId(),
|
||
OpActor: pbOp.GetOpActor(),
|
||
// OpAlgorithm和OpMetaHash字段已移除,固定使用Sha256Simd,哈希值由Envelope的OriginalHash提供
|
||
}
|
||
|
||
// 处理可选的哈希字段
|
||
if reqHash := pbOp.GetRequestBodyHash(); reqHash != "" {
|
||
operation.RequestBodyHash = &reqHash
|
||
}
|
||
if respHash := pbOp.GetResponseBodyHash(); respHash != "" {
|
||
operation.ResponseBodyHash = &respHash
|
||
}
|
||
|
||
return operation, nil
|
||
}
|
||
|
||
// ToProtobuf 将model.Operation转换为protobuf的OperationData.
|
||
func ToProtobuf(op *Operation) (*pb.OperationData, error) {
|
||
if op == nil {
|
||
return nil, errors.New("operation is nil")
|
||
}
|
||
|
||
// 转换时间戳
|
||
timestamp := timestamppb.New(op.Timestamp)
|
||
|
||
pbOp := &pb.OperationData{
|
||
OpId: op.OpID,
|
||
Timestamp: timestamp,
|
||
OpSource: string(op.OpSource),
|
||
OpType: op.OpType,
|
||
DoPrefix: op.DoPrefix,
|
||
DoRepository: op.DoRepository,
|
||
Doid: op.Doid,
|
||
ProducerId: op.ProducerID,
|
||
OpActor: op.OpActor,
|
||
// OpAlgorithm、OpMetaHash和OpHash字段已移除,固定使用Sha256Simd,哈希值由Envelope的OriginalHash提供
|
||
}
|
||
|
||
// 处理可选的哈希字段
|
||
if op.RequestBodyHash != nil {
|
||
pbOp.RequestBodyHash = *op.RequestBodyHash
|
||
}
|
||
if op.ResponseBodyHash != nil {
|
||
pbOp.ResponseBodyHash = *op.ResponseBodyHash
|
||
}
|
||
|
||
return pbOp, nil
|
||
}
|
||
|
||
// FromProtobufValidationResult 将protobuf的ValidationStreamRes转换为model.ValidationResult.
|
||
func FromProtobufValidationResult(pbRes *pb.ValidationStreamRes) (*ValidationResult, error) {
|
||
if pbRes == nil {
|
||
return nil, errors.New("protobuf validation result is nil")
|
||
}
|
||
|
||
result := &ValidationResult{
|
||
Code: pbRes.GetCode(),
|
||
Msg: pbRes.GetMsg(),
|
||
Progress: pbRes.GetProgress(),
|
||
Proof: ProofFromProtobuf(pbRes.GetProof()), // 取证证明
|
||
}
|
||
|
||
// 如果有操作数据,则转换
|
||
if pbRes.GetData() != nil {
|
||
op, err := FromProtobuf(pbRes.GetData())
|
||
if err != nil {
|
||
return nil, fmt.Errorf("failed to convert operation data: %w", err)
|
||
}
|
||
result.Data = op
|
||
}
|
||
|
||
return result, nil
|
||
}
|
||
|
||
// RecordFromProtobuf 将protobuf的RecordData转换为model.Record.
|
||
func RecordFromProtobuf(pbRec *pb.RecordData) (*Record, error) {
|
||
if pbRec == nil {
|
||
return nil, errors.New("protobuf record data is nil")
|
||
}
|
||
|
||
// 构建Record
|
||
record := &Record{
|
||
ID: pbRec.GetId(),
|
||
DoPrefix: pbRec.GetDoPrefix(),
|
||
ProducerID: pbRec.GetProducerId(),
|
||
Operator: pbRec.GetOperator(),
|
||
Extra: pbRec.GetExtra(),
|
||
RCType: pbRec.GetRcType(),
|
||
}
|
||
|
||
// 转换时间戳
|
||
if pbRec.GetTimestamp() != nil {
|
||
record.Timestamp = pbRec.GetTimestamp().AsTime()
|
||
}
|
||
|
||
return record, nil
|
||
}
|
||
|
||
// RecordToProtobuf 将model.Record转换为protobuf的RecordData.
|
||
func RecordToProtobuf(rec *Record) (*pb.RecordData, error) {
|
||
if rec == nil {
|
||
return nil, errors.New("record is nil")
|
||
}
|
||
|
||
// 转换时间戳
|
||
timestamp := timestamppb.New(rec.Timestamp)
|
||
|
||
pbRec := &pb.RecordData{
|
||
Id: rec.ID,
|
||
DoPrefix: rec.DoPrefix,
|
||
ProducerId: rec.ProducerID,
|
||
Timestamp: timestamp,
|
||
Operator: rec.Operator,
|
||
Extra: rec.Extra,
|
||
RcType: rec.RCType,
|
||
}
|
||
|
||
return pbRec, nil
|
||
}
|
||
|
||
// RecordValidationResult 包装记录验证的流式响应结果.
|
||
type RecordValidationResult struct {
|
||
Code int32 // 状态码(100处理中,200完成,500失败)
|
||
Msg string // 消息描述
|
||
Progress string // 当前进度(比如 "50%")
|
||
Data *Record // 最终完成时返回的记录数据,过程中可为空
|
||
Proof *Proof // 取证证明(仅在完成时返回)
|
||
}
|
||
|
||
// IsProcessing 判断是否正在处理中.
|
||
func (r *RecordValidationResult) IsProcessing() bool {
|
||
return r.Code == ValidationCodeProcessing
|
||
}
|
||
|
||
// IsCompleted 判断是否已完成.
|
||
func (r *RecordValidationResult) IsCompleted() bool {
|
||
return r.Code == ValidationCodeCompleted
|
||
}
|
||
|
||
// IsFailed 判断是否失败.
|
||
func (r *RecordValidationResult) IsFailed() bool {
|
||
return r.Code >= ValidationCodeFailed
|
||
}
|
||
|
||
// RecordFromProtobufValidationResult 将protobuf的RecordValidationStreamRes转换为model.RecordValidationResult.
|
||
func RecordFromProtobufValidationResult(pbRes *pb.RecordValidationStreamRes) (*RecordValidationResult, error) {
|
||
if pbRes == nil {
|
||
return nil, errors.New("protobuf record validation result is nil")
|
||
}
|
||
|
||
result := &RecordValidationResult{
|
||
Code: pbRes.GetCode(),
|
||
Msg: pbRes.GetMsg(),
|
||
Progress: pbRes.GetProgress(),
|
||
Proof: ProofFromProtobuf(pbRes.GetProof()), // 取证证明
|
||
}
|
||
|
||
// 如果有记录数据,则转换
|
||
if pbRes.GetResult() != nil {
|
||
rec, err := RecordFromProtobuf(pbRes.GetResult())
|
||
if err != nil {
|
||
return nil, fmt.Errorf("failed to convert record data: %w", err)
|
||
}
|
||
result.Data = rec
|
||
}
|
||
|
||
return result, nil
|
||
}
|