暂存一下,防止丢失
This commit is contained in:
59
internal/infrastructure/wallet/credit_consumer.go
Normal file
59
internal/infrastructure/wallet/credit_consumer.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package wallet
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
"gorm.io/gorm"
|
||||
|
||||
walletapp "github.com/break/junhong_cmp_fiber/internal/application/wallet"
|
||||
"github.com/break/junhong_cmp_fiber/internal/infrastructure/messaging/outbox"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
)
|
||||
|
||||
// CreditEventConsumer 校验已投递的代理主钱包入账事件具有对应权威资金流水。
|
||||
type CreditEventConsumer struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// NewCreditEventConsumer 创建代理主钱包入账事件消费者。
|
||||
func NewCreditEventConsumer(db *gorm.DB) *CreditEventConsumer {
|
||||
return &CreditEventConsumer{db: db}
|
||||
}
|
||||
|
||||
// Consume 校验事件载荷及不可变流水,拒绝确认未知或损坏事件。
|
||||
func (c *CreditEventConsumer) Consume(ctx context.Context, envelope outbox.DeliveryEnvelope) error {
|
||||
if c == nil || c.db == nil {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包入账事件消费者未配置")
|
||||
}
|
||||
if envelope.EventType != constants.OutboxEventTypeAgentMainWalletCredited || envelope.PayloadVersion != constants.AgentMainWalletCreditedPayloadVersionV1 {
|
||||
return errors.New(errors.CodeInvalidParam, "代理主钱包入账事件类型或版本不受支持")
|
||||
}
|
||||
var event walletapp.CreditedEvent
|
||||
if err := sonic.Unmarshal(envelope.Payload, &event); err != nil {
|
||||
return errors.Wrap(errors.CodeInvalidParam, err, "代理主钱包入账事件载荷无法解析")
|
||||
}
|
||||
validRecharge := event.ReferenceType == constants.ReferenceTypeTopup && event.TransactionType == constants.AgentTransactionTypeRecharge
|
||||
validAdjustment := event.ReferenceType == constants.ReferenceTypeManualAdjustment && event.TransactionType == constants.AgentTransactionTypeAdjustment
|
||||
if event.EventID != envelope.EventID || event.WalletID == 0 || event.ReferenceID == 0 || event.Amount <= 0 || (!validRecharge && !validAdjustment) {
|
||||
return errors.New(errors.CodeInvalidParam, "代理主钱包入账事件载荷不完整")
|
||||
}
|
||||
|
||||
var transaction model.AgentWalletTransaction
|
||||
err := c.db.WithContext(ctx).Unscoped().
|
||||
Where("agent_wallet_id = ? AND reference_type = ? AND reference_id = ? AND transaction_type = ? AND status = ?",
|
||||
event.WalletID, event.ReferenceType, event.ReferenceID, event.TransactionType, constants.TransactionStatusSuccess).
|
||||
First(&transaction).Error
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包入账事件缺少权威资金流水")
|
||||
}
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "查询代理主钱包入账流水失败")
|
||||
}
|
||||
if transaction.Amount != event.Amount || transaction.BalanceBefore != event.BalanceBefore || transaction.BalanceAfter != event.BalanceAfter {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包入账事件与权威资金流水不一致")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
37
internal/infrastructure/wallet/credit_event.go
Normal file
37
internal/infrastructure/wallet/credit_event.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package wallet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
walletapp "github.com/break/junhong_cmp_fiber/internal/application/wallet"
|
||||
"github.com/break/junhong_cmp_fiber/internal/infrastructure/messaging/outbox"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// CreditEventWriter 将代理主钱包正向入账事实写入公共 Outbox。
|
||||
type CreditEventWriter struct {
|
||||
outbox *outbox.Repository
|
||||
}
|
||||
|
||||
// NewCreditEventWriter 创建代理主钱包入账 Outbox Writer。
|
||||
func NewCreditEventWriter(repository *outbox.Repository) *CreditEventWriter {
|
||||
return &CreditEventWriter{outbox: repository}
|
||||
}
|
||||
|
||||
// Append 在调用方业务事务中追加代理主钱包入账事件。
|
||||
func (w *CreditEventWriter) Append(ctx context.Context, tx *gorm.DB, event walletapp.CreditedEvent) error {
|
||||
if w == nil || w.outbox == nil {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包入账 Outbox Writer 未配置")
|
||||
}
|
||||
_, err := w.outbox.Append(ctx, tx, outbox.Envelope{
|
||||
EventID: event.EventID, EventType: constants.OutboxEventTypeAgentMainWalletCredited,
|
||||
PayloadVersion: constants.AgentMainWalletCreditedPayloadVersionV1,
|
||||
AggregateType: "agent_wallet", AggregateID: strconv.FormatUint(uint64(event.WalletID), 10),
|
||||
ResourceType: event.ReferenceType, ResourceID: strconv.FormatUint(uint64(event.ReferenceID), 10),
|
||||
BusinessKey: event.EventID, RequestID: event.RequestID, CorrelationID: event.CorrelationID, Payload: event,
|
||||
})
|
||||
return err
|
||||
}
|
||||
62
internal/infrastructure/wallet/debit_consumer.go
Normal file
62
internal/infrastructure/wallet/debit_consumer.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package wallet
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
"gorm.io/gorm"
|
||||
|
||||
walletapp "github.com/break/junhong_cmp_fiber/internal/application/wallet"
|
||||
"github.com/break/junhong_cmp_fiber/internal/infrastructure/messaging/outbox"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
)
|
||||
|
||||
// DebitEventConsumer 校验已投递的代理主钱包扣款事件具有对应权威资金流水。
|
||||
// 后续余额预警等消费者在此稳定接缝上扩展,不需要回读或改写订单扣款事务。
|
||||
type DebitEventConsumer struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// NewDebitEventConsumer 创建代理主钱包扣款事件消费者。
|
||||
func NewDebitEventConsumer(db *gorm.DB) *DebitEventConsumer {
|
||||
return &DebitEventConsumer{db: db}
|
||||
}
|
||||
|
||||
// Consume 校验事件载荷及不可变流水,保证未知或损坏事件不会被静默确认。
|
||||
func (c *DebitEventConsumer) Consume(ctx context.Context, envelope outbox.DeliveryEnvelope) error {
|
||||
if c == nil || c.db == nil {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包扣款事件消费者未配置")
|
||||
}
|
||||
if envelope.EventType != constants.OutboxEventTypeAgentMainWalletDebited ||
|
||||
envelope.PayloadVersion != constants.AgentMainWalletDebitedPayloadVersionV1 {
|
||||
return errors.New(errors.CodeInvalidParam, "代理主钱包扣款事件类型或版本不受支持")
|
||||
}
|
||||
var event walletapp.DebitedEvent
|
||||
if err := sonic.Unmarshal(envelope.Payload, &event); err != nil {
|
||||
return errors.Wrap(errors.CodeInvalidParam, err, "代理主钱包扣款事件载荷无法解析")
|
||||
}
|
||||
if event.EventID != envelope.EventID || event.WalletID == 0 || event.ReferenceID == 0 ||
|
||||
event.ReferenceType != constants.ReferenceTypeOrder || event.TransactionType != constants.AgentTransactionTypeDeduct ||
|
||||
event.Amount <= 0 {
|
||||
return errors.New(errors.CodeInvalidParam, "代理主钱包扣款事件载荷不完整")
|
||||
}
|
||||
|
||||
var transaction model.AgentWalletTransaction
|
||||
err := c.db.WithContext(ctx).Unscoped().
|
||||
Where("agent_wallet_id = ? AND reference_type = ? AND reference_id = ? AND transaction_type = ? AND status = ?",
|
||||
event.WalletID, event.ReferenceType, event.ReferenceID, constants.AgentTransactionTypeDeduct, constants.TransactionStatusSuccess).
|
||||
First(&transaction).Error
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包扣款事件缺少权威资金流水")
|
||||
}
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "查询代理主钱包扣款流水失败")
|
||||
}
|
||||
if transaction.Amount != -event.Amount || transaction.BalanceBefore != event.BalanceBefore ||
|
||||
transaction.BalanceAfter != event.BalanceAfter {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包扣款事件与权威资金流水不一致")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
38
internal/infrastructure/wallet/debit_event.go
Normal file
38
internal/infrastructure/wallet/debit_event.go
Normal file
@@ -0,0 +1,38 @@
|
||||
// Package wallet 提供代理主钱包持久化与可靠事件 Adapter。
|
||||
package wallet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
walletapp "github.com/break/junhong_cmp_fiber/internal/application/wallet"
|
||||
"github.com/break/junhong_cmp_fiber/internal/infrastructure/messaging/outbox"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// DebitEventWriter 将代理主钱包扣款事实写入公共 Outbox。
|
||||
type DebitEventWriter struct {
|
||||
outbox *outbox.Repository
|
||||
}
|
||||
|
||||
// NewDebitEventWriter 创建代理主钱包扣款 Outbox Writer。
|
||||
func NewDebitEventWriter(repository *outbox.Repository) *DebitEventWriter {
|
||||
return &DebitEventWriter{outbox: repository}
|
||||
}
|
||||
|
||||
// Append 在调用方业务事务中追加代理主钱包扣款事件。
|
||||
func (w *DebitEventWriter) Append(ctx context.Context, tx *gorm.DB, event walletapp.DebitedEvent) error {
|
||||
if w == nil || w.outbox == nil {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包扣款 Outbox Writer 未配置")
|
||||
}
|
||||
_, err := w.outbox.Append(ctx, tx, outbox.Envelope{
|
||||
EventID: event.EventID, EventType: constants.OutboxEventTypeAgentMainWalletDebited,
|
||||
PayloadVersion: constants.AgentMainWalletDebitedPayloadVersionV1,
|
||||
AggregateType: "agent_wallet", AggregateID: strconv.FormatUint(uint64(event.WalletID), 10),
|
||||
ResourceType: event.ReferenceType, ResourceID: strconv.FormatUint(uint64(event.ReferenceID), 10),
|
||||
BusinessKey: event.EventID, RequestID: event.RequestID, CorrelationID: event.CorrelationID, Payload: event,
|
||||
})
|
||||
return err
|
||||
}
|
||||
98
internal/infrastructure/wallet/refund_consumer.go
Normal file
98
internal/infrastructure/wallet/refund_consumer.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package wallet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
"gorm.io/gorm"
|
||||
|
||||
walletapp "github.com/break/junhong_cmp_fiber/internal/application/wallet"
|
||||
"github.com/break/junhong_cmp_fiber/internal/infrastructure/messaging/outbox"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
)
|
||||
|
||||
// RefundEventConsumer 校验已投递的代理主钱包退款事件具有对应权威资金流水。
|
||||
type RefundEventConsumer struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// NewRefundEventConsumer 创建代理主钱包退款事件消费者。
|
||||
func NewRefundEventConsumer(db *gorm.DB) *RefundEventConsumer {
|
||||
return &RefundEventConsumer{db: db}
|
||||
}
|
||||
|
||||
// Consume 复核退款流水及正常订单的原扣款流水,拒绝确认未知或损坏事件。
|
||||
func (c *RefundEventConsumer) Consume(ctx context.Context, envelope outbox.DeliveryEnvelope) error {
|
||||
if c == nil || c.db == nil {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包退款事件消费者未配置")
|
||||
}
|
||||
if envelope.EventType != constants.OutboxEventTypeAgentMainWalletRefunded ||
|
||||
envelope.PayloadVersion != constants.AgentMainWalletRefundedPayloadVersionV1 {
|
||||
return errors.New(errors.CodeInvalidParam, "代理主钱包退款事件类型或版本不受支持")
|
||||
}
|
||||
var event walletapp.RefundedEvent
|
||||
if err := sonic.Unmarshal(envelope.Payload, &event); err != nil {
|
||||
return errors.Wrap(errors.CodeInvalidParam, err, "代理主钱包退款事件载荷无法解析")
|
||||
}
|
||||
if event.EventID != envelope.EventID || event.WalletID == 0 || event.ShopID == 0 ||
|
||||
event.OrderID == 0 || event.RefundID == 0 || event.Amount <= 0 || event.Version <= 0 ||
|
||||
event.OriginalDeductAmount <= 0 || event.Amount > event.OriginalDeductAmount {
|
||||
return errors.New(errors.CodeInvalidParam, "代理主钱包退款事件载荷不完整")
|
||||
}
|
||||
if event.Legacy == (event.OriginalDebitTransactionID > 0) {
|
||||
return errors.New(errors.CodeInvalidParam, "代理主钱包退款事件原扣款标识不一致")
|
||||
}
|
||||
|
||||
var refund model.AgentWalletTransaction
|
||||
err := c.db.WithContext(ctx).Unscoped().
|
||||
Where("agent_wallet_id = ? AND reference_type = ? AND reference_id = ? AND transaction_type = ? AND status = ?",
|
||||
event.WalletID, constants.ReferenceTypeRefund, event.RefundID, constants.AgentTransactionTypeRefund, constants.TransactionStatusSuccess).
|
||||
First(&refund).Error
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包退款事件缺少权威资金流水")
|
||||
}
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "查询代理主钱包退款流水失败")
|
||||
}
|
||||
if refund.ShopID != event.ShopID || refund.Amount != event.Amount ||
|
||||
refund.BalanceBefore != event.BalanceBefore || refund.BalanceAfter != event.BalanceAfter ||
|
||||
!sameRefundUint(refund.RelatedShopID, event.RelatedShopID) ||
|
||||
!sameRefundString(refund.TransactionSubtype, event.TransactionSubtype) ||
|
||||
refund.AssetType != event.AssetType || refund.AssetID != event.AssetID || refund.AssetIdentifier != event.AssetIdentifier {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包退款事件与权威退款流水不一致")
|
||||
}
|
||||
if event.Legacy {
|
||||
return nil
|
||||
}
|
||||
|
||||
var debit model.AgentWalletTransaction
|
||||
err = c.db.WithContext(ctx).Unscoped().
|
||||
Where("id = ? AND agent_wallet_id = ? AND reference_type = ? AND reference_id = ? AND transaction_type = ? AND status = ?",
|
||||
event.OriginalDebitTransactionID, event.WalletID, constants.ReferenceTypeOrder, event.OrderID,
|
||||
constants.AgentTransactionTypeDeduct, constants.TransactionStatusSuccess).
|
||||
First(&debit).Error
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包退款事件缺少原扣款流水")
|
||||
}
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "查询代理主钱包原扣款流水失败")
|
||||
}
|
||||
if debit.Amount >= 0 || debit.Amount == math.MinInt64 || event.OriginalDeductAmount != -debit.Amount ||
|
||||
!sameRefundUint(debit.RelatedShopID, event.RelatedShopID) ||
|
||||
!sameRefundString(debit.TransactionSubtype, event.TransactionSubtype) ||
|
||||
debit.AssetType != event.AssetType || debit.AssetID != event.AssetID || debit.AssetIdentifier != event.AssetIdentifier {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包退款事件与原扣款流水不一致")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func sameRefundUint(left, right *uint) bool {
|
||||
return (left == nil && right == nil) || (left != nil && right != nil && *left == *right)
|
||||
}
|
||||
|
||||
func sameRefundString(left, right *string) bool {
|
||||
return (left == nil && right == nil) || (left != nil && right != nil && *left == *right)
|
||||
}
|
||||
37
internal/infrastructure/wallet/refund_event.go
Normal file
37
internal/infrastructure/wallet/refund_event.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package wallet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
walletapp "github.com/break/junhong_cmp_fiber/internal/application/wallet"
|
||||
"github.com/break/junhong_cmp_fiber/internal/infrastructure/messaging/outbox"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// RefundEventWriter 将代理主钱包退款事实写入公共 Outbox。
|
||||
type RefundEventWriter struct {
|
||||
outbox *outbox.Repository
|
||||
}
|
||||
|
||||
// NewRefundEventWriter 创建代理主钱包退款 Outbox Writer。
|
||||
func NewRefundEventWriter(repository *outbox.Repository) *RefundEventWriter {
|
||||
return &RefundEventWriter{outbox: repository}
|
||||
}
|
||||
|
||||
// Append 在调用方业务事务中追加代理主钱包退款事件。
|
||||
func (w *RefundEventWriter) Append(ctx context.Context, tx *gorm.DB, event walletapp.RefundedEvent) error {
|
||||
if w == nil || w.outbox == nil {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包退款 Outbox Writer 未配置")
|
||||
}
|
||||
_, err := w.outbox.Append(ctx, tx, outbox.Envelope{
|
||||
EventID: event.EventID, EventType: constants.OutboxEventTypeAgentMainWalletRefunded,
|
||||
PayloadVersion: constants.AgentMainWalletRefundedPayloadVersionV1,
|
||||
AggregateType: "agent_wallet", AggregateID: strconv.FormatUint(uint64(event.WalletID), 10),
|
||||
ResourceType: constants.ReferenceTypeRefund, ResourceID: strconv.FormatUint(uint64(event.RefundID), 10),
|
||||
BusinessKey: event.EventID, RequestID: event.RequestID, CorrelationID: event.CorrelationID, Payload: event,
|
||||
})
|
||||
return err
|
||||
}
|
||||
64
internal/infrastructure/wallet/reservation_consumer.go
Normal file
64
internal/infrastructure/wallet/reservation_consumer.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package wallet
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
"gorm.io/gorm"
|
||||
|
||||
walletapp "github.com/break/junhong_cmp_fiber/internal/application/wallet"
|
||||
"github.com/break/junhong_cmp_fiber/internal/infrastructure/messaging/outbox"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
)
|
||||
|
||||
// ReservationEventConsumer 校验预占事件与本地权威事实一致。
|
||||
type ReservationEventConsumer struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// NewReservationEventConsumer 创建代理主钱包预占事件消费者。
|
||||
func NewReservationEventConsumer(db *gorm.DB) *ReservationEventConsumer {
|
||||
return &ReservationEventConsumer{db: db}
|
||||
}
|
||||
|
||||
// Consume 只确认具有匹配权威预占事实的事件。
|
||||
func (c *ReservationEventConsumer) Consume(ctx context.Context, envelope outbox.DeliveryEnvelope) error {
|
||||
if c == nil || c.db == nil {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包预占事件消费者未配置")
|
||||
}
|
||||
if envelope.EventType != constants.OutboxEventTypeAgentMainWalletReservationChanged ||
|
||||
envelope.PayloadVersion != constants.AgentMainWalletReservationPayloadVersionV1 {
|
||||
return errors.New(errors.CodeInvalidParam, "代理主钱包预占事件类型或版本不受支持")
|
||||
}
|
||||
var event walletapp.ReservationEvent
|
||||
if err := sonic.Unmarshal(envelope.Payload, &event); err != nil {
|
||||
return errors.Wrap(errors.CodeInvalidParam, err, "代理主钱包预占事件载荷无法解析")
|
||||
}
|
||||
if event.EventID != envelope.EventID || event.ReservationID == 0 || event.WalletID == 0 ||
|
||||
event.Amount <= 0 || event.ReferenceType == "" || event.ReferenceID == 0 {
|
||||
return errors.New(errors.CodeInvalidParam, "代理主钱包预占事件载荷不完整")
|
||||
}
|
||||
var reservation model.AgentWalletReservation
|
||||
if err := c.db.WithContext(ctx).Where("id = ?", event.ReservationID).First(&reservation).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包预占事件缺少权威事实")
|
||||
}
|
||||
return errors.Wrap(errors.CodeDatabaseError, err, "查询代理主钱包预占事实失败")
|
||||
}
|
||||
if reservation.AgentWalletID != event.WalletID || reservation.Amount != event.Amount ||
|
||||
reservation.ReferenceType != event.ReferenceType || reservation.ReferenceID != event.ReferenceID ||
|
||||
!reservationStatusContainsEvent(reservation.Status, event.Status) {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包预占事件与权威事实不一致")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func reservationStatusContainsEvent(current, event int) bool {
|
||||
if current == event {
|
||||
return true
|
||||
}
|
||||
return event == constants.AgentWalletReservationStatusFrozen &&
|
||||
(current == constants.AgentWalletReservationStatusReleased || current == constants.AgentWalletReservationStatusCompleted)
|
||||
}
|
||||
37
internal/infrastructure/wallet/reservation_event.go
Normal file
37
internal/infrastructure/wallet/reservation_event.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package wallet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
walletapp "github.com/break/junhong_cmp_fiber/internal/application/wallet"
|
||||
"github.com/break/junhong_cmp_fiber/internal/infrastructure/messaging/outbox"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ReservationEventWriter 将代理主钱包预占状态写入公共 Outbox。
|
||||
type ReservationEventWriter struct {
|
||||
outbox *outbox.Repository
|
||||
}
|
||||
|
||||
// NewReservationEventWriter 创建代理主钱包预占 Outbox Writer。
|
||||
func NewReservationEventWriter(repository *outbox.Repository) *ReservationEventWriter {
|
||||
return &ReservationEventWriter{outbox: repository}
|
||||
}
|
||||
|
||||
// Append 在调用方事务中追加预占状态事件。
|
||||
func (w *ReservationEventWriter) Append(ctx context.Context, tx *gorm.DB, event walletapp.ReservationEvent) error {
|
||||
if w == nil || w.outbox == nil {
|
||||
return errors.New(errors.CodeInternalError, "代理主钱包预占 Outbox Writer 未配置")
|
||||
}
|
||||
_, err := w.outbox.Append(ctx, tx, outbox.Envelope{
|
||||
EventID: event.EventID, EventType: constants.OutboxEventTypeAgentMainWalletReservationChanged,
|
||||
PayloadVersion: constants.AgentMainWalletReservationPayloadVersionV1,
|
||||
AggregateType: "agent_wallet_reservation", AggregateID: strconv.FormatUint(uint64(event.ReservationID), 10),
|
||||
ResourceType: event.ReferenceType, ResourceID: strconv.FormatUint(uint64(event.ReferenceID), 10),
|
||||
BusinessKey: event.EventID, RequestID: event.RequestID, CorrelationID: event.CorrelationID, Payload: event,
|
||||
})
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user