package ports import ( "context" "galaxy/gamemaster/internal/domain/playermapping" ) //go:generate go run go.uber.org/mock/mockgen -destination=../adapters/mocks/mock_playermappingstore.go -package=mocks galaxy/gamemaster/internal/ports PlayerMappingStore // PlayerMappingStore stores the (game_id, user_id) → race_name + // engine_player_uuid projection installed at register-runtime. Adapters // must preserve the storage-level invariants enforced by // `00001_init.sql`: // // - composite primary key on `(game_id, user_id)`; // - UNIQUE on `(game_id, race_name)` (one race per game). // // BulkInsert is the only ingestion path: register-runtime inserts every // row for a game in one batch. Per-row mutation is intentionally not // exposed; rosters are immutable for the lifetime of the runtime. type PlayerMappingStore interface { // BulkInsert installs every mapping in records. Adapters validate // each record through playermapping.PlayerMapping.Validate before // touching the store. Adapters may use a single multi-row INSERT // or one transaction with N rows; either way the operation is // atomic. BulkInsert(ctx context.Context, records []playermapping.PlayerMapping) error // Get returns the mapping identified by (gameID, userID). Returns // playermapping.ErrNotFound when no row exists. Get(ctx context.Context, gameID, userID string) (playermapping.PlayerMapping, error) // GetByRace returns the mapping identified by (gameID, raceName). // Used by the admin banish flow (Stage 17) to resolve the engine // player UUID for the engine /admin/race/banish call. Returns // playermapping.ErrNotFound when no row exists. GetByRace(ctx context.Context, gameID, raceName string) (playermapping.PlayerMapping, error) // ListByGame returns every mapping owned by gameID. The order is // adapter-defined; callers may reorder as needed. ListByGame(ctx context.Context, gameID string) ([]playermapping.PlayerMapping, error) // DeleteByGame removes every mapping owned by gameID. Returns nil // even when no rows were deleted (idempotent). DeleteByGame(ctx context.Context, gameID string) error }