Die Datasource-URL enthielt kein DB_CLOSE_DELAY. H2 nimmt dann 0 und schließt die Datei-Datenbank, sobald die letzte Verbindung geht — bei unbenutzter Anwendung zieht der Hikari-Pool genau das zurück. Der laufende Prozess schloss und öffnete seine Datenbank also wiederholt unter sich selbst.
Die Ursache des Vorfalls vom 2026-10-21 ist damit NICHT belegt
Klärung kam vor Behebung, und das Ergebnis ist negativ: ein leerer Pool bringt H2 nachweislich dazu, die Datenbank zu schließen — der nächste Schreibvorgang öffnet sie aber einfach wieder und gelingt. Das gilt auch bei 8000 Öffnen-und-Schließen-Durchläufen auf vier Threads, die das Rennen zwischen schließender und öffnender Sitzung absichtlich suchen. Die führende Erklärung trägt in dieser Form nicht.
Zwei Annahmen sind dabei als falsch belegt: H2 2.4.240 vergibt für 90xxx-Fehler den Fehlercode selbst als SQLState, nicht eine 08er-Klasse, und von den vermuteten Kandidaten erzeugen OBJECT_CLOSED (90007) und IO_EXCEPTION (90028/90031) gar keine JdbcSQLNonTransientConnectionException, sondern JdbcSQLNonTransientException.
Weiter eingegrenzt hat die Ursachenkette: UiErrorConfiguration protokolliert die unterste Ursache, und protokolliert wurde die H2-Klasse selbst — die Exception hatte also keine weitere Ursache.
Auslöser
Exception-Klasse
unterste Ursache
DATABASE_IS_CLOSED (90098)
JdbcSQLNonTransientConnectionException
keine
OutOfMemoryError → OUT_OF_MEMORY (90108)
JdbcSQLNonTransientConnectionException
java.lang.OutOfMemoryError
IOException → IO_EXCEPTION_2 (90031)
JdbcSQLNonTransientException
java.io.IOException
MVStoreException
JdbcSQLNonTransientException
org.h2.mvstore.MVStoreException
Speichermangel — naheliegend bei -Xmx384m — hätte java.lang.OutOfMemoryError hinterlassen. Übrig bleibt ein ursachenloses DATABASE_IS_CLOSED. Das Symptombild zeigt auf eine geschlossene Datenbank; der Weg dorthin bleibt offen, und dass Lesen durchgehend funktionierte, ist mit einer geschlossenen Datenbank ebenfalls nicht erklärt.
Belegt ist die beseitigte Vorbedingung, nicht der Fix. Die Härtung entfernt eine unnötige Unruhe im Betrieb, die den Vorfall nicht erklärt.
Begründung der Wahl zwischen den beiden Wegen
Gewählt: ;DB_CLOSE_DELAY=-1 an der Standard-URL in application.properties.
Verworfen: spring.datasource.hikari.connection-init-sql=SET DB_CLOSE_DELAY -1. Der Weg wirkt zwar unabhängig von der URL, aber SET DB_CLOSE_DELAY ist in H2 eine dauerhafte Einstellung der Datenbankdatei — nachgemessen: nach einem Lauf mit dieser Anweisung meldet auch eine Verbindung ohne sie DB_CLOSE_DELAY = -1. Die Einstellung wandert damit unsichtbar in die Daten und gilt anschließend auch für Werkzeuge, die die Datei kurz öffnen, etwa den Offline-Befehl AdminRecovery. Eine Konfigurationszeile, die sich zurücknehmen lässt, ist einer in die Datei geschriebenen Einstellung vorzuziehen, die das nicht tut; hinzu kommt, dass die Anweisung bei jeder neuen Verbindung läuft.
Der einzige Nachteil des gewählten Wegs — eine Umgebungsüberschreibung könnte den Parameter ersetzen — ist geprüft und geschlossen: der Lesezugriff auf ~/.config/werkjournal/environment zeigt, dass in Produktion keine Überschreibung der Datasource-URL gesetzt ist (die Datei führt nur Gastmodus, Bootstrap-Code und die Push-Schlüssel). Die Standard-URL ist dort also maßgeblich, und die Preflight nimmt eine künftige Überschreibung nur noch mit demselben Parameter an.
Preflight: Sicherungsgarantie bleibt
Bisher verglich die Preflight eine Überschreibung als Zeichenkette mit jdbc:h2:file:./data/werkjournal und hätte die neue URL abgelehnt. check_database_url prüft jetzt den Dateipfad: relativ wie absolut normalisiert, und er muss genau auf die verwaltete Datei fallen, weil das Deployment den Dienst stoppt und das geschlossene Datenverzeichnis in ein Rollback-Bündel kopiert. Weiterhin abgelehnt: Umwege über .., andere Dateinamen im selben Verzeichnis, mem: und tcp:. Zusätzlich muss DB_CLOSE_DELAY=-1 mitgeführt werden, und jeder weitere Parameter wird abgelehnt.
Letzteres schützt vor allem DB_CLOSE_ON_EXIT: die Vorgabe TRUE bleibt bewusst stehen, weil der Shutdown-Hook die Datenbank beim Prozessende sauber schließt und genau darauf die konsistente Sicherung beruht. Nachgemessen: auch mit DB_CLOSE_DELAY=-1 wird beim Prozessende geschlossen; -1 verhindert nur das Schließen im Betrieb. DB_CLOSE_ON_EXIT=FALSE würde das Datenverzeichnis ohne diese Zusicherung zurücklassen und wird deshalb zurückgewiesen.
Keine Migration, kein Schemaeingriff. Die fest eingetragene URL in AdminRecovery bleibt unverändert: dieser Offline-Befehl läuft kurzlebig ohne Pool.
Nachweise
H2ConnectionLifecycleTest: liest die Parameter der konfigurierten Standard-URL aus application.properties, baut einen Pool in der Form der Produktion (maximumPoolSize=4) und zieht dessen Verbindungen zurück. Ohne Härtung zählt ein DATABASE_EVENT_LISTENER mindestens eine Schließung der Datenbank, mit der konfigurierten URL keine. „Mindestens“, weil Hikari beim Aufbau des Pools eine Probeverbindung öffnet und wieder schließt, die ihrerseits schon eine Schließung auslösen kann.
tests/operations/test_update.py, neuer ManagedDatabaseUrlTest: die verwaltete Datei wird relativ, absolut und über einen Umweg akzeptiert, solange sie offen bleibt; Pfade außerhalb des Sicherungsverzeichnisses, andere Dateinamen, mem: und tcp: werden abgelehnt; ohne DB_CLOSE_DELAY=-1 wird abgelehnt; DB_CLOSE_ON_EXIT=FALSE, CIPHER und ein Parameter ohne Wert werden abgelehnt.
test_runtime_preflight_rejects_external_database_and_inline_overrides: derselbe Weg durch die vollständige Preflight über die geschützte Umgebungsdatei, einschließlich der jetzt angenommenen gehärteten Überschreibung.
Details: docs/implementation/h2-connection-lifecycle.md. Werkbaum: #h2-close-delay erledigt, #h2-failure-proof neu offen.
Hinweis zur Version
0.1.126-SNAPSHOT, abgestimmt mit dem parallelen Branch home-heading-one-line, der 0.1.125 nimmt. Wer zuletzt merged, sollte die Version auf main unmittelbar vorher prüfen und die nächste freie Nummer nehmen.
Die Datasource-URL enthielt kein `DB_CLOSE_DELAY`. H2 nimmt dann 0 und schließt die Datei-Datenbank, sobald die letzte Verbindung geht — bei unbenutzter Anwendung zieht der Hikari-Pool genau das zurück. Der laufende Prozess schloss und öffnete seine Datenbank also wiederholt unter sich selbst.
## Die Ursache des Vorfalls vom 2026-10-21 ist damit NICHT belegt
Klärung kam vor Behebung, und das Ergebnis ist negativ: ein leerer Pool bringt H2 nachweislich dazu, die Datenbank zu schließen — der nächste Schreibvorgang öffnet sie aber einfach wieder und gelingt. Das gilt auch bei 8000 Öffnen-und-Schließen-Durchläufen auf vier Threads, die das Rennen zwischen schließender und öffnender Sitzung absichtlich suchen. Die führende Erklärung trägt in dieser Form nicht.
Zwei Annahmen sind dabei als falsch belegt: H2 2.4.240 vergibt für 90xxx-Fehler den Fehlercode selbst als SQLState, nicht eine 08er-Klasse, und von den vermuteten Kandidaten erzeugen `OBJECT_CLOSED` (90007) und `IO_EXCEPTION` (90028/90031) gar keine `JdbcSQLNonTransientConnectionException`, sondern `JdbcSQLNonTransientException`.
Weiter eingegrenzt hat die Ursachenkette: `UiErrorConfiguration` protokolliert die unterste Ursache, und protokolliert wurde die H2-Klasse selbst — die Exception hatte also keine weitere Ursache.
| Auslöser | Exception-Klasse | unterste Ursache |
| --- | --- | --- |
| `DATABASE_IS_CLOSED` (90098) | `JdbcSQLNonTransientConnectionException` | keine |
| `OutOfMemoryError` → `OUT_OF_MEMORY` (90108) | `JdbcSQLNonTransientConnectionException` | `java.lang.OutOfMemoryError` |
| `IOException` → `IO_EXCEPTION_2` (90031) | `JdbcSQLNonTransientException` | `java.io.IOException` |
| `MVStoreException` | `JdbcSQLNonTransientException` | `org.h2.mvstore.MVStoreException` |
Speichermangel — naheliegend bei `-Xmx384m` — hätte `java.lang.OutOfMemoryError` hinterlassen. Übrig bleibt ein ursachenloses `DATABASE_IS_CLOSED`. Das Symptombild zeigt auf eine geschlossene Datenbank; der Weg dorthin bleibt offen, und dass Lesen durchgehend funktionierte, ist mit einer geschlossenen Datenbank ebenfalls nicht erklärt.
**Belegt ist die beseitigte Vorbedingung, nicht der Fix.** Die Härtung entfernt eine unnötige Unruhe im Betrieb, die den Vorfall nicht erklärt.
## Begründung der Wahl zwischen den beiden Wegen
**Gewählt: `;DB_CLOSE_DELAY=-1` an der Standard-URL in `application.properties`.**
**Verworfen: `spring.datasource.hikari.connection-init-sql=SET DB_CLOSE_DELAY -1`.** Der Weg wirkt zwar unabhängig von der URL, aber `SET DB_CLOSE_DELAY` ist in H2 eine **dauerhafte Einstellung der Datenbankdatei** — nachgemessen: nach einem Lauf mit dieser Anweisung meldet auch eine Verbindung ohne sie `DB_CLOSE_DELAY = -1`. Die Einstellung wandert damit unsichtbar in die Daten und gilt anschließend auch für Werkzeuge, die die Datei kurz öffnen, etwa den Offline-Befehl `AdminRecovery`. Eine Konfigurationszeile, die sich zurücknehmen lässt, ist einer in die Datei geschriebenen Einstellung vorzuziehen, die das nicht tut; hinzu kommt, dass die Anweisung bei jeder neuen Verbindung läuft.
Der einzige Nachteil des gewählten Wegs — eine Umgebungsüberschreibung könnte den Parameter ersetzen — ist geprüft und geschlossen: der Lesezugriff auf `~/.config/werkjournal/environment` zeigt, dass in Produktion **keine** Überschreibung der Datasource-URL gesetzt ist (die Datei führt nur Gastmodus, Bootstrap-Code und die Push-Schlüssel). Die Standard-URL ist dort also maßgeblich, und die Preflight nimmt eine künftige Überschreibung nur noch mit demselben Parameter an.
## Preflight: Sicherungsgarantie bleibt
Bisher verglich die Preflight eine Überschreibung als Zeichenkette mit `jdbc:h2:file:./data/werkjournal` und hätte die neue URL abgelehnt. `check_database_url` prüft jetzt den **Dateipfad**: relativ wie absolut normalisiert, und er muss genau auf die verwaltete Datei fallen, weil das Deployment den Dienst stoppt und das geschlossene Datenverzeichnis in ein Rollback-Bündel kopiert. Weiterhin abgelehnt: Umwege über `..`, andere Dateinamen im selben Verzeichnis, `mem:` und `tcp:`. Zusätzlich muss `DB_CLOSE_DELAY=-1` mitgeführt werden, und jeder weitere Parameter wird abgelehnt.
Letzteres schützt vor allem `DB_CLOSE_ON_EXIT`: die Vorgabe `TRUE` bleibt bewusst stehen, weil der Shutdown-Hook die Datenbank beim Prozessende sauber schließt und genau darauf die konsistente Sicherung beruht. Nachgemessen: auch mit `DB_CLOSE_DELAY=-1` wird beim Prozessende geschlossen; `-1` verhindert nur das Schließen im Betrieb. `DB_CLOSE_ON_EXIT=FALSE` würde das Datenverzeichnis ohne diese Zusicherung zurücklassen und wird deshalb zurückgewiesen.
Keine Migration, kein Schemaeingriff. Die fest eingetragene URL in `AdminRecovery` bleibt unverändert: dieser Offline-Befehl läuft kurzlebig ohne Pool.
## Nachweise
- `H2ConnectionLifecycleTest`: liest die Parameter der konfigurierten Standard-URL aus `application.properties`, baut einen Pool in der Form der Produktion (`maximumPoolSize=4`) und zieht dessen Verbindungen zurück. Ohne Härtung zählt ein `DATABASE_EVENT_LISTENER` mindestens eine Schließung der Datenbank, mit der konfigurierten URL keine. „Mindestens“, weil Hikari beim Aufbau des Pools eine Probeverbindung öffnet und wieder schließt, die ihrerseits schon eine Schließung auslösen kann.
- `tests/operations/test_update.py`, neuer `ManagedDatabaseUrlTest`: die verwaltete Datei wird relativ, absolut und über einen Umweg akzeptiert, solange sie offen bleibt; Pfade außerhalb des Sicherungsverzeichnisses, andere Dateinamen, `mem:` und `tcp:` werden abgelehnt; ohne `DB_CLOSE_DELAY=-1` wird abgelehnt; `DB_CLOSE_ON_EXIT=FALSE`, `CIPHER` und ein Parameter ohne Wert werden abgelehnt.
- `test_runtime_preflight_rejects_external_database_and_inline_overrides`: derselbe Weg durch die vollständige Preflight über die geschützte Umgebungsdatei, einschließlich der jetzt angenommenen gehärteten Überschreibung.
- `JAVA_HOME=~/opt/jdk25 ./tools/ci-jvm --without-firefox` grün: `BUILD SUCCESSFUL in 8m 15s`, 72 Betriebstests.
Details: `docs/implementation/h2-connection-lifecycle.md`. Werkbaum: `#h2-close-delay` erledigt, `#h2-failure-proof` neu offen.
## Hinweis zur Version
0.1.126-SNAPSHOT, abgestimmt mit dem parallelen Branch `home-heading-one-line`, der 0.1.125 nimmt. Wer zuletzt merged, sollte die Version auf `main` unmittelbar vorher prüfen und die nächste freie Nummer nehmen.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Die Datasource-URL enthielt kein DB_CLOSE_DELAY. H2 nimmt dann 0 und schließt die Datei-Datenbank,
sobald die letzte Verbindung geht — bei unbenutzter Anwendung zieht der Hikari-Pool genau das zurück.
Der laufende Prozess schloss und öffnete seine Datenbank also wiederholt unter sich selbst.
Das war der Anlass, und die Klärung kam vor der Behebung. Ergebnis: ein leerer Pool bringt H2
nachweislich dazu, die Datenbank zu schließen — der nächste Schreibvorgang öffnet sie aber einfach
wieder und gelingt. Das gilt auch bei 8000 Öffnen-und-Schließen-Durchläufen auf vier Threads, die das
Rennen absichtlich suchen. Die führende Erklärung trägt in dieser Form nicht.
Zwei Annahmen des Auftrags sind dabei als falsch belegt: H2 2.4.240 vergibt für 90xxx-Fehler den
Fehlercode selbst als SQLState, nicht eine 08er-Klasse, und von den genannten Kandidaten erzeugen
OBJECT_CLOSED (90007) und IO_EXCEPTION (90028/90031) gar keine JdbcSQLNonTransientConnectionException.
Weiter eingegrenzt hat die Ursachenkette: UiErrorConfiguration protokolliert die unterste Ursache, und
protokolliert wurde die H2-Klasse selbst. Ein Speichermangel hätte dort java.lang.OutOfMemoryError
hinterlassen, ein Schreibfehler der Ablage einen MVStoreException oder IOException. Übrig bleibt ein
ursachenloses DATABASE_IS_CLOSED. Das Symptombild zeigt auf eine geschlossene Datenbank, der Weg
dorthin bleibt offen — und dass Lesen durchgehend funktionierte, ist damit ebenfalls nicht erklärt.
- **`;DB_CLOSE_DELAY=-1` an der Standard-URL, nicht `connection-init-sql`.** `SET DB_CLOSE_DELAY` ist
in H2 eine dauerhafte Einstellung der Datenbankdatei: nach einem Lauf meldet auch eine Verbindung
ohne die Anweisung -1. Die Einstellung wanderte damit unsichtbar in die Daten und gälte auch für
Werkzeuge, die die Datei kurz öffnen. Eine Konfigurationszeile, die sich zurücknehmen lässt, ist
dem vorzuziehen. Der Lesezugriff auf die geschützte Umgebungsdatei in Produktion zeigt, dass dort
keine Überschreibung der Datasource-URL gesetzt ist; die Standard-URL ist also maßgeblich.
- **Die Preflight prüft den Dateipfad statt der Zeichenkette.** Ihre Zusicherung bleibt: der Pfad aus
der URL wird — relativ wie absolut — normalisiert und muss genau auf die verwaltete Datei fallen,
weil das Deployment das geschlossene Datenverzeichnis sichert. Umwege über `..`, andere Dateinamen,
`mem:` und `tcp:` werden weiterhin abgelehnt. Zusätzlich muss eine Überschreibung
`DB_CLOSE_DELAY=-1` mitführen, damit die Härtung nicht stillschweigend verlorengeht.
- **DB_CLOSE_ON_EXIT bleibt auf der Vorgabe TRUE.** Der Shutdown-Hook schließt die Datenbank beim
Prozessende weiterhin, und genau darauf beruht die konsistente Sicherung des gestoppten Dienstes;
`-1` verhindert nur das Schließen im Betrieb. Jeder weitere URL-Parameter wird abgelehnt, was
insbesondere `DB_CLOSE_ON_EXIT=FALSE` ausschließt.
Keine Migration, kein Schemaeingriff. Die fest eingetragene URL in AdminRecovery bleibt unverändert:
dieser Offline-Befehl läuft kurzlebig ohne Pool.
- `H2ConnectionLifecycleTest`: liest die Parameter der konfigurierten Standard-URL aus
application.properties, baut einen Pool in der Form der Produktion und zieht dessen Verbindungen
zurück. Ohne Härtung zählt ein DATABASE_EVENT_LISTENER mindestens eine Schließung, mit der
konfigurierten URL keine.
- `tests/operations/test_update.py`: neuer `ManagedDatabaseUrlTest` für die Pfadprüfung und die
abgelehnten Parameter, dazu die gehärtete Überschreibung durch die vollständige Preflight.
- `JAVA_HOME=~/opt/jdk25 ./tools/ci-jvm --without-firefox` grün: BUILD SUCCESSFUL in 8m 15s,
72 Betriebstests.
Details: `docs/implementation/h2-connection-lifecycle.md`.
Die Ursache selbst. Der fertige Commit auf Branch `failure-diagnostics` ergänzt die Logzeile um die
Kette der Exception-Klassen samt sqlState und errorCode und wird getrennt ausgeliefert; er ist das
Mittel, die Ursache beim nächsten Auftreten zu belegen statt zu raten.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Die Datasource-URL enthielt kein
DB_CLOSE_DELAY. H2 nimmt dann 0 und schließt die Datei-Datenbank, sobald die letzte Verbindung geht — bei unbenutzter Anwendung zieht der Hikari-Pool genau das zurück. Der laufende Prozess schloss und öffnete seine Datenbank also wiederholt unter sich selbst.Die Ursache des Vorfalls vom 2026-10-21 ist damit NICHT belegt
Klärung kam vor Behebung, und das Ergebnis ist negativ: ein leerer Pool bringt H2 nachweislich dazu, die Datenbank zu schließen — der nächste Schreibvorgang öffnet sie aber einfach wieder und gelingt. Das gilt auch bei 8000 Öffnen-und-Schließen-Durchläufen auf vier Threads, die das Rennen zwischen schließender und öffnender Sitzung absichtlich suchen. Die führende Erklärung trägt in dieser Form nicht.
Zwei Annahmen sind dabei als falsch belegt: H2 2.4.240 vergibt für 90xxx-Fehler den Fehlercode selbst als SQLState, nicht eine 08er-Klasse, und von den vermuteten Kandidaten erzeugen
OBJECT_CLOSED(90007) undIO_EXCEPTION(90028/90031) gar keineJdbcSQLNonTransientConnectionException, sondernJdbcSQLNonTransientException.Weiter eingegrenzt hat die Ursachenkette:
UiErrorConfigurationprotokolliert die unterste Ursache, und protokolliert wurde die H2-Klasse selbst — die Exception hatte also keine weitere Ursache.DATABASE_IS_CLOSED(90098)JdbcSQLNonTransientConnectionExceptionOutOfMemoryError→OUT_OF_MEMORY(90108)JdbcSQLNonTransientConnectionExceptionjava.lang.OutOfMemoryErrorIOException→IO_EXCEPTION_2(90031)JdbcSQLNonTransientExceptionjava.io.IOExceptionMVStoreExceptionJdbcSQLNonTransientExceptionorg.h2.mvstore.MVStoreExceptionSpeichermangel — naheliegend bei
-Xmx384m— hättejava.lang.OutOfMemoryErrorhinterlassen. Übrig bleibt ein ursachenlosesDATABASE_IS_CLOSED. Das Symptombild zeigt auf eine geschlossene Datenbank; der Weg dorthin bleibt offen, und dass Lesen durchgehend funktionierte, ist mit einer geschlossenen Datenbank ebenfalls nicht erklärt.Belegt ist die beseitigte Vorbedingung, nicht der Fix. Die Härtung entfernt eine unnötige Unruhe im Betrieb, die den Vorfall nicht erklärt.
Begründung der Wahl zwischen den beiden Wegen
Gewählt:
;DB_CLOSE_DELAY=-1an der Standard-URL inapplication.properties.Verworfen:
spring.datasource.hikari.connection-init-sql=SET DB_CLOSE_DELAY -1. Der Weg wirkt zwar unabhängig von der URL, aberSET DB_CLOSE_DELAYist in H2 eine dauerhafte Einstellung der Datenbankdatei — nachgemessen: nach einem Lauf mit dieser Anweisung meldet auch eine Verbindung ohne sieDB_CLOSE_DELAY = -1. Die Einstellung wandert damit unsichtbar in die Daten und gilt anschließend auch für Werkzeuge, die die Datei kurz öffnen, etwa den Offline-BefehlAdminRecovery. Eine Konfigurationszeile, die sich zurücknehmen lässt, ist einer in die Datei geschriebenen Einstellung vorzuziehen, die das nicht tut; hinzu kommt, dass die Anweisung bei jeder neuen Verbindung läuft.Der einzige Nachteil des gewählten Wegs — eine Umgebungsüberschreibung könnte den Parameter ersetzen — ist geprüft und geschlossen: der Lesezugriff auf
~/.config/werkjournal/environmentzeigt, dass in Produktion keine Überschreibung der Datasource-URL gesetzt ist (die Datei führt nur Gastmodus, Bootstrap-Code und die Push-Schlüssel). Die Standard-URL ist dort also maßgeblich, und die Preflight nimmt eine künftige Überschreibung nur noch mit demselben Parameter an.Preflight: Sicherungsgarantie bleibt
Bisher verglich die Preflight eine Überschreibung als Zeichenkette mit
jdbc:h2:file:./data/werkjournalund hätte die neue URL abgelehnt.check_database_urlprüft jetzt den Dateipfad: relativ wie absolut normalisiert, und er muss genau auf die verwaltete Datei fallen, weil das Deployment den Dienst stoppt und das geschlossene Datenverzeichnis in ein Rollback-Bündel kopiert. Weiterhin abgelehnt: Umwege über.., andere Dateinamen im selben Verzeichnis,mem:undtcp:. Zusätzlich mussDB_CLOSE_DELAY=-1mitgeführt werden, und jeder weitere Parameter wird abgelehnt.Letzteres schützt vor allem
DB_CLOSE_ON_EXIT: die VorgabeTRUEbleibt bewusst stehen, weil der Shutdown-Hook die Datenbank beim Prozessende sauber schließt und genau darauf die konsistente Sicherung beruht. Nachgemessen: auch mitDB_CLOSE_DELAY=-1wird beim Prozessende geschlossen;-1verhindert nur das Schließen im Betrieb.DB_CLOSE_ON_EXIT=FALSEwürde das Datenverzeichnis ohne diese Zusicherung zurücklassen und wird deshalb zurückgewiesen.Keine Migration, kein Schemaeingriff. Die fest eingetragene URL in
AdminRecoverybleibt unverändert: dieser Offline-Befehl läuft kurzlebig ohne Pool.Nachweise
H2ConnectionLifecycleTest: liest die Parameter der konfigurierten Standard-URL ausapplication.properties, baut einen Pool in der Form der Produktion (maximumPoolSize=4) und zieht dessen Verbindungen zurück. Ohne Härtung zählt einDATABASE_EVENT_LISTENERmindestens eine Schließung der Datenbank, mit der konfigurierten URL keine. „Mindestens“, weil Hikari beim Aufbau des Pools eine Probeverbindung öffnet und wieder schließt, die ihrerseits schon eine Schließung auslösen kann.tests/operations/test_update.py, neuerManagedDatabaseUrlTest: die verwaltete Datei wird relativ, absolut und über einen Umweg akzeptiert, solange sie offen bleibt; Pfade außerhalb des Sicherungsverzeichnisses, andere Dateinamen,mem:undtcp:werden abgelehnt; ohneDB_CLOSE_DELAY=-1wird abgelehnt;DB_CLOSE_ON_EXIT=FALSE,CIPHERund ein Parameter ohne Wert werden abgelehnt.test_runtime_preflight_rejects_external_database_and_inline_overrides: derselbe Weg durch die vollständige Preflight über die geschützte Umgebungsdatei, einschließlich der jetzt angenommenen gehärteten Überschreibung.JAVA_HOME=~/opt/jdk25 ./tools/ci-jvm --without-firefoxgrün:BUILD SUCCESSFUL in 8m 15s, 72 Betriebstests.Details:
docs/implementation/h2-connection-lifecycle.md. Werkbaum:#h2-close-delayerledigt,#h2-failure-proofneu offen.Hinweis zur Version
0.1.126-SNAPSHOT, abgestimmt mit dem parallelen Branch
home-heading-one-line, der 0.1.125 nimmt. Wer zuletzt merged, sollte die Version aufmainunmittelbar vorher prüfen und die nächste freie Nummer nehmen.🤖 Generated with Claude Code
a2aa123228to9db0d57badView command line instructions
Checkout
From your project repository, check out a new branch and test the changes.