// Die Panel-Anbindung -- ohne Discord, ohne Datenbank, nur die Logik. // // Geprüft wird vor allem, was passieren muss, wenn das Panel NICHT da ist: // dann darf sich nichts anders verhalten als vorher. Eine Zusatzauskunft, die // den Monitor mit herunterreißt, wäre schlimmer als gar keine. // // node tools/panel-pruefen.mjs import { panelEintrag, zustandText, lastText, startetNoch, gewolltAus, STARTGNADE_MS } from '../src/panel.js' let fehler = 0 const zeig = (gut, was, dazu = '') => { if (!gut) fehler++ console.log(` ${gut ? 'ok ' : 'FEHL'} ${was}${dazu ? ' ' + dazu : ''}`) } const items = [ // So sieht ein Modpack in der Startphase aus: Container läuft, das // Fertig-Merkmal stand noch nicht im Protokoll, GameDig bekommt nichts. { name: 'atm11-test', zustand: 'running', bereit: false, port: 26000, seit: Date.now() - 120_000, cpu: 187, kerne: 20, ram: 5_153_960_755, ram_grenze: 7_516_192_768 }, { name: 'nallheim', zustand: 'running', bereit: true, port: 26004, seit: Date.now() - 3_600_000, cpu: 20, kerne: 20, ram: 1_073_741_824, ram_grenze: 5_368_709_120 }, { name: 'alt', zustand: 'exited', bereit: false, port: 26010, code: 0, oom: false, seit: null, cpu: null, kerne: null, ram: null, ram_grenze: null }, ] // Ein Start, der die Gnadenfrist gerissen hat -- der Fall, in dem die // Anbindung NICHT mehr beschwichtigen darf. const haengt = { ...items[0], seit: Date.now() - (STARTGNADE_MS + 60_000) } console.log('=== Zuordnen') zeig(panelEintrag(items, { port: 26000 })?.name === 'atm11-test', 'über den Port') zeig(panelEintrag(items, { name: 'NALLHEIM' })?.name === 'nallheim', 'ersatzweise über den Namen, groß/klein egal') zeig(panelEintrag(items, { port: 9999 }) === null, 'unbekannter Port -> nichts') zeig(panelEintrag(null, { port: 26000 }) === null, 'ohne Panel-Daten -> nichts') zeig(panelEintrag([], { port: 26000 }) === null, 'leere Liste -> nichts') console.log('') console.log('=== Was im Embed steht, wenn GameDig nichts erreicht') const startet = zustandText(items[0]) zeig(/Startet gerade/.test(startet ?? ''), 'startender Server -> „Startet gerade"', startet) zeig(/2 min/.test(startet ?? ''), 'mit Dauer', startet) zeig(/Gestoppt/.test(zustandText(items[2]) ?? ''), 'gestoppter -> „Gestoppt"', zustandText(items[2])) zeig(zustandText(items[1]) === null, 'ein bereiter Server trägt hier nichts bei — da war GameDig schon erfolgreich') zeig(zustandText(null) === null, 'ohne Eintrag -> null, dann bleibt es beim schlichten „Offline"') console.log('') console.log('=== Wann der Alarm UNTERDRÜCKT wird -- und wann nicht') zeig(startetNoch(items[0]) === true, 'startender Server in der Frist -> unterdrücken') zeig(startetNoch(items[1]) === false, 'ein fertiger Server ist kein Startvorgang') zeig(startetNoch(items[2]) === false, 'ein beendeter erst recht nicht') zeig(startetNoch(null) === false, 'ohne Panel -> nichts unterdrücken (Monitor wie vorher)') // Die wichtigste Zeile hier: `bereit` wird nie von allein wahr. Ohne diese // Grenze fräße die Anbindung genau den Alarm, für den es sie gibt. zeig(startetNoch(haengt) === false, 'nach der Gnadenfrist NICHT mehr unterdrücken -- sonst kommt der Alarm nie') zeig(/nicht fertig/.test(zustandText(haengt) ?? ''), 'und im Embed steht dann Klartext', zustandText(haengt)) zeig(startetNoch({ ...items[0], seit: null }) === true, 'ohne Startzeit -> Nachsicht (kaputter Zeitstempel, kein hängender Server)') const abgestuerzt = { ...items[2], code: 1 } const oomTot = { ...items[2], code: 137, oom: true } const altesPanel = { name: 'x', zustand: 'exited', bereit: false, port: 1 } // ohne code/oom zeig(gewolltAus(items[2]) === true, 'Code 0 -> jemand hat gestoppt, kein Alarm') zeig(gewolltAus({ ...items[2], code: 143 }) === true, 'Code 143 (SIGTERM) -> auch ein Stopp') zeig(gewolltAus(abgestuerzt) === false, 'Code 1 -> ABSTURZ, der Alarm muss durch') zeig(gewolltAus(oomTot) === false, 'OOM-Kill -> Alarm, auch bei Code 137') zeig(gewolltAus(altesPanel) === false, 'älteres Panel ohne `code` -> im Zweifel echter Ausfall') zeig(gewolltAus(items[0]) === false, 'ein laufender Server ist nicht "aus"') zeig(/Abgestürzt.*\(Code 1\)/.test(zustandText(abgestuerzt) ?? ''), 'Absturz steht mit Code im Embed', zustandText(abgestuerzt)) zeig(/Speicher/.test(zustandText(oomTot) ?? ''), 'OOM wird benannt, nicht als Absturz getarnt', zustandText(oomTot)) console.log('') console.log('=== Last') const last = lastText(items[0]) zeig(/4\.8 GB \/ 7\.0 GB/.test(last ?? ''), 'RAM mit Grenze', last) // 187 / 20 = 9.35, und toFixed(1) macht daraus 9.3 -- 9.35 liegt binär knapp // UNTER 9.35, also wird abgerundet. Hier steht der gemessene Wert, nicht der // erwartete; für eine Auslastungsanzeige ist das Zehntel ohnehin ohne Belang. zeig(/9\.3 % CPU/.test(last ?? ''), 'CPU als Anteil der MASCHINE, nicht Dockers 187 %', last) zeig(lastText(items[2]) === null, 'gestoppt -> keine Last') zeig(lastText(null) === null, 'ohne Eintrag -> nichts') console.log('') console.log('=== Abschaltbarkeit') // Ohne Panel-Eintrag muss JEDE dieser Funktionen null liefern, sonst steht // im Embed plötzlich ein leeres Feld. zeig([zustandText(undefined), lastText(undefined), panelEintrag(undefined, {})].every((x) => x == null), 'undefined überall -> überall null') console.log('') console.log(fehler ? `${fehler} FEHLER` : 'alles grün') process.exitCode = fehler ? 1 : 0