Nachtrag zu B4: die Aufraeumung lief nie -- .changes an der falschen Stelle
WAS PASSIERT IST
Der Commit 60802170 ist um 23:33 ausgeliefert worden. Im Protokoll des
Servers stand danach:
[workspace] undefined zurueckgenommene Nachrichten endgueltig entfernt.
[workspace] 4 blaue Herzen auf babyblau umgestellt
Die zweite Zeile stimmt. Die erste ist der Befund: `undefined` statt
einer Zahl. Nachgesehen in der Live-Datenbank -- die fuenf
zurueckgenommenen Zeilen waren noch da.
URSACHE: `d.prepare("DELETE ...").changes` statt `.run().changes` --
also die Eigenschaft der vorbereiteten ANWEISUNG, nicht die des Laufs.
Die Anweisung wurde vorbereitet und nie ausgefuehrt. Nichts stuerzte
ab, nichts war rot, kein Fehler im Protokoll.
NEBENFOLGE, die es schlimmer gemacht haette: Die Sicherung wird VOR
dem Loeschen geschrieben. Da nie geloescht wurde, blieb die Bedingung
erfuellt -- bei JEDEM Neustart waere eine weitere Sicherungsdatei
entstanden. Genau das, wovor der Kommentar zwei Zeilen darueber warnt.
Ein Kommentar, der vor einem Fehler warnt, verhindert ihn nicht.
WAS JETZT ANDERS IST
Behoben, und die Umstellung ist eine exportierte Funktion geworden:
`loeschspurenAufraeumen(d, dbPfad)`. Nicht aus Ordnungsliebe -- eine
Umstellung, die tief im Hochfahren steckt, kann keine Pruefung
aufrufen. Eine Funktion schon.
pruef-loeschen.mjs (20 -> 25): stellt den alten Zustand her (Text leer,
weg_am gesetzt), ruft die Funktion und misst
* dass sie eine ZAHL meldet (`typeof === "number"`) -- genau hier
stand undefined, und 0 sieht in einer Meldung fast so aus,
* dass die Zeile wirklich verschwindet,
* und dass beim zweiten Aufruf nichts mehr passiert und nichts
gesichert wird.
Ohne den ersten dieser drei Haken waere der Fehler auch beim naechsten
Mal durchgegangen: Eine Meldung mit `undefined` ist gruen, solange
niemand sie liest.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
+80
-55
@@ -2191,6 +2191,85 @@ export function kanaeleFuer(person) {
|
||||
? KANAELE : [];
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
DIE ALTEN ZURUECKGENOMMENEN NACHRICHTEN GEHEN GANZ (22.09.2026)
|
||||
=====================================================================
|
||||
|
||||
Filipe: "Geloeschte Nachrichten verschwinden vollstaendig -- keine
|
||||
Spur, kein ‚wurde geloescht'-Hinweis, bei niemandem, auch nicht bei
|
||||
DogFather."
|
||||
|
||||
Seit dem 22.09.2026 loescht der Chat wirklich (DELETE). Was davor
|
||||
zurueckgenommen wurde, steht aber noch als Zeile da: Text leer,
|
||||
`weg_am` gesetzt. Die Anzeige zeigt sie nicht mehr -- in der
|
||||
Datenbank waere sie trotzdem. "Keine Spur" gaelte dann fuer alles,
|
||||
was ab heute passiert, und nicht fuer das, was ihn zu dem Satz
|
||||
gebracht hat.
|
||||
|
||||
ES GEHT NUR UM ZEILEN OHNE INHALT. `text = ''` ist die Bedingung,
|
||||
nicht bloss `weg_am IS NOT NULL`: Der Text wurde beim Zuruecknehmen
|
||||
geleert, also ist hier nichts zu verlieren. Stuende irgendwo doch
|
||||
noch Text in einer zurueckgenommenen Zeile, bliebe sie liegen --
|
||||
lieber ein Rest, den jemand ansehen kann, als ein stiller Verlust.
|
||||
|
||||
WIEDERHOLBAR: Beim zweiten Start gibt es nichts mehr zu tun, und es
|
||||
passiert nichts. GESICHERT WIRD VORHER -- aber nur, wenn es wirklich
|
||||
etwas zu tun gibt. Eine Sicherung bei jedem Start waere eine Datei
|
||||
je Neustart und damit kein Schutz, sondern Muell.
|
||||
|
||||
---------------------------------------------------------------------
|
||||
ALS EIGENE, EXPORTIERTE FUNKTION -- und das hat einen Grund, der an
|
||||
genau dieser Stelle entstanden ist.
|
||||
|
||||
In der ersten Fassung stand `d.prepare("DELETE ...").changes` statt
|
||||
`.run().changes`: die Eigenschaft der vorbereiteten ANWEISUNG, nicht
|
||||
die des Laufs. Die Anweisung wurde vorbereitet und nie ausgefuehrt.
|
||||
Nichts stuerzte ab, nichts war rot. Im Protokoll stand "undefined
|
||||
zurueckgenommene Nachrichten endgueltig entfernt" -- ein Zaehler,
|
||||
der `undefined` sagt, hat nicht gezaehlt, und was nicht zaehlt, hat
|
||||
meist auch nicht gearbeitet. Die fuenf Zeilen blieben liegen, und
|
||||
weil die Sicherung VOR dem Loeschen geschrieben wird, waere bei
|
||||
jedem Neustart eine weitere Sicherungsdatei entstanden.
|
||||
|
||||
Eine Umstellung, die tief im Hochfahren steckt, kann keine Pruefung
|
||||
aufrufen. Eine Funktion schon: pruef-loeschen.mjs gibt ihr eine
|
||||
vorbereitete Datenbank und sieht nach, was sie WIRKLICH getan hat.
|
||||
|
||||
@returns {{entfernt:number, gesichert:string|null}}
|
||||
===================================================================== */
|
||||
export function loeschspurenAufraeumen(d, dbPfad = DB_PFAD) {
|
||||
try {
|
||||
const spalten = d.prepare("PRAGMA table_info(chat_nachrichten)").all().map((x) => x.name);
|
||||
if (!spalten.includes("weg_am")) return { entfernt: 0, gesichert: null };
|
||||
const offen = d.prepare(
|
||||
"SELECT COUNT(*) AS n FROM chat_nachrichten WHERE weg_am IS NOT NULL AND text = ''").get().n;
|
||||
if (offen === 0) return { entfernt: 0, gesichert: null };
|
||||
|
||||
let sicherung = null;
|
||||
if (dbPfad) {
|
||||
const stempel = new Date().toISOString().replace(/[-:T]/g, "").slice(0, 14);
|
||||
sicherung = `${dbPfad}.vor-loeschspuren-${stempel}`;
|
||||
d.exec(`VACUUM INTO '${sicherung.replace(/'/g, "''")}'`);
|
||||
console.log("[workspace] Sicherung vor dem Aufraeumen:", sicherung);
|
||||
}
|
||||
/* Reaktionen und Erwaehnungen haengen mit ON DELETE CASCADE daran
|
||||
und gehen von selbst mit -- `PRAGMA foreign_keys = ON` steht
|
||||
beim Oeffnen. */
|
||||
const entfernt = d.prepare(
|
||||
"DELETE FROM chat_nachrichten WHERE weg_am IS NOT NULL AND text = ''").run().changes;
|
||||
/* Und die Raeume rechnen ihren letzten Zeitpunkt neu -- sonst
|
||||
stuende einer oben in der Liste, zu dessen Zeitpunkt es nichts
|
||||
mehr gibt. */
|
||||
d.exec(`UPDATE chat_raeume SET letzte_am =
|
||||
(SELECT MAX(erstellt) FROM chat_nachrichten WHERE raum_id = chat_raeume.id)`);
|
||||
console.log(`[workspace] ${entfernt} zurueckgenommene Nachrichten endgueltig entfernt.`);
|
||||
return { entfernt, gesichert: sicherung };
|
||||
} catch (fehler) {
|
||||
console.error("[workspace] Aufraeumen der Loeschspuren:", fehler?.message);
|
||||
return { entfernt: 0, gesichert: null };
|
||||
}
|
||||
}
|
||||
|
||||
export function kategorienFuer(person) {
|
||||
if (!person) return [];
|
||||
return TEAM_DOGI_ROLLEN.has(person.rolle) || person.rolle === "admin"
|
||||
@@ -3459,61 +3538,7 @@ function umstellungen(d) {
|
||||
}
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
DIE ALTEN ZURUECKGENOMMENEN NACHRICHTEN GEHEN GANZ (22.09.2026)
|
||||
=====================================================================
|
||||
|
||||
Filipe: „Geloeschte Nachrichten verschwinden vollstaendig -- keine
|
||||
Spur, kein ‚wurde geloescht'-Hinweis, bei niemandem, auch nicht
|
||||
bei DogFather."
|
||||
|
||||
Seit heute loescht der Chat wirklich (DELETE). Was davor
|
||||
zurueckgenommen wurde, steht aber noch als Zeile da: Text leer,
|
||||
`weg_am` gesetzt. Die Anzeige zeigt sie nicht mehr -- in der
|
||||
Datenbank waere sie trotzdem. „Keine Spur" gilt dann fuer alles,
|
||||
was ab heute passiert, und nicht fuer das, was ihn zu dem Satz
|
||||
gebracht hat.
|
||||
|
||||
ES GEHT NUR UM ZEILEN OHNE INHALT. `text = ''` ist die Bedingung,
|
||||
nicht bloss `weg_am IS NOT NULL`: Der Text wurde beim Zuruecknehmen
|
||||
geleert, also ist hier nichts zu verlieren. Stuende irgendwo doch
|
||||
noch Text in einer zurueckgenommenen Zeile, bliebe sie liegen --
|
||||
lieber ein Rest, den jemand ansehen kann, als ein stiller Verlust.
|
||||
|
||||
WIEDERHOLBAR: Beim zweiten Start gibt es nichts mehr zu tun, und
|
||||
es passiert nichts. Deshalb steht es hier bei den Umstellungen
|
||||
und nicht in einem einmaligen Skript, das jemand vergessen
|
||||
koennte.
|
||||
|
||||
GESICHERT WIRD VORHER -- aber nur, wenn es wirklich etwas zu tun
|
||||
gibt. Eine Sicherung bei jedem Start waere eine Datei je Neustart
|
||||
und damit kein Schutz, sondern Muell. */
|
||||
try {
|
||||
const spalten = d.prepare("PRAGMA table_info(chat_nachrichten)").all().map((x) => x.name);
|
||||
if (spalten.includes("weg_am")) {
|
||||
const offen = d.prepare(
|
||||
"SELECT COUNT(*) AS n FROM chat_nachrichten WHERE weg_am IS NOT NULL AND text = ''").get().n;
|
||||
if (offen > 0) {
|
||||
const stempel = new Date().toISOString().replace(/[-:T]/g, "").slice(0, 14);
|
||||
const sicherung = `${DB_PFAD}.vor-loeschspuren-${stempel}`;
|
||||
d.exec(`VACUUM INTO '${sicherung.replace(/'/g, "''")}'`);
|
||||
console.log("[workspace] Sicherung vor dem Aufraeumen:", sicherung);
|
||||
/* Reaktionen und Erwaehnungen haengen mit ON DELETE CASCADE
|
||||
daran und gehen von selbst mit -- `PRAGMA foreign_keys = ON`
|
||||
steht beim Oeffnen. Nachgesehen, nicht angenommen. */
|
||||
const weg = d.prepare(
|
||||
"DELETE FROM chat_nachrichten WHERE weg_am IS NOT NULL AND text = ''").changes;
|
||||
/* Und die Raeume rechnen ihren letzten Zeitpunkt neu -- sonst
|
||||
stuende einer oben in der Liste, zu dessen Zeitpunkt es
|
||||
nichts mehr gibt. */
|
||||
d.exec(`UPDATE chat_raeume SET letzte_am =
|
||||
(SELECT MAX(erstellt) FROM chat_nachrichten WHERE raum_id = chat_raeume.id)`);
|
||||
console.log(`[workspace] ${weg} zurueckgenommene Nachrichten endgueltig entfernt.`);
|
||||
}
|
||||
}
|
||||
} catch (fehler) {
|
||||
console.error("[workspace] Aufraeumen der Loeschspuren:", fehler?.message);
|
||||
}
|
||||
loeschspurenAufraeumen(d);
|
||||
|
||||
/* =====================================================================
|
||||
DIE BLAUEN HERZEN WERDEN BABYBLAU (22.09.2026)
|
||||
|
||||
Reference in New Issue
Block a user