test(integration): size the all-time count case to its measured cost

The rollup parity case writes over half a million readings and folds them
into DAY buckets: about 35 s on a CI runner alone. Run beside two other heavy
files on the same Postgres it took 1.7 times as long and crossed the 60 s
default. Nothing in the case waits on a lock: its advisory locks are scoped
to the worker's own database, and the measurement with the database capped
at two CPUs (14.6 s alone, 25.3 s beside the sharing matrix and the restore
memory test) shows plain contention. The case gets a 150 s budget, twice the
contended estimate. HEALTHLOG_INTEGRATION_PG_CPUS caps the database
container so a CI runner's contention can be reproduced locally.
This commit is contained in:
Marc-André Bombeck committed 2026-10-22 07:18:57 +02:00
1 parent 7248347188
commit b6e9eb98f7
3 files changed
+27 -10

No files matched your search

+3 -1
View File
@@ -119,7 +119,9 @@ Each Vitest worker clones it on its first file (`CREATE DATABASE … TEMPLATE`,
see `tests/integration/worker-database.ts`), so files run in parallel without
seeing each other's rows, advisory locks or queue schema. The worker count
follows the host (half the cores, at most eight) unless
`HEALTHLOG_INTEGRATION_WORKERS` pins it; CI uses three.
`HEALTHLOG_INTEGRATION_WORKERS` pins it; CI uses three. To reproduce a CI runner's
contention on a larger machine, cap the database container with
`HEALTHLOG_INTEGRATION_PG_CPUS=2`.
`truncateAllTables` empties every table the migrations created and puts back
the rows they seed (the mood-tag and symptom catalogues), so a test starts
@@ -335,5 +335,12 @@ describe("dashboard all-time counts — parity with the live count", () => {
expect(legacy.get("PULSE")).toBeGreaterThan(500_000);
expect(legacy.get("WEIGHT")).toBe(5);
expect(legacy.get("BLOOD_GLUCOSE")).toBe(2);
});
// Over half a million rows written and folded into DAY buckets: about
// 35 s on a CI runner when the file ran alone. With three files sharing
// the runner's Postgres it took 1.7 times as long (measured with the
// database capped at two CPUs, HEALTHLOG_INTEGRATION_PG_CPUS=2: 14.6 s
// alone, 25.3 s beside the sharing matrix and the restore memory test),
// past the suite's 60 s default. The work is the point of the case, so
// the budget is sized to it: twice the contended estimate.
}, 150_000);
});
+16 -8
View File
@@ -44,7 +44,7 @@ const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const PROJECT_ROOT = resolve(__dirname, "..", "..");
let container: StartedPostgreSqlContainer | null = null;
let started: StartedPostgreSqlContainer | null = null;
declare module "vitest" {
export interface ProvidedContext {
@@ -56,7 +56,7 @@ declare module "vitest" {
export default async function setup(
project: TestProject,
): Promise<() => Promise<void>> {
container = await new PostgreSqlContainer("postgres:16-alpine")
let container = new PostgreSqlContainer("postgres:16-alpine")
.withDatabase(TEMPLATE_DATABASE)
.withUsername("healthlog")
.withPassword("healthlog")
@@ -74,10 +74,18 @@ export default async function setup(
"full_page_writes=off",
"-c",
"max_connections=400",
])
.start();
]);
// A CPU quota for the database container, to reproduce a CI runner's
// contention on a larger machine: HEALTHLOG_INTEGRATION_PG_CPUS=2.
const cpus = Number.parseFloat(
process.env.HEALTHLOG_INTEGRATION_PG_CPUS ?? "",
);
if (Number.isFinite(cpus) && cpus > 0) {
container = container.withResourcesQuota({ cpu: cpus });
}
started = await container.start();
const url = container.getConnectionUri() + "?schema=public&pgbouncer=false";
const url = started.getConnectionUri() + "?schema=public&pgbouncer=false";
process.env.DATABASE_URL = url;
// The explicit child environment keeps Prisma CLI on the same container.
@@ -91,9 +99,9 @@ export default async function setup(
project.provide("integrationDatabasePlan", await readTemplate(url));
return async () => {
if (container) {
await container.stop({ remove: true });
container = null;
if (started) {
await started.stop({ remove: true });
started = null;
}
};
}