mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 08:32:41 +00:00
Branching zones G9c: drop legacy columns + add purge gate
Final G9 step. The schema no longer creates current_room or room_seq_json on fresh installs, and existing prod schemas drop them via purgeLegacyZoneRunColumns() once the operator flips GOGOBEE_BRANCHING_PURGE=1. - CREATE TABLE dnd_zone_run loses both columns; comment updated to point at G1's columnMigrations for the graph-mode columns. - cleanup_g9.go mirrors the L5 idempotent-purge shape: ALTER TABLE DROP COLUMN per legacy column, "no such column" treated as already done, default-off. - Wired into adventure Init alongside purgeLegacyAdvCharacterTable. - Plan doc marks G9 complete. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -310,18 +310,11 @@ func compileLegacyZoneGraph(z ZoneDefinition) ZoneGraph {
|
|||||||
- Flip `GOGOBEE_BRANCHING_ZONES=1` for that zone.
|
- Flip `GOGOBEE_BRANCHING_ZONES=1` for that zone.
|
||||||
- Remove env gate when all zones converted.
|
- Remove env gate when all zones converted.
|
||||||
|
|
||||||
### G9 — Retire linear model
|
### G9 — Retire linear model ✅
|
||||||
|
|
||||||
- Drop `room_seq_json` and `current_room` columns once all zones have registered graphs and old runs are completed.
|
- **G9a** — `GOGOBEE_BRANCHING_ZONES` POC gate removed; graph mode is the only runtime path.
|
||||||
- Idempotent purge gate (mirror `purgeLegacyAdvCharacterTable` shape from L5):
|
- **G9b** — `current_room` / `room_seq_json` no longer persisted. `CurrentRoom` derived from `len(VisitedNodes)-1` on read; `RoomSeq` is in-memory only and unused at runtime.
|
||||||
```go
|
- **G9c** — Columns dropped from `CREATE TABLE dnd_zone_run`. `purgeLegacyZoneRunColumns()` in `cleanup_g9.go` mirrors the L5 shape (gated by `GOGOBEE_BRANCHING_PURGE=1`, idempotent, runs in adventure init). Operator flips after final soak.
|
||||||
func purgeLegacyZoneRunColumns() {
|
|
||||||
if os.Getenv("GOGOBEE_BRANCHING_PURGE") != "1" { return }
|
|
||||||
// ALTER TABLE dnd_zone_run DROP COLUMN current_room
|
|
||||||
// ALTER TABLE dnd_zone_run DROP COLUMN room_seq_json
|
|
||||||
}
|
|
||||||
```
|
|
||||||
- Wire into Init, gated, idempotent. Operator flips after final soak.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1730,16 +1730,16 @@ CREATE TABLE IF NOT EXISTS adventure_characters_pre_dnd (
|
|||||||
-- A single in-progress or completed dungeon run. One row per run; players
|
-- A single in-progress or completed dungeon run. One row per run; players
|
||||||
-- may have at most one row with completed_at IS NULL AND abandoned = 0
|
-- may have at most one row with completed_at IS NULL AND abandoned = 0
|
||||||
-- (enforced in code, not via constraint, to keep migrations simple).
|
-- (enforced in code, not via constraint, to keep migrations simple).
|
||||||
-- room_seq_json is a JSON array of RoomType strings generated at run start;
|
-- rooms_cleared is a JSON array of room indices the player has resolved
|
||||||
-- current_room indexes into that array. rooms_cleared is a JSON array of
|
-- (combat won / trap survived / etc.). The zone-graph columns
|
||||||
-- room indices the player has resolved (combat won / trap survived / etc.).
|
-- (current_node, visited_nodes, node_choices) are added in Phase G1's
|
||||||
|
-- columnMigrations; the legacy linear current_room / room_seq_json
|
||||||
|
-- columns retired in G9.
|
||||||
CREATE TABLE IF NOT EXISTS dnd_zone_run (
|
CREATE TABLE IF NOT EXISTS dnd_zone_run (
|
||||||
run_id TEXT PRIMARY KEY,
|
run_id TEXT PRIMARY KEY,
|
||||||
user_id TEXT NOT NULL,
|
user_id TEXT NOT NULL,
|
||||||
zone_id TEXT NOT NULL,
|
zone_id TEXT NOT NULL,
|
||||||
current_room INTEGER NOT NULL DEFAULT 0,
|
|
||||||
total_rooms INTEGER NOT NULL,
|
total_rooms INTEGER NOT NULL,
|
||||||
room_seq_json TEXT NOT NULL DEFAULT '[]',
|
|
||||||
rooms_cleared TEXT NOT NULL DEFAULT '[]',
|
rooms_cleared TEXT NOT NULL DEFAULT '[]',
|
||||||
boss_defeated INTEGER NOT NULL DEFAULT 0,
|
boss_defeated INTEGER NOT NULL DEFAULT 0,
|
||||||
abandoned INTEGER NOT NULL DEFAULT 0,
|
abandoned INTEGER NOT NULL DEFAULT 0,
|
||||||
|
|||||||
@@ -200,6 +200,10 @@ func (p *AdventurePlugin) Init() error {
|
|||||||
// Phase L5 close-out — drop the now-cold adventure_characters table when
|
// Phase L5 close-out — drop the now-cold adventure_characters table when
|
||||||
// the operator sets GOGOBEE_LEGACY_PURGE=1. Default off; idempotent.
|
// the operator sets GOGOBEE_LEGACY_PURGE=1. Default off; idempotent.
|
||||||
purgeLegacyAdvCharacterTable()
|
purgeLegacyAdvCharacterTable()
|
||||||
|
// Phase G9 close-out — drop the now-cold current_room / room_seq_json
|
||||||
|
// columns from dnd_zone_run when the operator sets
|
||||||
|
// GOGOBEE_BRANCHING_PURGE=1. Default off; idempotent.
|
||||||
|
purgeLegacyZoneRunColumns()
|
||||||
// Phase R1 orphan-archive used to run here on every Init, but it
|
// Phase R1 orphan-archive used to run here on every Init, but it
|
||||||
// over-archived: it treats any active dnd_zone_run row not linked to
|
// over-archived: it treats any active dnd_zone_run row not linked to
|
||||||
// an active expedition as a legacy `!adventure dungeon` orphan, which
|
// an active expedition as a legacy `!adventure dungeon` orphan, which
|
||||||
|
|||||||
37
internal/plugin/cleanup_g9.go
Normal file
37
internal/plugin/cleanup_g9.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"gogobee/internal/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
// purgeLegacyZoneRunColumns drops the dnd_zone_run.current_room and
|
||||||
|
// dnd_zone_run.room_seq_json columns when the operator opts in via
|
||||||
|
// GOGOBEE_BRANCHING_PURGE=1. Phase G9 close-out: G9a removed the
|
||||||
|
// runtime gate, G9b stopped persisting the columns, and this is the
|
||||||
|
// final step.
|
||||||
|
//
|
||||||
|
// Idempotent: skips silently when the columns are already gone (or
|
||||||
|
// never existed on a fresh install — the schema in db.go no longer
|
||||||
|
// creates them).
|
||||||
|
func purgeLegacyZoneRunColumns() {
|
||||||
|
if os.Getenv("GOGOBEE_BRANCHING_PURGE") != "1" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d := db.Get()
|
||||||
|
for _, col := range []string{"current_room", "room_seq_json"} {
|
||||||
|
if _, err := d.Exec("ALTER TABLE dnd_zone_run DROP COLUMN " + col); err != nil {
|
||||||
|
msg := err.Error()
|
||||||
|
// "no such column" → already dropped (or fresh install).
|
||||||
|
if strings.Contains(msg, "no such column") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
slog.Error("G9 purge: drop column failed", "col", col, "err", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
slog.Warn("G9 purge: dnd_zone_run column dropped (GOGOBEE_BRANCHING_PURGE=1)", "col", col)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user