package ports import ( "context" "errors" "fmt" "strings" "galaxy/lobby/internal/domain/common" ) // ErrGMUnavailable signals that a Game Master call could not be // completed because the upstream service was unreachable, returned an // error response, or timed out. treats every non-success // outcome of GMClient.RegisterGame uniformly: the start flow transitions // to `paused` and an admin notification is published. var ErrGMUnavailable = errors.New("game master unavailable") //go:generate go run go.uber.org/mock/mockgen -destination=../adapters/mocks/mock_gmclient.go -package=mocks galaxy/lobby/internal/ports GMClient // GMClient executes synchronous calls to Game Master. introduced // the registration call; added the liveness probe used by the // voluntary resume flow. type GMClient interface { // RegisterGame registers a running game with Game Master after a // successful container start and runtime binding persistence. A // non-nil error is returned for any non-success outcome (transport // error, timeout, non-2xx response). Implementations wrap such // failures with ErrGMUnavailable so callers can branch with // errors.Is. RegisterGame(ctx context.Context, request RegisterGameRequest) error // Ping performs a synchronous liveness probe against Game Master. // Implementations return nil when GM is reachable and healthy and // wrap every other outcome (transport error, timeout, non-2xx // response) with ErrGMUnavailable so callers can // branch with errors.Is. Ping(ctx context.Context) error } // RegisterGameRequest stores the parameters required to register one // running game with Game Master. The shape mirrors the JSON body sent // by the HTTP adapter and is independent of the GM-side schema so the // adapter and the consumer can reason about it without leaking // transport details. type RegisterGameRequest struct { // GameID identifies the running game. GameID common.GameID // ContainerID identifies the engine container assigned by Runtime // Manager. ContainerID string // EngineEndpoint stores the network address Game Master uses to // reach the engine container. EngineEndpoint string // TargetEngineVersion stores the semver of the engine version that // was launched (copied from the game record at registration time). TargetEngineVersion string // TurnSchedule stores the cron expression that drives turn // generation (copied from the game record at registration time). TurnSchedule string } // Validate reports whether request stores the structurally valid // arguments required for Game Master registration. func (request RegisterGameRequest) Validate() error { if err := request.GameID.Validate(); err != nil { return fmt.Errorf("register game: game id: %w", err) } if strings.TrimSpace(request.ContainerID) == "" { return fmt.Errorf("register game: container id must not be empty") } if strings.TrimSpace(request.EngineEndpoint) == "" { return fmt.Errorf("register game: engine endpoint must not be empty") } if strings.TrimSpace(request.TargetEngineVersion) == "" { return fmt.Errorf("register game: target engine version must not be empty") } if strings.TrimSpace(request.TurnSchedule) == "" { return fmt.Errorf("register game: turn schedule must not be empty") } return nil }