From 69235cac5b3da5ff0dc20310e7474cabd8e63ba3 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Tue, 15 Sep 2026 20:14:02 -0400 Subject: feat: route all html editor API mutations through single owner task --- internal/game/exit_migrate.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'internal/game/exit_migrate.go') diff --git a/internal/game/exit_migrate.go b/internal/game/exit_migrate.go index db70c8d..c678591 100644 --- a/internal/game/exit_migrate.go +++ b/internal/game/exit_migrate.go @@ -152,7 +152,7 @@ func (g *Game) RewriteRoomIDs(idMap map[int]int) { } // MigrateRoomIDs is the complete room-ID migration entry point for other -// goroutines (the admin API and swapid command): player state, Hub room +// goroutines: player state, Hub room // buckets, casino room keys, world room-keyed runtime state, and live mob // instances all move together under one owner task. This is what makes a // live rename leave NO gameplay or broadcast attached to the old location. @@ -161,13 +161,17 @@ func (g *Game) MigrateRoomIDs(idMap map[int]int) { return } g.RunOnOwner(func() { - g.migrateRoomIDsLocked(idMap) + g.MigrateRoomIDsOnOwner(idMap) }) } -// migrateRoomIDsLocked performs the full runtime migration; caller must -// already be on the owner goroutine. -func (g *Game) migrateRoomIDsLocked(idMap map[int]int) { +// MigrateRoomIDsOnOwner performs the full runtime migration within an existing +// owner task (e.g. the admin editor's file commit + migration + reload task). +// It must not dispatch again: a nested RunOnOwner would deadlock. +func (g *Game) MigrateRoomIDsOnOwner(idMap map[int]int) { + if len(idMap) == 0 { + return + } if g.Hub != nil { g.Hub.RekeyRooms(idMap) } -- cgit v1.2.3