- 将所有trustlog-sdk文件移动到trustlog/go-trustlog/目录 - 更新README中所有import路径从trustlog-sdk改为go-trustlog - 更新cookiecutter配置文件中的项目名称 - 更新根目录.lefthook.yml以引用新位置的配置 - 添加go.sum文件到版本控制 - 删除过时的示例文件 这次重构与trustlog-server保持一致的目录结构, 为未来支持多语言SDK(Python、Java等)预留空间。
157 lines
3.9 KiB
Go
157 lines
3.9 KiB
Go
package highclient
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
|
||
"github.com/ThreeDotsLabs/watermill/message"
|
||
|
||
"go.yandata.net/iod/iod/trustlog-sdk/api/adapter"
|
||
"go.yandata.net/iod/iod/trustlog-sdk/api/logger"
|
||
"go.yandata.net/iod/iod/trustlog-sdk/api/model"
|
||
)
|
||
|
||
type Client struct {
|
||
publisher message.Publisher
|
||
logger logger.Logger
|
||
envelopeConfig model.EnvelopeConfig
|
||
}
|
||
|
||
// NewClient 创建HighClient,使用Envelope序列化方式.
|
||
// publisher可以使用任意(包含forwarder)创建的publisher,但是我们所有的订阅者必须可以处理Envelope格式的消息.
|
||
// 参数:
|
||
// - publisher: 消息发布器
|
||
// - logger: 日志记录器
|
||
// - envelopeConfig: SM2密钥配置,用于签名和序列化
|
||
func NewClient(publisher message.Publisher, logger logger.Logger, envelopeConfig model.EnvelopeConfig) *Client {
|
||
return &Client{
|
||
publisher: publisher,
|
||
logger: logger,
|
||
envelopeConfig: envelopeConfig,
|
||
}
|
||
}
|
||
|
||
func (c *Client) GetLow() message.Publisher {
|
||
return c.publisher
|
||
}
|
||
|
||
func (c *Client) OperationPublish(operation *model.Operation) error {
|
||
if operation == nil {
|
||
c.logger.Error("operation publish failed: operation is nil")
|
||
return errors.New("operation cannot be nil")
|
||
}
|
||
|
||
c.logger.Debug("publishing operation",
|
||
"opID", operation.OpID,
|
||
"opType", operation.OpType,
|
||
"doPrefix", operation.DoPrefix,
|
||
)
|
||
|
||
err := publish(operation, adapter.OperationTopic, c.publisher, c.envelopeConfig, c.logger)
|
||
if err != nil {
|
||
c.logger.Error("operation publish failed",
|
||
"opID", operation.OpID,
|
||
"error", err,
|
||
)
|
||
return err
|
||
}
|
||
|
||
c.logger.Info("operation published successfully",
|
||
"opID", operation.OpID,
|
||
"opType", operation.OpType,
|
||
)
|
||
return nil
|
||
}
|
||
|
||
func (c *Client) RecordPublish(record *model.Record) error {
|
||
if record == nil {
|
||
c.logger.Error("record publish failed: record is nil")
|
||
return errors.New("record cannot be nil")
|
||
}
|
||
|
||
c.logger.Debug("publishing record",
|
||
"recordID", record.ID,
|
||
"rcType", record.RCType,
|
||
"doPrefix", record.DoPrefix,
|
||
)
|
||
|
||
err := publish(record, adapter.RecordTopic, c.publisher, c.envelopeConfig, c.logger)
|
||
if err != nil {
|
||
c.logger.Error("record publish failed",
|
||
"recordID", record.ID,
|
||
"error", err,
|
||
)
|
||
return err
|
||
}
|
||
|
||
c.logger.Info("record published successfully",
|
||
"recordID", record.ID,
|
||
"rcType", record.RCType,
|
||
)
|
||
return nil
|
||
}
|
||
|
||
func (c *Client) Close() error {
|
||
c.logger.Info("closing high client")
|
||
err := c.publisher.Close()
|
||
if err != nil {
|
||
c.logger.Error("failed to close publisher", "error", err)
|
||
return err
|
||
}
|
||
c.logger.Info("high client closed successfully")
|
||
return nil
|
||
}
|
||
|
||
// publish 通用的发布函数,支持任何实现了 Trustlog 接口的类型。
|
||
// 使用 Envelope 格式序列化并发布到指定 topic。
|
||
func publish(
|
||
data model.Trustlog,
|
||
topic string,
|
||
publisher message.Publisher,
|
||
config model.EnvelopeConfig,
|
||
logger logger.Logger,
|
||
) error {
|
||
messageKey := data.Key()
|
||
|
||
logger.Debug("starting envelope serialization",
|
||
"messageKey", messageKey,
|
||
"topic", topic,
|
||
)
|
||
|
||
// 使用 Envelope 序列化(MarshalTrustlog 会自动提取 producerID)
|
||
envelopeData, err := model.MarshalTrustlog(data, config)
|
||
if err != nil {
|
||
logger.Error("envelope serialization failed",
|
||
"messageKey", messageKey,
|
||
"error", err,
|
||
)
|
||
return fmt.Errorf("failed to marshal envelope: %w", err)
|
||
}
|
||
|
||
logger.Debug("envelope serialized successfully",
|
||
"messageKey", messageKey,
|
||
"envelopeSize", len(envelopeData),
|
||
)
|
||
|
||
msg := message.NewMessage(messageKey, envelopeData)
|
||
logger.Debug("publishing message to topic",
|
||
"messageKey", messageKey,
|
||
"topic", topic,
|
||
)
|
||
|
||
if publishErr := publisher.Publish(topic, msg); publishErr != nil {
|
||
logger.Error("failed to publish to topic",
|
||
"messageKey", messageKey,
|
||
"topic", topic,
|
||
"error", publishErr,
|
||
)
|
||
return fmt.Errorf("failed to publish message to topic %s: %w", topic, publishErr)
|
||
}
|
||
|
||
logger.Debug("message published to topic successfully",
|
||
"messageKey", messageKey,
|
||
"topic", topic,
|
||
)
|
||
return nil
|
||
}
|