hyapp-server/pkg/gamemq/messages.go
2026-06-11 19:24:51 +08:00

89 lines
3.1 KiB
Go

// Package gamemq defines RocketMQ payloads owned by game-service.
package gamemq
import (
"encoding/json"
"errors"
"strings"
)
const (
MessageTypeGameOutboxEvent = "game_outbox_event"
TagGameOutboxEvent = "game_outbox_event"
EventTypeGameOrderSettled = "GameOrderSettled"
EventTypeSelfGameMatchCreated = "SelfGameMatchCreated"
EventTypeSelfGameMatchReady = "SelfGameMatchReady"
EventTypeSelfGameMatchSettled = "SelfGameMatchSettled"
EventTypeSelfGameMatchCanceled = "SelfGameMatchCanceled"
EventTypeSelfGameMatchFailed = "SelfGameMatchFailed"
EventTypeSelfGamePoolAdjusted = "SelfGamePoolAdjusted"
)
// GameOutboxMessage is the MQ representation of one committed game_outbox fact.
type GameOutboxMessage struct {
MessageType string `json:"message_type"`
AppCode string `json:"app_code"`
EventID string `json:"event_id"`
EventType string `json:"event_type"`
OrderID string `json:"order_id"`
UserID int64 `json:"user_id"`
PlatformCode string `json:"platform_code"`
GameID string `json:"game_id"`
OpType string `json:"op_type"`
CoinAmount int64 `json:"coin_amount"`
PayloadJSON string `json:"payload_json"`
OccurredAtMS int64 `json:"occurred_at_ms"`
}
// EncodeGameOutboxMessage serializes a game fact for fanout through RocketMQ.
func EncodeGameOutboxMessage(message GameOutboxMessage) ([]byte, error) {
message.MessageType = MessageTypeGameOutboxEvent
if strings.TrimSpace(message.AppCode) == "" ||
strings.TrimSpace(message.EventID) == "" ||
strings.TrimSpace(message.EventType) == "" ||
strings.TrimSpace(message.GameID) == "" ||
message.OccurredAtMS <= 0 {
return nil, errors.New("game outbox message is incomplete")
}
if message.EventType == EventTypeGameOrderSettled && (strings.TrimSpace(message.OrderID) == "" ||
message.UserID <= 0 ||
strings.TrimSpace(message.OpType) == "" ||
message.CoinAmount <= 0) {
return nil, errors.New("game order outbox message is incomplete")
}
if strings.TrimSpace(message.PayloadJSON) == "" {
message.PayloadJSON = "{}"
}
return json.Marshal(message)
}
// DecodeGameOutboxMessage validates the MQ body and restores the game fact.
func DecodeGameOutboxMessage(body []byte) (GameOutboxMessage, error) {
var message GameOutboxMessage
if err := json.Unmarshal(body, &message); err != nil {
return GameOutboxMessage{}, err
}
if message.MessageType != MessageTypeGameOutboxEvent {
return GameOutboxMessage{}, errors.New("unexpected game outbox message_type")
}
if strings.TrimSpace(message.AppCode) == "" ||
strings.TrimSpace(message.EventID) == "" ||
strings.TrimSpace(message.EventType) == "" ||
strings.TrimSpace(message.GameID) == "" ||
message.OccurredAtMS <= 0 {
return GameOutboxMessage{}, errors.New("game outbox message is incomplete")
}
if message.EventType == EventTypeGameOrderSettled && (strings.TrimSpace(message.OrderID) == "" ||
message.UserID <= 0 ||
strings.TrimSpace(message.OpType) == "" ||
message.CoinAmount <= 0) {
return GameOutboxMessage{}, errors.New("game order outbox message is incomplete")
}
if strings.TrimSpace(message.PayloadJSON) == "" {
message.PayloadJSON = "{}"
}
return message, nil
}