2026-06-08 19:00:23 +08:00

101 lines
3.6 KiB
Go

package service_test
import (
"context"
"encoding/json"
"testing"
"time"
roomv1 "hyapp.local/api/proto/room/v1"
"hyapp/pkg/appcode"
"hyapp/pkg/usermq"
"hyapp/services/room-service/internal/integration"
roomservice "hyapp/services/room-service/internal/room/service"
"hyapp/services/room-service/internal/router"
"hyapp/services/room-service/internal/testutil/mysqltest"
)
func TestHandleUserRegionChangedUpdatesOwnerRoomRegionIdempotently(t *testing.T) {
ctx := appcode.WithContext(context.Background(), appcode.Default)
repository := mysqltest.NewRepository(t)
svc := roomservice.New(roomservice.Config{
NodeID: "node-user-region-sync-test",
LeaseTTL: 10 * time.Second,
RankLimit: 20,
SnapshotEveryN: 1,
}, router.NewMemoryDirectory(), repository, followTestWallet{}, integration.NewNoopRoomEventPublisher(), integration.NewNoopOutboxPublisher())
roomID := "room-user-region-sync"
ownerID := int64(163212)
if _, err := svc.CreateRoom(ctx, &roomv1.CreateRoomRequest{
Meta: roomservice.NewRequestMeta(roomID, ownerID),
SeatCount: 10,
Mode: "voice",
VisibleRegionId: 3,
OwnerCountryCode: "AE",
RoomName: "Region Sync Room",
RoomAvatar: testRoomCoverURL,
RoomShortId: "163212",
}); err != nil {
t.Fatalf("create room failed: %v", err)
}
payload, err := json.Marshal(map[string]any{
"user_id": ownerID,
"old_country": "AE",
"new_country": "BD",
"old_region_id": 3,
"new_region_id": 2,
"source": "admin",
"request_id": "req-user-region-sync",
"changed_at_ms": int64(1_700_000_789_000),
})
if err != nil {
t.Fatalf("marshal payload failed: %v", err)
}
message := usermq.UserOutboxMessage{
AppCode: appcode.Default,
EventID: "UserRegionChanged:admin:163212:3:2:1700000789000",
EventType: "UserRegionChanged",
AggregateType: "user",
AggregateID: ownerID,
PayloadJSON: string(payload),
OccurredAtMS: 1_700_000_789_000,
}
if err := svc.HandleUserOutboxMessage(ctx, message); err != nil {
t.Fatalf("HandleUserOutboxMessage failed: %v", err)
}
if err := svc.HandleUserOutboxMessage(ctx, message); err != nil {
t.Fatalf("replayed HandleUserOutboxMessage failed: %v", err)
}
meta, exists, err := repository.GetRoomMeta(ctx, roomID)
if err != nil || !exists {
t.Fatalf("room meta missing after sync: exists=%t err=%v", exists, err)
}
if meta.VisibleRegionID != 2 {
t.Fatalf("rooms visible region mismatch: %+v", meta)
}
newRegionEntries, err := repository.ListRoomListEntries(ctx, roomservice.RoomListQuery{VisibleRegionID: 2, Tab: "new", Limit: 10})
if err != nil {
t.Fatalf("list new region entries failed: %v", err)
}
if len(newRegionEntries) != 1 || newRegionEntries[0].RoomID != roomID || newRegionEntries[0].VisibleRegionID != 2 || newRegionEntries[0].OwnerCountryCode != "BD" {
t.Fatalf("new region list projection mismatch: %+v", newRegionEntries)
}
countryEntries, err := repository.ListRoomListEntries(ctx, roomservice.RoomListQuery{VisibleRegionID: 2, CountryCode: "BD", Tab: "new", Limit: 10})
if err != nil {
t.Fatalf("list new country entries failed: %v", err)
}
if len(countryEntries) != 1 || countryEntries[0].RoomID != roomID || countryEntries[0].OwnerCountryCode != "BD" {
t.Fatalf("new country list projection mismatch: %+v", countryEntries)
}
oldRegionEntries, err := repository.ListRoomListEntries(ctx, roomservice.RoomListQuery{VisibleRegionID: 3, Tab: "new", Limit: 10})
if err != nil {
t.Fatalf("list old region entries failed: %v", err)
}
if len(oldRegionEntries) != 0 {
t.Fatalf("old region list must not contain migrated room: %+v", oldRegionEntries)
}
}