Files
galaxy-game/lobby/docs/examples.md
T
2026-04-26 20:34:39 +02:00

5.6 KiB

Configuration And Contract Examples

The examples below are illustrative. Replace localhost, port numbers, IDs, and timestamps with values that match the deployment under inspection.

Example .env

A minimum-viable LOBBY_* set for a local run against a single Redis container plus a PostgreSQL container with the lobby schema and the lobbyservice role provisioned. The full list with defaults lives in ../README.md §Configuration.

LOBBY_REDIS_MASTER_ADDR=127.0.0.1:6379
LOBBY_REDIS_PASSWORD=local
LOBBY_POSTGRES_PRIMARY_DSN=postgres://lobbyservice:lobbyservice@127.0.0.1:5432/galaxy?search_path=lobby&sslmode=disable
LOBBY_USER_SERVICE_BASE_URL=http://127.0.0.1:8083
LOBBY_GM_BASE_URL=http://127.0.0.1:8096

LOBBY_PUBLIC_HTTP_ADDR=:8094
LOBBY_INTERNAL_HTTP_ADDR=:8095

LOBBY_LOG_LEVEL=info
LOBBY_SHUTDOWN_TIMEOUT=30s

LOBBY_RACE_NAME_DIRECTORY_BACKEND=postgres
LOBBY_ENROLLMENT_AUTOMATION_INTERVAL=30s
LOBBY_RACE_NAME_EXPIRATION_INTERVAL=1h

OTEL_SERVICE_NAME=galaxy-lobby
OTEL_TRACES_EXPORTER=none
OTEL_METRICS_EXPORTER=none
LOBBY_OTEL_STDOUT_TRACES_ENABLED=false
LOBBY_OTEL_STDOUT_METRICS_ENABLED=false

Public HTTP Examples

The public listener trusts the X-User-ID header injected by Edge Gateway. Direct calls during development can supply the header manually.

Submit an application to a public game

curl -s -X POST \
  -H 'Content-Type: application/json' \
  -H 'X-User-ID: user-01HZ...' \
  http://localhost:8094/api/v1/lobby/games/game-01HZ.../applications \
  -d '{"race_name":"Aurora"}'

Response (200 OK):

{
  "application_id": "application-01HZ...",
  "game_id": "game-01HZ...",
  "user_id": "user-01HZ...",
  "status": "submitted",
  "created_at": 1714081234567
}

List my open invites

curl -s \
  -H 'X-User-ID: user-01HZ...' \
  'http://localhost:8094/api/v1/lobby/my/invites?page_size=50'

Register a race name from a pending entry

curl -s -X POST \
  -H 'Content-Type: application/json' \
  -H 'X-User-ID: user-01HZ...' \
  http://localhost:8094/api/v1/lobby/race-names/register \
  -d '{"race_name":"Aurora"}'

A 422 response with error.code="race_name_pending_window_expired" indicates the 30-day window has elapsed and the user must enter a new game to re-establish eligibility.

Internal HTTP Examples

The internal listener admits the admin actor without X-User-ID and serves GM-facing read paths.

Create a public game (admin)

curl -s -X POST \
  -H 'Content-Type: application/json' \
  http://localhost:8095/api/v1/lobby/games \
  -d '{
    "game_name": "Spring Tournament",
    "game_type": "public",
    "min_players": 4,
    "max_players": 12,
    "start_gap_hours": 24,
    "start_gap_players": 4,
    "enrollment_ends_at": 1716673200,
    "turn_schedule": "0 18 * * *",
    "target_engine_version": "1.4.0"
  }'

Read a game record (Game Master)

curl -s http://localhost:8095/api/v1/internal/games/game-01HZ...

List memberships for a running game (Game Master)

curl -s http://localhost:8095/api/v1/internal/games/game-01HZ.../memberships

Storage Inspection Examples

Inspect a game record (PostgreSQL)

psql "$LOBBY_POSTGRES_PRIMARY_DSN" -c \
  "SELECT * FROM lobby.games WHERE game_id = 'game-01HZ...'"

The columns mirror the fields documented in ../README.md §Game Record Model.

Inspect open enrollment games (sorted by created_at)

psql "$LOBBY_POSTGRES_PRIMARY_DSN" -c \
  "SELECT game_id, game_name, created_at FROM lobby.games
   WHERE status = 'enrollment_open'
   ORDER BY created_at DESC"

Inspect a Race Name Directory binding

psql "$LOBBY_POSTGRES_PRIMARY_DSN" -c \
  "SELECT canonical_key, game_id, holder_user_id, race_name, binding_kind,
          source_game_id, eligible_until_ms, registered_at_ms
   FROM lobby.race_names WHERE race_name = 'Aurora'"

Redis Examples

Publish a runtime job result (Runtime Manager simulation)

Runtime Manager would normally publish this. The shape matches the consumer in internal/worker/runtimejobresult/consumer.go.

redis-cli XADD runtime:job_results '*' \
  job_id 'runtime-job-01HZ...' \
  game_id 'game-01HZ...' \
  outcome 'success' \
  container_id 'container-7f...' \
  engine_endpoint '127.0.0.1:9100' \
  bound_at_ms 1714081239876

Publish a Game Master runtime snapshot update

redis-cli XADD gm:lobby_events '*' \
  kind 'runtime_snapshot_update' \
  game_id 'game-01HZ...' \
  current_turn '12' \
  runtime_status 'healthy' \
  engine_health_summary 'ok' \
  player_turn_stats '[{"user_id":"user-01HZ...","planets":4,"population":900,"ships_built":17}]'

Publish a game-finished event

redis-cli XADD gm:lobby_events '*' \
  kind 'game_finished' \
  game_id 'game-01HZ...' \
  finished_at_ms 1714123456789

Notification Intent Format

Lobby produces every notification through pkg/notificationintent and appends to notification:intents with plain XADD. A representative intent for lobby.application.submitted:

redis-cli XADD notification:intents '*' \
  envelope '{
    "type": "lobby.application.submitted",
    "producer": "lobby",
    "idempotency_key": "lobby.application.submitted:application-01HZ...",
    "audience": {"kind": "admin_email", "email_address_kind": "lobby_application_submitted"},
    "payload": {
      "game_id": "game-01HZ...",
      "game_name": "Spring Tournament",
      "applicant_user_id": "user-01HZ...",
      "applicant_name": "Aurora"
    }
  }'

The exact field set per type is documented in ../../notification/README.md and frozen by the AsyncAPI spec under ../../notification/api/intents-asyncapi.yaml.