docs: reorder & testing

This commit is contained in:
Ilia Denisov
2026-05-07 00:58:53 +03:00
committed by GitHub
parent f446c6a2ac
commit 604fe40bcf
148 changed files with 9150 additions and 2757 deletions
+50 -62
View File
@@ -346,6 +346,12 @@ The current direct `Gateway -> User` self-service boundary uses that pattern:
- `user.account.get`
- `user.profile.update`
- `user.settings.update`
- `user.sessions.list`
- `user.sessions.revoke`
- `user.sessions.revoke_all`
- `user.games.command`
- `user.games.order`
- `user.games.report`
- external payloads and responses:
- FlatBuffers
- internal downstream transport:
@@ -479,20 +485,25 @@ payload only: `user_id`, optional `device_session_id`, `event_type`,
gateway derives `timestamp_ms`, recomputes `payload_hash`, signs the event,
and only then forwards it to the matching `SubscribeEvents` streams.
Notification-owned user-facing payloads are expected to use
`pkg/schema/fbs/notification.fbs`. The initial notification event vocabulary
in v1 is exactly:
Notification-owned user-facing payloads use
`pkg/schema/fbs/notification.fbs`. Each catalog kind has a 1:1
FlatBuffers table named with the camel-case form of the kind plus the
`Event` suffix. The closed v1 vocabulary is exactly the 13 kinds
defined in `backend/internal/notification/catalog.go`:
- `game.turn.ready`
- `game.finished`
- `lobby.invite.received`
- `lobby.invite.revoked`
- `lobby.application.submitted`
- `lobby.membership.approved`
- `lobby.membership.rejected`
- `lobby.application.approved`
- `lobby.application.rejected`
- `lobby.membership.removed`
- `lobby.membership.blocked`
- `lobby.invite.created`
- `lobby.invite.redeemed`
- `lobby.race_name.registration_eligible`
- `lobby.race_name.registered`
- `lobby.race_name.pending`
- `lobby.race_name.expired`
- `runtime.image_pull_failed` (admin recipient)
- `runtime.container_start_failed` (admin recipient)
- `runtime.start_config_invalid` (admin recipient)
`lobby.application.submitted` is published toward `Gateway` only for the
private-game owner flow. The public-game variant is email-only.
@@ -589,68 +600,45 @@ Expected session fields available to the gateway:
### Session Cache
`SessionCache` provides the fast path for:
`SessionCache` is the in-memory LRU + TTL store fronting every
authenticated request. It serves the hot path for:
- session existence checks;
- `device_session_id -> user_id`;
- `device_session_id user_id`;
- access to the base64-encoded raw Ed25519 client public key used for
signature verification;
- revoked versus active status checks.
- active vs revoked status checks.
Cache updates are event-driven.
TTL is allowed only as a safety net and must not replace invalidation events.
Implementation: a bounded LRU map (default 50 000 entries) wrapped by a
safety-net TTL (default 10 minutes). On miss the cache calls
`/api/v1/internal/sessions/{id}` against backend and seeds the entry.
`session_invalidation` push frames flip the cached entry's status to
`revoked` so subsequent authenticated requests are rejected at the edge
without another backend round-trip. The TTL covers the case of a missed
event (cursor aged out, gateway restart) by forcing a fresh backend
lookup at most once per window.
The gateway keeps a process-local in-memory snapshot
cache in front of the Redis fallback backend. Authenticated requests read the
local snapshot first. A local miss performs one bounded Redis lookup and seeds
the local snapshot so later requests for the same session avoid another Redis
round-trip unless a later session event changes the cached state.
The cache is process-local and unsynchronised across gateway instances.
The MVP ships a single gateway instance (see
`docs/ARCHITECTURE.md §18`); multi-instance scale-out is a later step
that may revisit the topology.
The local snapshot cache intentionally has no TTL and no size-based
eviction policy. Session lifecycle events are the authoritative mechanism for
keeping the hot path current, while Redis fallback remains the safety net for
cold misses and process restarts.
Configuration:
The Redis fallback implementation uses `go-redis/v9`. `cmd/gateway` opens one
shared `*redis.Client` via `pkg/redisconn` (instrumented with OpenTelemetry
tracing and metrics), issues a single bounded `PING` on startup, and refuses
to start when Redis is misconfigured or unavailable. The session cache,
replay store, session-events subscriber, and client-events subscriber all
use that shared client. See `docs/redis-config.md` for the rationale behind
the shape and the project-wide rules in
`ARCHITECTURE.md §Persistence Backends`.
- `GATEWAY_SESSION_CACHE_MAX_ENTRIES` with default `50000`
- `GATEWAY_SESSION_CACHE_TTL` with default `10m`
Required Redis connection variables:
Redis is used by the gateway only for the authenticated Replay Store
(see below). The shared client is opened via `pkg/redisconn` against
`GATEWAY_REDIS_MASTER_ADDR` and `GATEWAY_REDIS_PASSWORD`; optional
tuning lives under `GATEWAY_REDIS_REPLICA_ADDRS`, `GATEWAY_REDIS_DB`,
and `GATEWAY_REDIS_OPERATION_TIMEOUT` (all documented in
`docs/redis-config.md`).
- `GATEWAY_REDIS_MASTER_ADDR`
- `GATEWAY_REDIS_PASSWORD`
Optional Redis connection variables:
- `GATEWAY_REDIS_REPLICA_ADDRS` (comma-separated; reserved for future
read-routing — currently unused)
- `GATEWAY_REDIS_DB` with default `0`
- `GATEWAY_REDIS_OPERATION_TIMEOUT` with default `250ms`
> Removed: `GATEWAY_SESSION_CACHE_REDIS_ADDR`,
> `GATEWAY_SESSION_CACHE_REDIS_USERNAME`,
> `GATEWAY_SESSION_CACHE_REDIS_PASSWORD`,
> `GATEWAY_SESSION_CACHE_REDIS_DB`,
> `GATEWAY_SESSION_CACHE_REDIS_TLS_ENABLED`. `pkg/redisconn.LoadFromEnv`
> rejects the deprecated `GATEWAY_REDIS_TLS_ENABLED` and
> `GATEWAY_REDIS_USERNAME` variables at startup.
Per-subsystem Redis behavior variables (namespace, timeouts):
- `GATEWAY_REPLAY_REDIS_KEY_PREFIX` with default `gateway:replay:`
- `GATEWAY_REPLAY_REDIS_RESERVE_TIMEOUT` with default `250ms`
Gateway no longer keeps a session cache projection or the two Redis
Streams (`session_events`, `client_events`). Session lookup is a
synchronous REST call to backend, and inbound client / session events
arrive through the gRPC `Push.SubscribePush` consumer (see the
**Backend Client** section below). Redis is therefore used only by
the Replay Store.
> Removed: the previous Redis-backed session-cache projection and its
> environment variables (`GATEWAY_SESSION_CACHE_REDIS_*`,
> `GATEWAY_REDIS_TLS_ENABLED`, `GATEWAY_REDIS_USERNAME`).
> `pkg/redisconn.LoadFromEnv` rejects the deprecated names at startup.
### Backend Client