aboutsummaryrefslogtreecommitdiff
path: root/building_guide
diff options
context:
space:
mode:
Diffstat (limited to 'building_guide')
-rw-r--r--building_guide/admin.md17
-rw-r--r--building_guide/concurrency.md58
2 files changed, 74 insertions, 1 deletions
diff --git a/building_guide/admin.md b/building_guide/admin.md
index 05363d5..9805ef7 100644
--- a/building_guide/admin.md
+++ b/building_guide/admin.md
@@ -266,6 +266,23 @@ the game server and is configured in `config.yaml` under `admin_http` (plain HTT
All CRUD editors support undo/redo (persisted to `data/.admin_history.json`), so changes can be reverted
even across sessions.
+#### Live editing and maintenance
+
+Editor API requests (including undo/redo) execute as one game-owner task:
+file writes and their runtime callbacks/reloads cannot interleave with a tick
+or player command. Large edits briefly pause gameplay; slow browser uploads
+and downloads do not. Requests are limited to 8 MiB and rejected during game
+shutdown. See [Concurrency & durability](concurrency.md#admin-editor-isolation)
+for the endpoint inventory and developer rules.
+
+This does not make every edit automatically hot-reloadable. Existing reload
+requirements still apply to definition editors and raw Files edits. Use the
+structured room rename/insert/remove tools for live structural changes; raw
+YAML/file renames do not migrate player or casino state. Stop the game before
+external bulk file edits, and prefer a maintenance window for major world
+reorganizations. A browser timeout does not necessarily mean an edit failed:
+check the current state before retrying.
+
#### Map Interface
The map page (`/`) is the main navigation hub:
diff --git a/building_guide/concurrency.md b/building_guide/concurrency.md
index ff8c049..984a61d 100644
--- a/building_guide/concurrency.md
+++ b/building_guide/concurrency.md
@@ -43,6 +43,61 @@ inline on the caller's goroutine (legacy behavior), which is fine for
synthetic tests but production Games always have the owner (started by
`game.New`).
+## Admin editor isolation
+
+All `/api/` routes run through one boundary in `internal/admin/owner.go`:
+
+1. Authenticate, read the request body (maximum 8 MiB) on the HTTP goroutine.
+2. Submit one synchronous `Game.RunAdminOnOwner` task. The **whole handler**
+ runs there: validation against current files, plan construction, file
+ commits, runtime migration/eviction, store reloads, and undo history.
+3. Write the buffered response on the HTTP goroutine after the task finishes.
+
+Reads use the same boundary so editor API reads cannot observe half an edit.
+Neither slow uploads nor slow downloads hold the owner. File I/O does: large
+bulk edits can briefly pause gameplay. This deliberately avoids a second
+transaction scheduler, fine-grained locks, or optimistic plan retries. Use a
+maintenance window for large world reorganizations.
+
+`RunAdminOnOwner` rejects requests during shutdown with HTTP 503, including
+requests queued before shutdown but not yet started. It never executes on the
+HTTP goroutine after the owner stops. A disconnected request is skipped if it
+has not started; once started, its edit completes even if the browser leaves.
+A failed/lost HTTP response is not proof that the edit did not commit.
+
+### Endpoint inventory and callback contract
+
+| API family (all behind the same boundary) | Mutations / live dependencies |
+| --- | --- |
+| `/rooms`, `/rooms/{id}`, `/rooms/new-empty` | Room create/update/delete, room index and runtime room state |
+| `/rooms/link`, `/rooms/insert`, `/rooms/remove`, `/rooms/move`, `/rooms/rename`, `/rooms/swap` | Multi-file room plans, course changes, room-ID migration or eviction where applicable |
+| `/rooms/bulk-edit`, `/rooms/bulk-delete`, `/rooms/resolve-duplicate` | Bulk room changes, indexes and runtime cleanup |
+| `/room-dirs/create`, `/room-dirs/rename` | Room file organization and indexes |
+| `/items`, `/mobs`, `/drops`, `/hazards` and their ID routes | Definitions plus existing cache/index invalidation; items also rebuild crafting |
+| `/objects`, `/techs`, `/modules`, `/triggers` and their ID routes | Definition files; existing manual-reload semantics remain unchanged |
+| Entity `/rename`, `/move`, `/dirs` routes | Definition file organization, undo history, existing cache invalidation |
+| `/courses`, `/courses/{id}` | Course files, exit reconciliation, course store reload |
+| `/files`, `/files/rename` | Raw file data and history; NOT a semantic room-ID migration or automatic cache reload |
+| `/colors`, `/colors/reset` | Persisted config and live color maps |
+| `/undo/undo`, `/undo/redo` | File images, room-ID migration, index/cache rebuilds, history together |
+| Remaining API routes | Read-only queries; serialized to get coherent snapshots |
+
+Register new endpoints on `apiMux`, never outside this boundary. Do not wrap
+individual callbacks in `RunOnOwner`: they are **already on the owner**.
+`cmd/thoi/main.go` wires direct course reload, craft rebuild, casino eviction,
+and `MigrateRoomIDsOnOwner` callbacks. `UndoStack`'s mutex protects history,
+not gameplay: its apply path and the following rebuild must remain in the
+same enclosing API task. Login password rehash saves and history clearing
+also run on the owner, with expensive password hashing outside it.
+
+This guarantees **isolation from gameplay**, not new crash-atomicity or
+rollback guarantees for every editor operation. Existing file transaction
+and error behavior is unchanged. Raw Files edits and external filesystem
+writes still bypass semantic validation/migrations; use structured room
+operations for live renumbering, and stop the game for external bulk edits.
+Some definition editors still need the in-game `reload` command; serialization
+does not add missing cache invalidations or migrate existing spawned entities.
+
## Durable money (casino wallet)
Every wager and payout is journaled before the balance mutation
@@ -135,7 +190,8 @@ Signals (SIGINT/SIGTERM) and the in-game `shutdown` command converge on
Live room-ID changes (admin rename, swapid) execute as one mutation plan:
the renamed room's file (id field, filename, self-loop references) plus every
other room whose references moved, applied as a single journal transaction,
-followed by the full runtime migration (`Game.MigrateRoomIDs`): player
+followed within the same owner task by the full runtime migration
+(`Game.MigrateRoomIDsOnOwner` for the editor): player
state, Hub room buckets, casino room keys, world room-keyed state (ground
items, seeded markers, object states), and live mob instances. Undo/redo
store the whole plan (all before/after images plus the idMap) and apply the