Replace in-memory game session store with Valkey #20

Open
opened 2026-04-19 07:23:32 +00:00 by forgejo-lila · 0 comments
Owner

Context

Game sessions (the mapping of questionId -> correctOptionId for active quizzes) are stored in an in-memory Map inside the API process. Sessions are lost on API restart. Multiplayer requires persistent, shared state.

What to do

  1. Add Valkey to the production Docker Compose stack.
  2. Implement ValkeyGameSessionStore using the existing GameSessionStore interface.
  3. Switch the API to use Valkey in production.

Files to change

  • docker-compose.yml (production, on VPS at ~/lila-app/) — add valkey service. Reference: valkey/valkey:9.1-alpine3.23.
  • apps/api/src/gameSessionStore/ValkeyGameSessionStore.ts — new file implementing GameSessionStore interface.
  • apps/api/src/gameSessionStore/index.ts — export Valkey implementation. Switch based on env var (e.g. SESSION_STORE=valkey).
  • .env (production) — add Valkey connection URL.

Interface reference

// apps/api/src/gameSessionStore/GameSessionStore.ts
interface GameSessionStore {
  save(sessionId: string, answers: Map<string, number>): Promise<void>;
  get(sessionId: string): Promise<Map<string, number> | null>;
  delete(sessionId: string): Promise<void>;
}

Acceptance criteria

  • Valkey container runs in production alongside other services
  • Game sessions survive API container restarts
  • Existing singleplayer quiz flow works unchanged
  • InMemoryGameSessionStore remains available for dev/testing
  • Sessions have a TTL (e.g. 1 hour) so stale sessions are cleaned up automatically

Notes

The dev compose already has Valkey. The GameSessionStore interface was designed for this swap — all methods are async even in the in-memory implementation.

## Context Game sessions (the mapping of questionId -> correctOptionId for active quizzes) are stored in an in-memory Map inside the API process. Sessions are lost on API restart. Multiplayer requires persistent, shared state. ## What to do 1. Add Valkey to the production Docker Compose stack. 2. Implement `ValkeyGameSessionStore` using the existing `GameSessionStore` interface. 3. Switch the API to use Valkey in production. ## Files to change - `docker-compose.yml` (production, on VPS at `~/lila-app/`) — add valkey service. Reference: `valkey/valkey:9.1-alpine3.23`. - `apps/api/src/gameSessionStore/ValkeyGameSessionStore.ts` — new file implementing `GameSessionStore` interface. - `apps/api/src/gameSessionStore/index.ts` — export Valkey implementation. Switch based on env var (e.g. `SESSION_STORE=valkey`). - `.env` (production) — add Valkey connection URL. ## Interface reference ```typescript // apps/api/src/gameSessionStore/GameSessionStore.ts interface GameSessionStore { save(sessionId: string, answers: Map<string, number>): Promise<void>; get(sessionId: string): Promise<Map<string, number> | null>; delete(sessionId: string): Promise<void>; } ``` ## Acceptance criteria - Valkey container runs in production alongside other services - Game sessions survive API container restarts - Existing singleplayer quiz flow works unchanged - InMemoryGameSessionStore remains available for dev/testing - Sessions have a TTL (e.g. 1 hour) so stale sessions are cleaned up automatically ## Notes The dev compose already has Valkey. The `GameSessionStore` interface was designed for this swap — all methods are async even in the in-memory implementation.
forgejo-lila added the
infra
label 2026-04-19 07:23:32 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: forgejo-lila/lila#20
No description provided.