214 lines
5.6 KiB
Markdown
214 lines
5.6 KiB
Markdown
# 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.
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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`):
|
|
|
|
```json
|
|
{
|
|
"application_id": "application-01HZ...",
|
|
"game_id": "game-01HZ...",
|
|
"user_id": "user-01HZ...",
|
|
"status": "submitted",
|
|
"created_at": 1714081234567
|
|
}
|
|
```
|
|
|
|
### List my open invites
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
curl -s http://localhost:8095/api/v1/internal/games/game-01HZ...
|
|
```
|
|
|
|
### List memberships for a running game (Game Master)
|
|
|
|
```bash
|
|
curl -s http://localhost:8095/api/v1/internal/games/game-01HZ.../memberships
|
|
```
|
|
|
|
## Storage Inspection Examples
|
|
|
|
### Inspect a game record (PostgreSQL)
|
|
|
|
```bash
|
|
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)
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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`.
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
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`:
|
|
|
|
```bash
|
|
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`.
|