The backend README, how to run and test it, what is easy to get wrong with the game loop and the shared data formats, and the deployment note. The web app was played against it in Chrome: a full game with a spectator, a reload, a restart mid-game, the replay and a game lost on time.
89 lines
5.4 KiB
Markdown
89 lines
5.4 KiB
Markdown
# Quarkus backend: requirements
|
|
|
|
Status: implemented on branch `feature/quarkus-backend`; checked in Chrome against the local stack.
|
|
Scope: `apps/backend`, its Docker image, `apps/compose.yaml` and the docs.
|
|
|
|
## Goals
|
|
|
|
The backend is rewritten in Java with Quarkus on the latest Java LTS (Java 25). Players, the web app and the mobile
|
|
app notice nothing: the WebSocket protocol, the HTTP API and the stored data stay as they are, and the new backend
|
|
can replace the Node backend in a running deployment without ending live games.
|
|
|
|
## Terms
|
|
|
|
- **Node backend**: the Express + `ws` backend in `apps/backend` before this change.
|
|
- **Java backend**: its replacement.
|
|
- **Wire format**: the JSON sent over the WebSocket and the HTTP API, as the clients in `packages/core`,
|
|
`apps/frontend` and `apps/mobile` read it.
|
|
|
|
## Requirements
|
|
|
|
### R1. Platform
|
|
- R1.1 The backend is a Quarkus application (the latest stable 3.x release) compiled for and run on Java 25.
|
|
- R1.2 It is built with Maven; dependencies have exact versions (the Quarkus platform BOM pins the extensions).
|
|
- R1.3 It runs in JVM mode. A native image is out of scope.
|
|
- R1.4 It no longer depends on `packages/core` or `packages/mancala.js`; the game rules it needs are part of the
|
|
Java backend.
|
|
|
|
### R2. Game rules
|
|
- R2.1 The Java backend plays games by exactly the rules of `packages/mancala.js`: the same moves are allowed, the
|
|
same errors are raised, and every move produces the same board, the same history entry (board snapshot and game
|
|
steps with their data) and the same next player.
|
|
- R2.2 A test replays games recorded with the TypeScript engine and compares every result, including the JSON a
|
|
client receives, so the two engines cannot drift apart unnoticed. The recording can be regenerated with a script.
|
|
|
|
### R3. WebSocket protocol
|
|
- R3.1 Clients connect to the server's root path, as now (`ws://localhost:5005`, `wss://api.playmancala.app`).
|
|
- R3.2 Every channel in `packages/core/src/rtmt/channel_names.ts` behaves as in the Node backend: the same messages
|
|
are sent to the same users in the same order, with the same JSON. This covers authentication (`auth`, `on_auth`,
|
|
`on_auth_error`, close code 4001, the 5 second timeout, token refresh), matchmaking, moves, leaving, spectating,
|
|
connection changes, live game previews and the ping/pong keep-alive.
|
|
- R3.3 Legacy clients that connect with `?userKey=<uuid>` work while `LEGACY_USERKEY_AUTH` is on.
|
|
- R3.4 A user can be connected from several sockets; the user is offline when the last one closes.
|
|
|
|
### R4. HTTP API
|
|
- R4.1 `GET /`, `GET /register/` (only with legacy auth), `GET /game/:id`, `GET /games/popular`,
|
|
`GET /games/me/active` and `GET /games/me` answer with the same status codes and JSON as in the Node backend.
|
|
- R4.2 CORS allows every origin, as now.
|
|
- R4.3 Requests are written to `access.log` in the common log format, as now.
|
|
|
|
### R5. Data
|
|
- R5.1 The Java backend uses the existing Postgres schema and the `schema_migrations` table: on a database the Node
|
|
backend migrated, it applies nothing; on an empty one it creates the same tables.
|
|
- R5.2 It restores live games that the Node backend saved in Valkey (snapshot versions 1 and 2), and writes snapshots
|
|
the Node backend can restore, so a rollback also keeps live games.
|
|
- R5.3 It saves finished games that the Node backend left pending in Valkey, and pending records it leaves can be
|
|
saved by the Node backend.
|
|
- R5.4 Saved games and cached lists have the same JSON as before; a game saved by either backend reads the same.
|
|
|
|
### R6. Behaviour when a dependency is down
|
|
Unchanged from `game-history` and `game-clock`:
|
|
- R6.1 Games are played while Postgres or Valkey is down. Finished games are kept and saved once Postgres is back;
|
|
lists are served without the missing data.
|
|
- R6.2 The backend starts while Postgres is down (migrations are retried) and while Valkey is down (live games are
|
|
then not restored).
|
|
- R6.3 Live games survive a restart; the time the backend is down is not charged to the clock.
|
|
|
|
### R7. Configuration and deployment
|
|
- R7.1 The settings stay environment variables with the same names and defaults (`PORT`, `KEYCLOAK_*`,
|
|
`LEGACY_USERKEY_AUTH`, `VALKEY_URL`, `GAME_CLOCK_MS`), except the database: `DATABASE_URL` is replaced by
|
|
`DATABASE_JDBC_URL`, `DATABASE_USERNAME` and `DATABASE_PASSWORD`. `apps/.env` needs no change.
|
|
- R7.2 The Docker image is still built from the repo root with `docker build -f apps/backend/Dockerfile .`, listens
|
|
on port 6000 in the container and runs under `apps/compose.yaml` as before.
|
|
- R7.3 `mvn quarkus:dev` runs the backend locally on port 5005 against the compose services, like `yarn dev` did.
|
|
|
|
### R8. Tests and docs
|
|
- R8.1 The Node backend's tests are ported: game manager, live games, clock scheduler, token verifier, WebSocket
|
|
server, HTTP API, Postgres repository and Valkey store and cache. Tests that need Postgres or Valkey run them in
|
|
Docker, as now.
|
|
- R8.2 The web app is played against the Java backend in Chrome: login, a full game between two users, a spectator,
|
|
live previews, reconnecting, the game clock, restart with a live game, and the replay of the saved game.
|
|
- R8.3 `README.md`, `apps/backend/README.md`, `AGENTS.md` and `TODO.md` describe the Java backend.
|
|
|
|
## Out of scope
|
|
|
|
- Changes to the protocol, the API or the stored data, including fixing their known quirks (e.g. `on_game_crashed`
|
|
sending `{}`).
|
|
- Running more than one backend instance.
|
|
- Publishing the Java engine as a library, or replacing the TypeScript engine in the clients.
|