00dffc59eb
- web/main.py: Session-basierte REST-API um den GA-Kern (POST /sitzung, .../tische, .../tische-datei, .../personen, .../berechnen, GET .../ergebnis[.svg]); Sessions in-memory mit 24h-TTL - web/static/index.html: einfache Browser-Testoberflaeche (Tisch-Tabelle mit Presets, tische.ini-Upload, CSV-Gaesteliste, Kennzahlen, SVG) - bin/run_web.bat/.sh + run_web_helper.ps1: start/stop/status inkl. Aufraeumen verwaister uvicorn-Reload-Kindprozesse (Zombie-Sockets) - work/hochzeit: 120 Hochzeitsgaeste, Ehrentafel, Kindertisch/Teenager- Tisch fest gesetzt, Kinderalter normalverteilt, ~85% Auslastung - work/innenhoefe: 300 Gaeste in zwei trapezfoermigen Innenhoefen mit 4er-Tischen, 12 VIPs vor der Buehne, Umfeld.svg mit Tanzflaeche/Band - Roadmap: Konzeptentscheidungen 1-11 (Zielgruppe, Einmalzahlung, MoR, Hetzner, Zwei-Marken-Strategie Sitz&Platz/SeatWonder), Namensrecherche im Anhang, M1-Fortschritt und GA-Lasttest-Datenpunkt dokumentiert Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
87 lines
3.6 KiB
PowerShell
87 lines
3.6 KiB
PowerShell
# ================================================================
|
|
# PowerShell-Helfer fuer run_web.bat (start/stop/status)
|
|
# Aufruf: powershell -NoProfile -ExecutionPolicy Bypass
|
|
# -File run_web_helper.ps1 <status|stop|check> <port>
|
|
#
|
|
# "check" liefert nur den Exitcode (0 = Server lauscht, 1 = nicht)
|
|
# und keine Ausgabe - fuer die Pruefung nach dem Start.
|
|
#
|
|
# Verwaiste Socket-Eintraege (Listener, deren Prozess nicht mehr
|
|
# existiert - passiert nach abgestuerzten Reload-Kindprozessen)
|
|
# werden ueberall ignoriert.
|
|
# ================================================================
|
|
param(
|
|
[Parameter(Mandatory = $true)][ValidateSet('status', 'stop', 'check')]
|
|
[string]$Aktion,
|
|
[int]$Port = 8000
|
|
)
|
|
|
|
function Lebende-Listener([int]$p) {
|
|
try {
|
|
Get-NetTCPConnection -LocalPort $p -State Listen -ErrorAction Stop |
|
|
Where-Object { Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue }
|
|
} catch { @() }
|
|
}
|
|
|
|
function Uvicorn-Prozesse {
|
|
Get-CimInstance Win32_Process -Filter "Name like 'python%'" |
|
|
Where-Object { $_.CommandLine -match 'uvicorn main:app' }
|
|
}
|
|
|
|
switch ($Aktion) {
|
|
|
|
'check' {
|
|
if (Lebende-Listener $Port) { exit 0 } else { exit 1 }
|
|
}
|
|
|
|
'status' {
|
|
$l = Lebende-Listener $Port | Select-Object -First 1
|
|
if ($l) {
|
|
"LAEUFT: http://localhost:$Port (Listener-PID $($l.OwningProcess))"
|
|
foreach ($e in Uvicorn-Prozesse) { " uvicorn-Prozess: PID $($e.ProcessId)" }
|
|
exit 0
|
|
} else {
|
|
"GESTOPPT: kein Server auf Port $Port"
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
'stop' {
|
|
$gefunden = $false
|
|
$alle = Get-CimInstance Win32_Process -Filter "Name like 'python%'"
|
|
$reloaderPids = @()
|
|
foreach ($e in ($alle | Where-Object { $_.CommandLine -match 'uvicorn main:app' })) {
|
|
$gefunden = $true
|
|
$reloaderPids += $e.ProcessId
|
|
# erst die Kindprozesse (Reload-Worker), dann den Reloader selbst
|
|
$alle | Where-Object { $_.ParentProcessId -eq $e.ProcessId } | ForEach-Object {
|
|
Stop-Process -Id $_.ProcessId -Force -Confirm:$false -ErrorAction SilentlyContinue
|
|
}
|
|
Stop-Process -Id $e.ProcessId -Force -Confirm:$false -ErrorAction SilentlyContinue
|
|
}
|
|
# Zombie-Jagd: uvicorn-Reload-Worker sind multiprocessing-Spawn-Kinder
|
|
# ("spawn_main(parent_pid=N, ...)"). Stirbt ihr Reloader unsanft,
|
|
# ueberleben sie MIT geerbtem Server-Socket und bedienen den Port
|
|
# unsichtbar weiter (weder "uvicorn" in der Kommandozeile noch
|
|
# Eintrag als Socket-Besitzer!). Erkennung: spawn_main-Prozess,
|
|
# dessen parent_pid tot oder ein eben beendeter Reloader ist.
|
|
foreach ($k in ($alle | Where-Object { $_.CommandLine -match 'multiprocessing.spawn.*spawn_main' })) {
|
|
if ($k.CommandLine -match 'parent_pid=(\d+)') {
|
|
$eltern = [int]$Matches[1]
|
|
$elternTot = -not (Get-Process -Id $eltern -ErrorAction SilentlyContinue)
|
|
if ($elternTot -or ($reloaderPids -contains $eltern)) {
|
|
$gefunden = $true
|
|
Stop-Process -Id $k.ProcessId -Force -Confirm:$false -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
}
|
|
# Nachzuegler: alles Lebende, das den Port noch haelt
|
|
Lebende-Listener $Port | ForEach-Object {
|
|
$gefunden = $true
|
|
Stop-Process -Id $_.OwningProcess -Force -Confirm:$false -ErrorAction SilentlyContinue
|
|
}
|
|
if ($gefunden) { 'Beendet.' } else { 'Es lief nichts.' }
|
|
exit 0
|
|
}
|
|
}
|