88 lines
2.8 KiB
Go
88 lines
2.8 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"strings"
|
|
|
|
roomv1 "hyapp.local/api/proto/room/v1"
|
|
"hyapp/pkg/appcode"
|
|
"hyapp/pkg/usermq"
|
|
"hyapp/services/room-service/internal/room/command"
|
|
"hyapp/services/room-service/internal/room/state"
|
|
)
|
|
|
|
type userRegionChangedPayload struct {
|
|
UserID int64 `json:"user_id"`
|
|
OldCountry string `json:"old_country"`
|
|
NewCountry string `json:"new_country"`
|
|
OldRegionID int64 `json:"old_region_id"`
|
|
NewRegionID int64 `json:"new_region_id"`
|
|
Source string `json:"source"`
|
|
RequestID string `json:"request_id"`
|
|
ChangedAtMS int64 `json:"changed_at_ms"`
|
|
}
|
|
|
|
// HandleUserOutboxMessage 只消费 user-service 的当前区域迁移事实;历史注册、邀请或麦位事实不是 room-service 的状态输入。
|
|
func (s *Service) HandleUserOutboxMessage(ctx context.Context, message usermq.UserOutboxMessage) error {
|
|
if strings.TrimSpace(message.EventType) != "UserRegionChanged" {
|
|
return nil
|
|
}
|
|
var payload userRegionChangedPayload
|
|
if err := json.Unmarshal([]byte(message.PayloadJSON), &payload); err != nil {
|
|
return err
|
|
}
|
|
if payload.UserID <= 0 || payload.NewRegionID < 0 {
|
|
// user_outbox 已经是 owner service 提交后的事实;结构错误交给 MQ 重试和告警,不在本地猜测修复。
|
|
return errors.New("user region changed payload is invalid")
|
|
}
|
|
if payload.UserID != message.AggregateID {
|
|
// aggregate_id 是 outbox 幂等和审计键,必须和 payload 指向同一个用户,避免错误事件迁移别人的房间。
|
|
return errors.New("user region changed aggregate_id mismatch")
|
|
}
|
|
|
|
ctx = appcode.WithContext(ctx, message.AppCode)
|
|
meta, exists, err := s.repository.GetRoomMetaByOwner(ctx, payload.UserID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !exists || meta.Status == state.RoomStatusDeleted {
|
|
return nil
|
|
}
|
|
|
|
newCountry := normalizeRoomCountryCode(payload.NewCountry)
|
|
if meta.VisibleRegionID == payload.NewRegionID && newCountry == "" {
|
|
return nil
|
|
}
|
|
requestID := strings.TrimSpace(payload.RequestID)
|
|
if requestID == "" {
|
|
requestID = message.EventID
|
|
}
|
|
sentAtMS := payload.ChangedAtMS
|
|
if sentAtMS <= 0 {
|
|
sentAtMS = message.OccurredAtMS
|
|
}
|
|
updateMeta := &roomv1.RequestMeta{
|
|
AppCode: message.AppCode,
|
|
RequestId: requestID,
|
|
CommandId: message.EventID,
|
|
ActorUserId: payload.UserID,
|
|
RoomId: meta.RoomID,
|
|
SentAtMs: sentAtMS,
|
|
}
|
|
cmd := command.AdminUpdateRoom{
|
|
Base: baseFromMeta(updateMeta),
|
|
AdminName: "user-region-sync",
|
|
}
|
|
if meta.VisibleRegionID != payload.NewRegionID {
|
|
cmd.VisibleRegionID = &payload.NewRegionID
|
|
}
|
|
if newCountry != "" {
|
|
// UserRegionChanged 同时承载国家事实;即使区域未变,也要把房主国家投影写回房间列表。
|
|
cmd.OwnerCountryCode = &newCountry
|
|
}
|
|
_, err = s.applyAdminRoomMutation(ctx, cmd, cmd)
|
|
return err
|
|
}
|