- Connection pool and a small migration runner (schema_migrations, one transaction per migration, advisory lock) - games and game_players tables with indexes for a user's games and for popular games - PostgresGameHistoryRepository: idempotent save, get, recent games of a user, popular games - Integration tests against a real Postgres via testcontainers; a custom Jest environment gives tests Node's web globals, which Jest 27 leaves out - GameRecord carries the number of distinct spectators
32 lines
1.2 KiB
TypeScript
32 lines
1.2 KiB
TypeScript
import { GenericContainer, StartedTestContainer, Wait } from "testcontainers";
|
|
|
|
// Same images as apps/compose.yaml.
|
|
const POSTGRES_IMAGE = "postgres:17.6";
|
|
const VALKEY_IMAGE = "valkey/valkey:9.1.2";
|
|
|
|
export interface RunningService {
|
|
url: string;
|
|
container: StartedTestContainer;
|
|
}
|
|
|
|
export async function startPostgres(): Promise<RunningService> {
|
|
const container = await new GenericContainer(POSTGRES_IMAGE)
|
|
.withEnvironment({ POSTGRES_USER: "mancala", POSTGRES_PASSWORD: "mancala", POSTGRES_DB: "mancala" })
|
|
.withExposedPorts(5432)
|
|
// Postgres logs this twice: once for the init run, once when it is really up.
|
|
.withWaitStrategy(Wait.forLogMessage(/database system is ready to accept connections/, 2))
|
|
.start();
|
|
return {
|
|
url: `postgres://mancala:mancala@${container.getHost()}:${container.getMappedPort(5432)}/mancala`,
|
|
container,
|
|
};
|
|
}
|
|
|
|
export async function startValkey(): Promise<RunningService> {
|
|
const container = await new GenericContainer(VALKEY_IMAGE)
|
|
.withExposedPorts(6379)
|
|
.withWaitStrategy(Wait.forLogMessage(/Ready to accept connections/))
|
|
.start();
|
|
return { url: `redis://${container.getHost()}:${container.getMappedPort(6379)}`, container };
|
|
}
|