Die Umstellung von Dogi-Media merkt jetzt, wenn sie nicht durchkam

BEIM AUSLIEFERN AUFGEFALLEN, NICHT BEIM BAUEN.

Nach Neustart und `git pull` standen die zwei neuen Spalten noch nicht
in der echten Ablage -- die Umstellung laeuft erst beim ersten
angemeldeten Zugriff. Das ist in Ordnung. Beim Nachsehen, WARUM sie
noch nicht da waren, fiel aber der eigentliche Mangel auf:

`bereit = true` stand UNBEDINGT hinter der Schleife, und der Fehler des
`ALTER TABLE` daneben ging still in die Konsole. Ein einziger
misslungener Versuch -- Datei gesperrt, Platte voll -- haette die
Umstellung damit fuer immer als erledigt vermerkt. Danach scheitert
JEDE Liste an `SELECT ... m.gilt_ab`, und zwar fuer alle, mit einem 503
und dem Satz "gerade nicht verfuegbar", der nirgends sagt, woran es
liegt. Bis zum naechsten Neustart.

Jetzt wird nach der Schleife nachgezaehlt. Fehlt etwas, wird geworfen
statt notiert, und der Vermerk bleibt aus -- der naechste Aufruf
versucht es also wieder. Ein Aufruf, der mit einer klaren Meldung
scheitert, ist besser als hundert, die raetseln.

AUF EINER KOPIE DURCHGESPIELT, nicht an den echten Daten erlebt:
Sicherung der laufenden Ablage gezogen (`.backup`, integrity_check ok,
Zeilenzahlen gegen live geprueft), darauf beide ALTER ausgefuehrt. Die
vorhandene Zeile ueberlebt mit leerem Fenster, die Listenabfrage des
Servers laeuft wortgleich durch, integrity_check danach ok.

pruef-material 159/0 (von 155). Neu ist eine Gegenprobe, die den
halb-umgestellten Zustand herstellt -- genau den, der vorher
"erledigt" geheissen haette -- und eine Zeile, die die Spalten in der
laufenden Ablage nachzaehlt statt sie anzunehmen.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-22 14:03:11 +02:00
co-authored by Claude Opus 5
parent fc823240ab
commit 774eeee3e5
2 changed files with 71 additions and 4 deletions
+49 -3
View File
@@ -524,6 +524,52 @@ const IN10 = tagLokal(10);
+ (fehlend.length ? ` -- es fehlt: ${fehlend.join(", ")}` : ""));
}
melde("");
melde("=== 9a. Die Umstellung merkt, wenn sie nicht durchkam ===");
{
/* WARUM DAS HIER STEHT: Im ersten Entwurf setzte `tabellen()` den
Vermerk "erledigt" UNBEDINGT -- auch wenn das ALTER scheiterte,
dessen Fehler daneben still in die Konsole ging. Ein einziger
misslungener Versuch haette die Umstellung fuer immer als getan
vermerkt, und danach scheitert JEDE Liste an `m.gilt_ab`: 503 fuer
alle, mit einer Meldung, die nicht sagt, woran es liegt.
Geprueft wird an einer Wegwerfdatei, nicht am laufenden Haus --
eine Tabelle ohne die Spalten laesst sich sonst gar nicht
herstellen, ohne etwas kaputtzumachen. */
const probe = new (await import("node:sqlite")).DatabaseSync(join(ordner, "probe-schema.db"));
probe.exec("CREATE TABLE material (id INTEGER PRIMARY KEY, dateiname TEXT)");
const NOETIG = ["gilt_ab", "gilt_bis"];
const fehlt = () => {
const da = new Set(probe.prepare("PRAGMA table_info(material)").all().map((c) => c.name));
return NOETIG.filter((n) => !da.has(n));
};
ok(fehlt().length === 2,
`vor der Umstellung fehlen beide Spalten (${fehlt().join(", ")})`);
probe.exec("ALTER TABLE material ADD COLUMN gilt_ab TEXT");
ok(fehlt().length === 1 && fehlt()[0] === "gilt_bis",
`nach der halben Umstellung fehlt genau eine (${fehlt().join(", ")}) `
+ `-- genau dieser Fall haette "erledigt" heissen koennen`);
probe.exec("ALTER TABLE material ADD COLUMN gilt_bis TEXT");
ok(fehlt().length === 0, "nach der ganzen keine mehr");
probe.close();
/* UND AM LAUFENDEN HAUS: Die Spalten sind wirklich da. Die Zeile
darueber beweist nur, dass die Rechnung stimmt -- nicht, dass sie
hier angewandt wurde. */
const { DatabaseSync: DS } = await import("node:sqlite");
const echt = new DS(process.env.WORKSPACE_DB);
const spalten = echt.prepare("PRAGMA table_info(material)").all().map((c) => c.name);
echt.close();
ok(NOETIG.every((n) => spalten.includes(n)),
`und in der laufenden Ablage stehen sie auch (${spalten.length} Spalten: `
+ `${spalten.join(", ")})`);
}
melde("");
melde("=== 9b. Ein Fenster, das nicht geht ===");
{
@@ -1033,11 +1079,11 @@ melde("");
/* Von 40 ueber 90 auf 145 angehoben (22.09.2026), als das Bearbeiten,
das Zeitfenster und der Blick am echten Bildschirm dazukamen. Die
Zahl ist keine Schaetzung: Sie steht knapp unter dem, was der Lauf
danach tatsaechlich gemeldet hat (155). Bei 90 waere der ganze
danach tatsaechlich gemeldet hat (159). Bei 90 waere der ganze
Browserabschnitt still ausfallen koennen, ohne dass die Zahl etwas
gesagt haette -- und genau das soll sie fangen. */
if (geprueft < 145) {
console.log(` FEHL nur ${geprueft} Pruefungen gelaufen -- erwartet waren 145+`);
if (geprueft < 150) {
console.log(` FEHL nur ${geprueft} Pruefungen gelaufen -- erwartet waren 150+`);
fehler++;
}
melde(fehler === 0
+22 -1
View File
@@ -127,14 +127,35 @@ function tabellen() {
Fehler, ein neues CREATE wuerde die vorhandenen Zeilen nicht
erreichen. Also nachsehen, was da ist, und nur ergaenzen, was
fehlt -- dieselbe Bauart wie bei den Personen-Spalten. */
const NOETIG = [["gilt_ab", "TEXT"], ["gilt_bis", "TEXT"]];
const da = new Set(d.prepare("PRAGMA table_info(material)").all().map((c) => c.name));
for (const [spalte, form] of [["gilt_ab", "TEXT"], ["gilt_bis", "TEXT"]]) {
for (const [spalte, form] of NOETIG) {
if (da.has(spalte)) continue;
try {
d.exec(`ALTER TABLE material ADD COLUMN ${spalte} ${form}`);
console.log(`[material] Spalte '${spalte}' ergaenzt.`);
} catch (f) { console.error(`[material] Spalte '${spalte}':`, f?.message); }
}
/* NACHSEHEN, OB ES AUCH GEKLAPPT HAT -- und das ist keine Formalie.
Im ersten Entwurf stand `bereit = true` UNBEDINGT hinter der
Schleife, und das `catch` darueber schluckte den Fehler. Ein
einziger misslungener Versuch (Datei gesperrt, Platte voll) haette
die Umstellung damit fuer immer als erledigt vermerkt. Danach
scheitert JEDE Liste an `SELECT ... m.gilt_ab` -- fuer alle, mit
einem 503 und der Meldung "gerade nicht verfuegbar", die nirgends
sagt, woran es liegt.
Jetzt wird nachgezaehlt, der Vermerk nur bei Erfolg gesetzt (der
naechste Aufruf versucht es also wieder), und der Fehler
geworfen statt notiert: Ein Aufruf, der mit einer klaren Meldung
scheitert, ist besser als hundert, die raetseln. */
const jetzt = new Set(d.prepare("PRAGMA table_info(material)").all().map((c) => c.name));
const fehlend = NOETIG.map(([n]) => n).filter((n) => !jetzt.has(n));
if (fehlend.length) {
throw new Error(`[material] Umstellung unvollstaendig, es fehlt: ${fehlend.join(", ")}`
+ " -- die Liste kann ohne diese Spalten nicht gelesen werden.");
}
bereit = true;
}