修复机器人房

This commit is contained in:
zhx 2026-07-07 19:09:20 +08:00
parent a328b2bfef
commit 5ad7160033
2 changed files with 37 additions and 1 deletions

View File

@ -10,6 +10,7 @@ import (
"google.golang.org/protobuf/proto"
"hyapp/pkg/appcode"
"hyapp/services/room-service/internal/room/command"
"hyapp/services/room-service/internal/room/outbox"
roomservice "hyapp/services/room-service/internal/room/service"
)
@ -76,7 +77,7 @@ func (r *Repository) SaveMutation(ctx context.Context, commit roomservice.Mutati
return err
}
if commit.Command.Replayable {
if commit.Command.Replayable && enforceUniqueReplayableRoomVersion(commit.Command.CommandType) {
var existingCommandID string
err := tx.QueryRowContext(ctx,
`SELECT command_id
@ -367,6 +368,18 @@ func (r *Repository) lockRoomMutation(ctx context.Context, tx *sql.Tx, appCode s
return nil
}
func enforceUniqueReplayableRoomVersion(commandType string) bool {
switch strings.TrimSpace(commandType) {
case command.SendGift{}.Type():
// SendGift 是账务成功后的 additive 房间表现:热度、榜单和展示事件都可以按自增 id 顺序补偿。
// 历史机器人房间已经存在同版本礼物命令时,继续拦截会让 Cell 永久卡在旧版本,反而阻止后续快照推进。
return false
default:
// presence、麦位、房间资料和生命周期命令会改变恢复结构同版本双写必须 fail-closed。
return true
}
}
func (r *Repository) deleteRoomRows(ctx context.Context, tx *sql.Tx, appCode string, roomID string) error {
// 删除覆盖所有能让房间重新出现在列表、恢复链路或 owner 唯一约束里的本服务表。
// room_outbox 也一起清理,避免已删除房间继续补偿投递旧的展示事件。

View File

@ -109,6 +109,29 @@ func TestSaveMutationRejectsDuplicateReplayableRoomVersion(t *testing.T) {
}
}
func TestSaveMutationAllowsDuplicateReplayableGiftVersion(t *testing.T) {
ctx := appcode.WithContext(context.Background(), appcode.Default)
repo := newCommandLogTestRepository(t, ctx)
roomID := "room-gift-version"
for _, commandID := range []string{"cmd-gift-first", "cmd-gift-second"} {
if err := repo.SaveMutation(ctx, roomservice.MutationCommit{Command: roomservice.CommandRecord{
AppCode: appcode.Default,
RoomID: roomID,
RoomVersion: 40,
CommandID: commandID,
CommandType: "send_gift",
Payload: []byte(`{"command_id":"` + commandID + `"}`),
Replayable: true,
OwnerNodeID: "node-a",
LeaseToken: "lease-a",
CreatedAtMS: 5000,
}}); err != nil {
t.Fatalf("same-version send_gift should remain appendable for additive recovery facts: %v", err)
}
}
}
func TestSaveMutationSerializesConcurrentReplayableRoomVersion(t *testing.T) {
ctx := appcode.WithContext(context.Background(), appcode.Default)
repo := newCommandLogTestRepository(t, ctx)