Suchindex ins Schema, Testdatenbank je Lauf frisch

Zwei Funde beim Nachsehen, warum `pnpm db:migrate` hängt.

**Der Befehl hing nicht, er fragte.** `prisma migrate dev` fand einen
Unterschied zwischen schema.prisma und den Migrationen und wartete auf einen
Namen für eine neue Migration. Deren Inhalt wäre gewesen, den GIN-Index über
den Suchvektor zu löschen: er stand nur in der Migration, weil
Unsupported("tsvector") dazu verleitet, den Index für nicht darstellbar zu
halten. Er ist darstellbar. Wer die Frage in Eile beantwortet hätte, hätte die
gestufte Volltextsuche verloren und es erst gemerkt, wenn die Suche leer
bleibt.

packages/db/tests/schema-drift.test.ts prüft das jetzt und nennt im Fehlerfall
das fehlende Stück. Gegengeprobt: ohne die Zeile im Schema schlägt der Test an.

Die Sperre, an der der zweite Versuch scheiterte (P1002), hielt eine verwaiste
Verbindung eines abgeschossenen migrate-dev. Wie man den Halter findet und
freigibt, steht jetzt in docs/11.

**Die Testdatenbank wird verworfen und neu angelegt.** Weil Akten nicht
löschbar sind, hatte sie 2487 angesammelt, und drei Zusicherungen auf eine auf
zehn Einträge begrenzte Liste fanden ihre eigene Akte nicht mehr darin. Das
sieht aus wie ein Fehler im Code und ist keiner. Neu aufsetzen kostet
dreieinhalb Sekunden; KEEP_TEST_DB=1 behält den Bestand.
This commit is contained in:
Harlekin
2026-09-03 17:13:34 +02:00
parent 2608c7587f
commit bfe12f3894
4 changed files with 101 additions and 6 deletions
+39 -5
View File
@@ -6,8 +6,19 @@ import { loadEnvFromRepoRoot } from '../dist/loadEnv.js'
import { resolveTestDatabaseUrl } from '../dist/testDatabase.js'
/**
* Legt die Testdatenbank an, falls sie fehlt, und bringt sie auf den aktuellen
* Migrationsstand. Wird von `pnpm test` vorgeschaltet.
* Setzt die Testdatenbank neu auf und bringt sie auf den Migrationsstand.
* Wird von `pnpm test` vorgeschaltet.
*
* **Neu aufsetzen, nicht nur anlegen.** Verlaufseinträge, Akten und
* Protokollzeilen sind nach harter Regel 2 aus CLAUDE.md nicht löschbar — was
* ein Testlauf anlegt, bleibt für immer stehen. Nach einigen Dutzend Läufen
* standen 2487 Akten in der Datenbank, und Tests, die eine auf zehn Einträge
* begrenzte Liste prüfen, fanden ihre eigene Akte nicht mehr darin. Solche
* Fehlschläge sehen aus wie ein Fehler im Code und sind keiner; das kostet mehr
* Zeit als das Neuaufsetzen.
*
* `KEEP_TEST_DB=1` behält den Bestand. Für das schnelle Nacheinander beim
* Arbeiten an einer einzelnen Testdatei.
*
* Läuft nur in der Entwicklung und in der CI, nie im Betrieb.
*/
@@ -21,12 +32,35 @@ maintenance.pathname = '/postgres'
const client = new pg.Client({ connectionString: maintenance.toString() })
await client.connect()
// Bezeichner lassen sich nicht als Parameter binden, deshalb quotiert. Der Name
// kommt aus resolveTestDatabaseUrl und endet immer auf _test.
const quoted = `"${dbName.replace(/"/g, '""')}"`
if (!dbName.endsWith('_test')) {
throw new Error(`Sicherung: ${dbName} endet nicht auf _test, wird nicht angefasst`)
}
try {
const { rowCount } = await client.query('SELECT 1 FROM pg_database WHERE datname = $1', [dbName])
if (rowCount === 0) {
// Bezeichner lassen sich nicht als Parameter binden, deshalb quotiert.
await client.query(`CREATE DATABASE "${dbName.replace(/"/g, '""')}"`)
const behalten = process.env.KEEP_TEST_DB === '1'
if (rowCount > 0 && !behalten) {
// Offene Verbindungen verhindern das Verwerfen — etwa ein Prisma Studio
// oder ein abgebrochener Testlauf.
await client.query(
`SELECT pg_terminate_backend(pid) FROM pg_stat_activity
WHERE datname = $1 AND pid <> pg_backend_pid()`,
[dbName],
)
await client.query(`DROP DATABASE ${quoted}`)
console.log(`[test-db] ${dbName} verworfen`)
}
if (rowCount === 0 || !behalten) {
await client.query(`CREATE DATABASE ${quoted}`)
console.log(`[test-db] ${dbName} angelegt`)
} else {
console.log(`[test-db] ${dbName} behalten (KEEP_TEST_DB=1)`)
}
} finally {
await client.end()