2026-04-25 13:21:39 +08:00

61 lines
1.4 KiB
Go

package memory
import (
"context"
"fmt"
"sync"
"hyapp/pkg/xerr"
"hyapp/services/wallet-service/internal/domain/ledger"
)
// Repository 是钱包单元测试用内存账本。
// 它保留幂等命中语义,但不作为生产路径。
type Repository struct {
mu sync.Mutex
balance map[int64]int64
receipts map[string]ledger.Receipt
}
// NewRepository 创建内存账本。
func NewRepository() *Repository {
return &Repository{
balance: make(map[int64]int64),
receipts: make(map[string]ledger.Receipt),
}
}
// SetBalance 为测试准备用户余额。
func (r *Repository) SetBalance(userID int64, balance int64) {
r.mu.Lock()
defer r.mu.Unlock()
r.balance[userID] = balance
}
// DebitGift 执行内存扣费并按 command_id 幂等返回原始回执。
func (r *Repository) DebitGift(_ context.Context, command ledger.DebitGiftCommand) (ledger.Receipt, error) {
r.mu.Lock()
defer r.mu.Unlock()
if receipt, ok := r.receipts[command.CommandID]; ok {
return receipt, nil
}
total := command.TotalGiftValue()
current := r.balance[command.SenderUserID]
if current < total {
return ledger.Receipt{}, xerr.New(xerr.InsufficientBalance, "insufficient balance")
}
receipt := ledger.Receipt{
BillingReceiptID: fmt.Sprintf("bill_%s", command.CommandID),
TotalGiftValue: total,
BalanceAfter: current - total,
}
r.balance[command.SenderUserID] = receipt.BalanceAfter
r.receipts[command.CommandID] = receipt
return receipt, nil
}