84 lines
2.8 KiB
Go
84 lines
2.8 KiB
Go
package service
|
||
|
||
import (
|
||
"time"
|
||
|
||
"google.golang.org/protobuf/proto"
|
||
roomv1 "hyapp.local/api/proto/room/v1"
|
||
"hyapp/pkg/xerr"
|
||
"hyapp/services/room-service/internal/room/command"
|
||
)
|
||
|
||
func marshalMutationResult(result mutationResult) ([]byte, error) {
|
||
if result.giftV2 == nil {
|
||
return nil, nil
|
||
}
|
||
payload, err := proto.Marshal(result.giftV2)
|
||
if err != nil {
|
||
return nil, xerr.New(xerr.Internal, "send gift v2 result cannot be encoded")
|
||
}
|
||
return payload, nil
|
||
}
|
||
|
||
func replayMutationResult(record CommandRecord, snapshot *roomv1.RoomSnapshot) (mutationResult, error) {
|
||
result := mutationResult{snapshot: snapshot}
|
||
if record.CommandType != (command.SendGift{}).Type() || len(record.ResultPayload) == 0 {
|
||
// 历史命令没有 typed result;继续返回当前 snapshot,保持 V1 已上线行为,不伪造账务字段。
|
||
return result, nil
|
||
}
|
||
var stored roomv1.SendGiftResultV2
|
||
if err := proto.Unmarshal(record.ResultPayload, &stored); err != nil {
|
||
// 已提交结果损坏时必须 fail-close,不能重跑 wallet 或幸运礼物来“修复”一个已提交命令。
|
||
return mutationResult{}, xerr.New(xerr.Internal, "stored send gift result cannot be decoded")
|
||
}
|
||
replayed := proto.Clone(&stored).(*roomv1.SendGiftResultV2)
|
||
replayed.IdempotentReplay = true
|
||
replayed.OperationStatus = GiftOperationStatusCommitted
|
||
result.billingReceiptID = replayed.GetBillingReceiptId()
|
||
result.coinBalanceAfter = replayed.GetCoinBalanceAfter()
|
||
result.giftIncomeBalanceAfter = replayed.GetGiftIncomeBalanceAfter()
|
||
result.roomHeat = replayed.GetRoomHeat()
|
||
result.giftRank = cloneGiftRankItems(replayed.GetGiftRank())
|
||
result.luckyGift = replayed.GetLuckyGift()
|
||
result.luckyGifts = append([]*roomv1.LuckyGiftDrawResult(nil), replayed.GetLuckyGifts()...)
|
||
result.batchDisplay = replayed.GetBatchDisplay()
|
||
result.giftV2 = replayed
|
||
return result, nil
|
||
}
|
||
|
||
func cloneGiftRankItems(items []*roomv1.RankItem) []*roomv1.RankItem {
|
||
out := make([]*roomv1.RankItem, 0, len(items))
|
||
for _, item := range items {
|
||
if item != nil {
|
||
out = append(out, proto.Clone(item).(*roomv1.RankItem))
|
||
}
|
||
}
|
||
return out
|
||
}
|
||
|
||
func luckyHitsFromResults(results []*roomv1.LuckyGiftDrawResult) []*roomv1.SendGiftLuckyHit {
|
||
hits := make([]*roomv1.SendGiftLuckyHit, 0)
|
||
for _, result := range results {
|
||
if result == nil {
|
||
continue
|
||
}
|
||
for _, hit := range result.GetHits() {
|
||
if hit != nil && hit.GetRewardCoins() > 0 {
|
||
hits = append(hits, proto.Clone(hit).(*roomv1.SendGiftLuckyHit))
|
||
}
|
||
}
|
||
}
|
||
return hits
|
||
}
|
||
|
||
func giftOperationCommitForResult(cmd command.Command, resultPayload []byte, now time.Time) *GiftOperationCommit {
|
||
if cmd == nil || cmd.Type() != (command.SendGift{}).Type() || len(resultPayload) == 0 {
|
||
return nil
|
||
}
|
||
return &GiftOperationCommit{
|
||
CommandID: cmd.ID(),
|
||
ResultPayload: resultPayload,
|
||
UpdatedAtMS: now.UnixMilli(),
|
||
}
|
||
}
|