feat: gamemaster
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
asyncapi: 3.1.0
|
||||
info:
|
||||
title: Galaxy Game Master Runtime Events Contract
|
||||
version: 1.0.0
|
||||
description: |
|
||||
Stable Redis Streams contract for runtime snapshot updates and game
|
||||
finish events published by `Game Master` toward `Game Lobby` on the
|
||||
`gm:lobby_events` stream.
|
||||
|
||||
Two distinct message types share the channel and are discriminated
|
||||
by the `event_type` field on the payload:
|
||||
|
||||
- `RuntimeSnapshotUpdate` (`event_type=runtime_snapshot_update`) is
|
||||
published whenever a turn was generated (success or failure), the
|
||||
runtime status transitioned, or the engine health summary changed
|
||||
in response to a `runtime:health_events` observation. Duplicates
|
||||
are suppressed when the summary did not change.
|
||||
- `GameFinished` (`event_type=game_finished`) is published once
|
||||
when the engine reports `finished:true` on a turn-generation
|
||||
response. The runtime stays in `status=finished` indefinitely;
|
||||
no further events are published for the game.
|
||||
|
||||
Both payload schemas are closed (`additionalProperties: false`).
|
||||
Adding a field to either payload after this contract was frozen is
|
||||
a breaking change that requires a contract bump and a coordinated
|
||||
consumer update.
|
||||
|
||||
Polymorphism: the AsyncAPI surface uses two messages on one channel
|
||||
and one `send` operation per message. The
|
||||
`runtime_health-asyncapi.yaml` style of a single message with
|
||||
`oneOf` details is not used here because the two payload shapes
|
||||
have no shared field set beyond the discriminator and the
|
||||
`game_id`. See `gamemaster/docs/stage06-contract-files.md`.
|
||||
channels:
|
||||
lobbyEvents:
|
||||
address: gm:lobby_events
|
||||
messages:
|
||||
runtimeSnapshotUpdate:
|
||||
$ref: '#/components/messages/RuntimeSnapshotUpdate'
|
||||
gameFinished:
|
||||
$ref: '#/components/messages/GameFinished'
|
||||
operations:
|
||||
publishRuntimeSnapshotUpdate:
|
||||
action: send
|
||||
summary: Publish a runtime snapshot update for Game Lobby.
|
||||
channel:
|
||||
$ref: '#/channels/lobbyEvents'
|
||||
messages:
|
||||
- $ref: '#/channels/lobbyEvents/messages/runtimeSnapshotUpdate'
|
||||
publishGameFinished:
|
||||
action: send
|
||||
summary: Publish a game finish event for Game Lobby.
|
||||
channel:
|
||||
$ref: '#/channels/lobbyEvents'
|
||||
messages:
|
||||
- $ref: '#/channels/lobbyEvents/messages/gameFinished'
|
||||
components:
|
||||
messages:
|
||||
RuntimeSnapshotUpdate:
|
||||
name: RuntimeSnapshotUpdate
|
||||
title: Runtime snapshot update
|
||||
summary: Snapshot of one game's runtime state, published on transitions and health changes.
|
||||
payload:
|
||||
$ref: '#/components/schemas/RuntimeSnapshotUpdatePayload'
|
||||
examples:
|
||||
- name: runningTurnReady
|
||||
summary: Snapshot published after a successful turn generation.
|
||||
payload:
|
||||
event_type: runtime_snapshot_update
|
||||
game_id: game-123
|
||||
current_turn: 17
|
||||
runtime_status: running
|
||||
engine_health_summary: healthy
|
||||
player_turn_stats:
|
||||
- user_id: user-1
|
||||
planets: 4
|
||||
population: 12000
|
||||
- user_id: user-2
|
||||
planets: 3
|
||||
population: 9000
|
||||
occurred_at_ms: 1775121700000
|
||||
GameFinished:
|
||||
name: GameFinished
|
||||
title: Game finished
|
||||
summary: Terminal event published once when the engine reports finished:true on a turn-generation response.
|
||||
payload:
|
||||
$ref: '#/components/schemas/GameFinishedPayload'
|
||||
examples:
|
||||
- name: gameFinished
|
||||
summary: Game finished on turn 42; final per-player stats included.
|
||||
payload:
|
||||
event_type: game_finished
|
||||
game_id: game-123
|
||||
final_turn_number: 42
|
||||
runtime_status: finished
|
||||
player_turn_stats:
|
||||
- user_id: user-1
|
||||
planets: 6
|
||||
population: 25000
|
||||
- user_id: user-2
|
||||
planets: 0
|
||||
population: 0
|
||||
finished_at_ms: 1775130000000
|
||||
schemas:
|
||||
RuntimeStatus:
|
||||
type: string
|
||||
enum:
|
||||
- starting
|
||||
- running
|
||||
- generation_in_progress
|
||||
- generation_failed
|
||||
- stopped
|
||||
- engine_unreachable
|
||||
- finished
|
||||
description: Runtime status enum; identical to the value used in the internal REST contract.
|
||||
PlayerTurnStat:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required:
|
||||
- user_id
|
||||
- planets
|
||||
- population
|
||||
properties:
|
||||
user_id:
|
||||
type: string
|
||||
description: Platform user identifier of the player.
|
||||
planets:
|
||||
type: integer
|
||||
minimum: 0
|
||||
description: Number of planets controlled by the player at the snapshot turn.
|
||||
population:
|
||||
type: integer
|
||||
minimum: 0
|
||||
description: Total population controlled by the player at the snapshot turn.
|
||||
RuntimeSnapshotUpdatePayload:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required:
|
||||
- event_type
|
||||
- game_id
|
||||
- current_turn
|
||||
- runtime_status
|
||||
- engine_health_summary
|
||||
- player_turn_stats
|
||||
- occurred_at_ms
|
||||
properties:
|
||||
event_type:
|
||||
type: string
|
||||
const: runtime_snapshot_update
|
||||
description: Discriminator pinned to `runtime_snapshot_update`; consumers dispatch on this value.
|
||||
game_id:
|
||||
type: string
|
||||
description: Opaque stable game identifier.
|
||||
current_turn:
|
||||
type: integer
|
||||
minimum: 0
|
||||
description: Last completed turn number; zero when the snapshot reflects the pre-first-turn state.
|
||||
runtime_status:
|
||||
$ref: '#/components/schemas/RuntimeStatus'
|
||||
engine_health_summary:
|
||||
type: string
|
||||
description: Short text summary of engine health; empty until the first health observation.
|
||||
player_turn_stats:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/PlayerTurnStat'
|
||||
description: Per-player stats projection; empty before any turn has generated.
|
||||
occurred_at_ms:
|
||||
type: integer
|
||||
format: int64
|
||||
description: UTC Unix milliseconds when Game Master observed the underlying transition.
|
||||
GameFinishedPayload:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
required:
|
||||
- event_type
|
||||
- game_id
|
||||
- final_turn_number
|
||||
- runtime_status
|
||||
- player_turn_stats
|
||||
- finished_at_ms
|
||||
properties:
|
||||
event_type:
|
||||
type: string
|
||||
const: game_finished
|
||||
description: Discriminator pinned to `game_finished`; consumers dispatch on this value.
|
||||
game_id:
|
||||
type: string
|
||||
description: Opaque stable game identifier.
|
||||
final_turn_number:
|
||||
type: integer
|
||||
minimum: 0
|
||||
description: Last turn number generated before the engine reported finished:true.
|
||||
runtime_status:
|
||||
$ref: '#/components/schemas/RuntimeStatus'
|
||||
player_turn_stats:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/PlayerTurnStat'
|
||||
description: Final per-player stats projection at the finish turn.
|
||||
finished_at_ms:
|
||||
type: integer
|
||||
format: int64
|
||||
description: UTC Unix milliseconds when Game Master persisted the finish transition.
|
||||
Reference in New Issue
Block a user