94 lines
3.7 KiB
Go
94 lines
3.7 KiB
Go
package ports
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
)
|
|
|
|
//go:generate go run go.uber.org/mock/mockgen -destination=../adapters/mocks/mock_lobbyclient.go -package=mocks galaxy/gamemaster/internal/ports LobbyClient
|
|
|
|
// LobbyClient executes synchronous calls to Game Lobby. The port
|
|
// surfaces two operations:
|
|
//
|
|
// - GetMemberships — used by the membership cache to authorise player
|
|
// commands on the hot path.
|
|
// - GetGameSummary — used by the turn-generation orchestrator to
|
|
// resolve the human-readable `game_name` consumed by
|
|
// `notification:intents` payloads (`game.turn.ready`,
|
|
// `game.finished`, `game.generation_failed`). Failure is fail-soft:
|
|
// callers fall back to `game_id` rather than block the runtime
|
|
// mutation.
|
|
//
|
|
// Membership data and the game record are owned by Game Lobby; GM
|
|
// treats them as remote projections. Consequently the Membership and
|
|
// GameSummary types live on the port file rather than as domain types,
|
|
// mirroring rtmanager's `LobbyGameRecord` precedent.
|
|
type LobbyClient interface {
|
|
// GetMemberships returns every membership of gameID, in any
|
|
// status. The cache layer filters to `active` for authorisation.
|
|
// Implementations wrap any non-success outcome (transport error,
|
|
// timeout, non-2xx response) with ErrLobbyUnavailable so callers
|
|
// can branch with errors.Is.
|
|
GetMemberships(ctx context.Context, gameID string) ([]Membership, error)
|
|
|
|
// GetGameSummary returns the narrow projection of Lobby's
|
|
// `GameRecord` GM needs to populate notification payloads with a
|
|
// human-readable `game_name`. Implementations wrap any non-success
|
|
// outcome (transport error, timeout, non-2xx response, malformed
|
|
// payload) with ErrLobbyUnavailable.
|
|
GetGameSummary(ctx context.Context, gameID string) (GameSummary, error)
|
|
}
|
|
|
|
// Membership stores one row of the membership projection returned by
|
|
// `Lobby /api/v1/internal/games/{game_id}/memberships`. The shape
|
|
// mirrors `MembershipRecord` in
|
|
// `galaxy/lobby/api/internal-openapi.yaml`.
|
|
type Membership struct {
|
|
// UserID identifies the platform user.
|
|
UserID string
|
|
|
|
// RaceName stores the in-game race reserved for the user.
|
|
RaceName string
|
|
|
|
// Status reports `active`, `removed`, or `blocked`. GM authorises
|
|
// only `active` callers on the hot path.
|
|
Status string
|
|
|
|
// JoinedAt stores the wall-clock at which the membership entered
|
|
// active.
|
|
JoinedAt time.Time
|
|
|
|
// RemovedAt stores the wall-clock at which the membership left
|
|
// active. Nil while the membership is still active.
|
|
RemovedAt *time.Time
|
|
}
|
|
|
|
// GameSummary stores the narrow projection of Lobby's `GameRecord` GM
|
|
// consumes today: the platform game id, the human-readable
|
|
// `game_name`, and the platform-level lifecycle status. Additional
|
|
// fields can be added without breaking consumers because every caller
|
|
// reads through the typed fields directly.
|
|
type GameSummary struct {
|
|
// GameID identifies the platform game. Echoed back from Lobby as a
|
|
// sanity check.
|
|
GameID string
|
|
|
|
// GameName stores the human-readable game name maintained by
|
|
// Lobby. Used by the turn-generation orchestrator to populate
|
|
// `game_name` on `notification:intents` payloads.
|
|
GameName string
|
|
|
|
// Status stores Lobby's platform-level lifecycle status (`draft`,
|
|
// `enrollment_open`, `running`, `finished`, etc.). GM does not act
|
|
// on the value today; it is captured for future audit/log use.
|
|
Status string
|
|
}
|
|
|
|
// ErrLobbyUnavailable signals that a Lobby call could not be completed
|
|
// because the upstream service was unreachable, returned an error
|
|
// response, or timed out. GM's hot-path callers treat any non-success
|
|
// outcome uniformly: the player command is rejected with
|
|
// `service_unavailable` and the cache TTL eventually retries.
|
|
var ErrLobbyUnavailable = errors.New("lobby unavailable")
|