Files
galaxy-game/gamemaster/api/runtime-events-asyncapi.yaml
T
2026-05-03 07:59:03 +02:00

205 lines
7.2 KiB
YAML

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.