DER AGENTUR-BEREICH (Stufe 4 des Plans)
Kernprinzip 04 des Konzepts lautet woertlich "Die Agentur bleibt
angebunden" -- und dafuer gab es bis heute nichts. Fuenf Bereiche
standen, der sechste fehlte vollstaendig. Damit stand nirgends, welche
Kampagne laeuft, welche Schulung ansteht und wie ein Anliegen an die
Agentur ausgegangen ist. Das lief ueber private Nachrichten: nicht
auffindbar, nicht nachvollziehbar, beim naechsten Mal von vorn.
Vier Arten, und die vierte ist der Punkt: kampagne, schulung, anliegen
und ZUSTAENDIGKEIT. Die letzte ist keine Verlegenheit, sondern das, was
das Konzept ausdruecklich fordert -- Betreuung und Umsetzung sind unsere
Seite, offizielle Wege sind Agenturseite. Solange das nur im Kopf steht,
wird es bei jedem Streitfall neu verhandelt.
Der Umbau war das eigentliche Risiko, nicht der Bereich: Ein CHECK
laesst sich in SQLite nicht aendern, die Tabelle muss neu gebaut werden
-- und dabei werden ALLE vorhandenen Eintraege umgeschrieben. Deshalb
geht pruef-agentur.mjs (31 Pruefungen) den Weg wirklich: Sie baut eine
Datenbank im ALTEN Stand nach, fuellt sie mit allen fuenf Bereichen,
laesst die echte Anwendung darueberlaufen und zaehlt danach jede Zeile
UND jedes Feld nach -- auch die seltenen Spalten (hook, creator_extern),
die man beim Abschreiben des Bauplans vergisst. Wichtigste Gegenprobe:
Der CHECK muss danach noch BEISSEN. Eine Umstellung, die nebenbei die
Schranke entfernt, sieht aus wie ein Erfolg und ist der schlimmere
Ausgang.
Nebenbei drei abgeschriebene Bereichslisten beseitigt (Wochenbericht,
Suche, Report-Ziele). Im Wochenbericht waere der neue Bereich sonst
schlicht nicht vorgekommen -- ohne Fehler, ohne Luecke, einfach nicht da.
ZWEI PRUEFUNGEN, DIE DEN GESAMTLAUF ZUM STILLSTAND BRACHTEN
pruef-call-kategorien.mjs hing DREI STUNDEN. Ursache war ein Zeitzuender
in ihr selbst: Sie legte Calls auf "heute 18:00" und erwartete zwei
davon unter "Heute". Ab 18 Uhr sind die vorbei, der Server schiebt sie
nach "Protokoll fehlt", und die Oberflaeche unterteilt erst ab FUENF
anstehenden. Uebrig blieben vier, die Bloecke verschwanden, und die
Pruefung wartete auf einen Klick auf einen Block, den es nicht gab.
Genau die Sorte Fehler, vor der die Projektnotiz vom 06.09. warnt: Sie
war um 17:59 gruen und um 18:01 rot, ohne dass sich am Code etwas
geaendert hatte. Jetzt liegen alle Zeiten RELATIV zu jetzt, und die
Erwartung wird mit derselben Vorschrift gerechnet, die calls.js benutzt
-- statt Zahlen, die nur zu einer bestimmten Tageszeit stimmen.
Und der Grund, warum daraus ein Stillstand statt eines Fehlers wurde:
index.js setzt bewusst zwei Auffangnetze (uncaughtException,
unhandledRejection). Fuer den Betrieb richtig -- ein Fehler darf die
Website nicht offline nehmen. Fuer eine Pruefung fatal: Sie importiert
index.js in denselben Prozess und erbt die Netze. Ihr eigener Absturz
wird dann nur protokolliert, und der Express-Server haelt den Prozess
danach ewig am Leben. Kein Fehler, kein Ergebnis, kein Ende.
Deshalb zwei Abhilfen, die zusammengehoeren:
* server/helfer-notbremse.mjs -- haengt eigene Zuhoerer DANEBEN
(process.on ergaenzt, es ersetzt nicht) und beendet den Lauf mit
Fehler; dazu ein Wecker. In alle 42 Browserpruefungen eingebaut.
Der Betrieb bleibt unveraendert.
* tools/alles-pruefen.mjs gibt jeder Datei eine Frist von 600 s. Wer
sie reisst, wird abgebrochen und ZAEHLT ALS FEHLGESCHLAGEN, mit der
letzten Ausgabe davor als Beleg. Einzelne Dateien nachzuruesten hilft
nur bis zur naechsten ohne Notbremse -- deshalb sitzt sie dort, wo
sie fuer alle gilt, auch fuer die, die es noch nicht gibt.
AUSSERDEM: pruef-breiten.mjs pruefte 16 Seiten aus einer Liste von Hand,
chat.html und leistung.html fehlten darin. Der Chat war bei keiner
einzigen der neun Breiten je gemessen worden. Wie bei pruef-handy kommt
die Liste jetzt aus dem Verzeichnis.
Co-Authored-By: Claude Opus 5 <[email protected]>
76 lines
3.3 KiB
JavaScript
76 lines
3.3 KiB
JavaScript
/* DIE NOTBREMSE FÜR PRÜFUNGEN
|
|
|
|
---------------------------------------------------------------------
|
|
DER FEHLER, DEN DAS VERHINDERT (06.09.2026, drei Stunden gekostet)
|
|
|
|
index.js setzt am Ende bewusst zwei Auffangnetze:
|
|
|
|
process.on("uncaughtException", (f) => console.error(…));
|
|
process.on("unhandledRejection", (g) => console.error(…));
|
|
|
|
Für den echten Betrieb ist das genau richtig: Ein Fehler in einer
|
|
Nebensache darf die Website nicht offline nehmen.
|
|
|
|
Für eine PRÜFUNG ist es das Gegenteil. Eine Prüfung importiert
|
|
index.js in denselben Prozess -- und erbt damit die Netze. Wenn dann
|
|
ihr eigener Ablauf abstürzt (ein Playwright-Klick auf ein Element,
|
|
das es nicht gibt), wird der Absturz nur PROTOKOLLIERT. Danach
|
|
passiert nichts mehr: Das Skript ist zu Ende, aber der Express-Server
|
|
hält den Prozess am Leben. Kein Fehler, kein Ergebnis, kein Ende.
|
|
|
|
Genau so blieb pruef-call-kategorien.mjs drei Stunden stehen -- und
|
|
mit ihr der gesamte Regressionslauf, der auf sie wartete. Von aussen
|
|
sieht "läuft noch" genauso aus wie "hängt für immer".
|
|
|
|
---------------------------------------------------------------------
|
|
WAS DIESE DATEI TUT
|
|
|
|
Sie hängt ZWEI eigene Zuhörer daneben (process.on ergänzt, es
|
|
ersetzt nicht -- die Meldung von index.js bleibt also erhalten) und
|
|
beendet den Lauf mit einem Fehler. Und sie stellt einen Wecker: Wer
|
|
nach der Frist noch läuft, wartet nicht mehr, er hängt.
|
|
|
|
Beides greift NUR in Prüfungen. Der Betrieb importiert diese Datei
|
|
nicht und behält seine Netze unverändert.
|
|
|
|
---------------------------------------------------------------------
|
|
BENUTZUNG — nach dem Import von index.js, vor dem ersten Browser:
|
|
|
|
import { notbremse } from "./helfer-notbremse.mjs";
|
|
await import("./index.js");
|
|
notbremse(300_000, "die Kategorienpruefung");
|
|
*/
|
|
|
|
/** @param {number} fristMs Nach dieser Zeit gilt der Lauf als haengend.
|
|
* @param {string} wer Name für die Meldung. */
|
|
export function notbremse(fristMs = 300_000, wer = "diese Pruefung") {
|
|
let schonAus = false;
|
|
const raus = (art, was) => {
|
|
if (schonAus) return;
|
|
schonAus = true;
|
|
console.error(`\n FEHL ${wer}: ${art}`);
|
|
console.error(` ${String(was?.stack || was).split("\n").slice(0, 6).join("\n ")}`);
|
|
console.error(`\n Abgebrochen. Ohne diese Notbremse wuerde der Prozess`);
|
|
console.error(` weiterlaufen, weil der Server ihn am Leben haelt --`);
|
|
console.error(` ohne Fehler, ohne Ergebnis, ohne Ende.\n`);
|
|
process.exit(1);
|
|
};
|
|
|
|
process.on("uncaughtException", (f) => raus("unbehandelter Fehler", f));
|
|
process.on("unhandledRejection", (g) => raus("unbehandeltes Versprechen", g));
|
|
|
|
/* unref(): Der Wecker allein soll den Prozess NICHT am Leben halten.
|
|
Sonst haette ausgerechnet die Notbremse dafuer gesorgt, dass eine
|
|
fertige Pruefung noch fuenf Minuten herumsteht. */
|
|
const wecker = setTimeout(() => {
|
|
console.error(`\n FEHL ${wer} HING: nach ${Math.round(fristMs / 1000)} s war sie `
|
|
+ `noch nicht fertig.`);
|
|
console.error(` Haeufigste Ursachen: ein Warten auf ein Element, das nie kommt,`);
|
|
console.error(` oder eine Verbindung, die nie endet (Ereignisstrom).\n`);
|
|
process.exit(1);
|
|
}, fristMs);
|
|
wecker.unref?.();
|
|
|
|
return () => clearTimeout(wecker);
|
|
}
|