2026-07-09 13:02:49 +08:00

101 lines
3.2 KiB
Go

package mysql
import (
"context"
"database/sql"
"google.golang.org/protobuf/proto"
roomv1 "hyapp.local/api/proto/room/v1"
"hyapp/pkg/appcode"
roomservice "hyapp/services/room-service/internal/room/service"
)
const ownerCountryRoomExtKey = "owner_country_code"
type ownerCountrySnapshotUpdate struct {
roomID string
roomVersion int64
payload []byte
}
// RenameOwnerCountryCode 同事务刷新房间当前列表投影和最新快照中的房主国家码。
// command_log 保留房间发生时事实,因此这里明确只碰当前读模型,供后台国家码重命名任务收敛线上展示态。
func (r *Repository) RenameOwnerCountryCode(ctx context.Context, oldCountryCode string, newCountryCode string, nowMS int64) (roomservice.OwnerCountryCodeRenameResult, error) {
app := appcode.FromContext(ctx)
var result roomservice.OwnerCountryCodeRenameResult
tx, err := r.db.BeginTx(ctx, &sql.TxOptions{})
if err != nil {
return roomservice.OwnerCountryCodeRenameResult{}, err
}
defer tx.Rollback()
rows, err := tx.QueryContext(ctx, `
SELECT room_id, room_version, payload
FROM room_snapshots
WHERE app_code = ?
FOR UPDATE
`, app)
if err != nil {
return roomservice.OwnerCountryCodeRenameResult{}, err
}
updates := []ownerCountrySnapshotUpdate{}
for rows.Next() {
var update ownerCountrySnapshotUpdate
if err := rows.Scan(&update.roomID, &update.roomVersion, &update.payload); err != nil {
_ = rows.Close()
return roomservice.OwnerCountryCodeRenameResult{}, err
}
var snapshot roomv1.RoomSnapshot
if err := proto.Unmarshal(update.payload, &snapshot); err != nil {
_ = rows.Close()
return roomservice.OwnerCountryCodeRenameResult{}, err
}
if snapshot.RoomExt == nil || snapshot.RoomExt[ownerCountryRoomExtKey] != oldCountryCode {
continue
}
snapshot.RoomExt[ownerCountryRoomExtKey] = newCountryCode
body, err := proto.Marshal(&snapshot)
if err != nil {
_ = rows.Close()
return roomservice.OwnerCountryCodeRenameResult{}, err
}
update.payload = body
updates = append(updates, update)
}
if err := rows.Close(); err != nil {
return roomservice.OwnerCountryCodeRenameResult{}, err
}
if err := rows.Err(); err != nil {
return roomservice.OwnerCountryCodeRenameResult{}, err
}
listResult, err := tx.ExecContext(ctx, `
UPDATE room_list_entries
SET owner_country_code = ?, updated_at_ms = ?
WHERE app_code = ? AND owner_country_code = ?
`, newCountryCode, nowMS, app, oldCountryCode)
if err != nil {
return roomservice.OwnerCountryCodeRenameResult{}, err
}
result.RoomListEntries, _ = listResult.RowsAffected()
for _, update := range updates {
// room_version 不递增,避免把低频后台投影修复伪装成 Room Cell 状态版本推进。
affected, err := tx.ExecContext(ctx, `
UPDATE room_snapshots
SET payload = ?, updated_at_ms = ?
WHERE app_code = ? AND room_id = ? AND room_version = ?
`, update.payload, nowMS, app, update.roomID, update.roomVersion)
if err != nil {
return roomservice.OwnerCountryCodeRenameResult{}, err
}
rowsAffected, _ := affected.RowsAffected()
result.RoomSnapshots += rowsAffected
}
if err := tx.Commit(); err != nil {
return roomservice.OwnerCountryCodeRenameResult{}, err
}
return result, nil
}