test: Backend-e2e in CI stabil (eigene Jahre, Sperren, ein Server je App)
Backend E2E / e2e (push) Failing after 7m26s
Backend Image / build-and-push (push) Failing after 4m20s
Frontend Image / build-and-push (push) Successful in 15m44s

- daily-evaluation nutzt die Jahre 2011/2012 statt 2001, damit der Job nicht
  die Daten von autopilot und reminders liest und verändert.
- throttler: app.listen(0) einmal je App statt eines Servers je Anfrage
  (ECONNRESET bei 40 parallelen Anfragen).
- outbox-claims: 120 s Zeitlimit für 2000 sequentielle Anweisungen.
- migration-harness: eine `migrate deploy` zur Zeit über eine eigene
  Advisory-Sperre (P1002 bei parallelen Migrations-Suites).
- authority-notices und authority-notices-herd laufen über
  exclusive-suite nacheinander; Herd-Wiederholung räumt eigene Entwürfe.

Refs #32

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Nick.RosenloecherandClaude Opus 5.5 committed 2026-10-16 16:55:56 +02:00
1 parent 258e90828f
commit 6edae3efec
7 files changed
+217 -140

No files matched your search

@@ -0,0 +1,31 @@
import { Client } from 'pg';
/** Arbitrary keys, one per shared resource a suite needs to own alone. */
export const EXCLUSIVE_KEYS = {
/** Open drafts are unique per kind: only one suite may create/clear them. */
authorityNotices: 72707371,
} as const;
/**
* Holds a Postgres session advisory lock for the lifetime of a suite, so
* suites that clear or count a table whose rows are global (e.g. the open
* draft per notice kind) never run at the same time, even in parallel jest
* workers. Blocks until the previous owner released it; the lock disappears
* with the connection if a worker dies. Call release() in afterAll.
*/
export async function acquireExclusive(
key: number,
): Promise<() => Promise<void>> {
const url = process.env.DATABASE_URL;
if (!url) {
throw new Error('DATABASE_URL is not set');
}
const connection = new URL(url);
connection.searchParams.delete('schema');
const client = new Client({ connectionString: connection.toString() });
await client.connect();
await client.query('SELECT pg_advisory_lock($1)', [key]);
return async () => {
await client.end();
};
}