Files
Aether/backend/pkg/bg/bg.go
T
marcandClaude Opus 5 c26bcba012 fix(bg): Hintergrundarbeit reisst den Prozess nicht mehr mit
Das Vorschaubild entstand in einer nackten Goroutine. Chis Recoverer haengt
am Anfragebehandler und sieht davon nichts -- eine Panik im Bilddekodierer
nahm den ganzen Go-Prozess mit, ausgeloest durch einen gewoehnlichen
Upload. Die Bibliothek ist seit ef60497 aktuell; das schloss **diese**
Luecke. Dies hier schliesst die **Gattung**.

pkg/bg mit zwei Funktionen, und der Unterschied ist keine Feinheit:

* bg.Go(name, fn)  -- Goroutine, die eine Panik ueberlebt
* bg.Run(name, fn) -- dasselbe ohne eigene Goroutine, fuer Schleifen

Faengt man eine Panik um den **ganzen** Arbeiter ab, ueberlebt der Prozess
-- aber der Arbeiter ist tot, und von da an wird still keine Datei mehr
erkannt. Der OCR-Arbeiter sichert deshalb jeden **Auftrag** einzeln ab.

Umgestellt: Vorschaubild, Bestand nachtragen, Freigabe-Zaehler,
Speicherbereinigung, OCR-Arbeiter. Eine nackte Goroutine bleibt mit
Begruendung im Code -- die Signalbehandlung; ein recover braechte dort
nichts, weil main ohnehin wartete.

Aufgefangene Paniken werden mit Stapel und Herkunft protokolliert. Vier
Tests, darunter der wichtige: Eine Schleife laeuft nach einer Panik im
dritten Durchgang weiter.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 18:29:02 +02:00

54 lines
2.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package bg startet Hintergrundarbeit, die den Prozess nicht mitreißen kann.
//
// **Der Anlass ist gemessen, nicht theoretisch.** Aether erzeugt das
// Vorschaubild einer hochgeladenen Datei in einer eigenen Goroutine. Chis
// `Recoverer` hängt am Anfragebehandler und sieht davon nichts – eine Panik
// dort nimmt den **ganzen Go-Prozess** mit. Am 12.09.2026 stand dafür sogar
// eine passende Lücke offen (GO-2026-5061, Panik im WebP-Dekodierer): Ein
// gewöhnlicher Bild-Upload hätte den Server umgelegt.
//
// Die Bibliothek zu aktualisieren schließt **diese** Lücke. Diese Datei
// schließt die **Gattung**: Bilddekodierer, Fremdformate und externe Programme
// sind Felder, in denen regelmäßig etwas gefunden wird, und keines davon darf
// über einen Weg erreichbar sein, an dessen Ende der Prozess stirbt.
//
// Was hier *nicht* passiert: Fehler verschlucken. Eine aufgefangene Panik wird
// mit Stapel protokolliert. Sie ist ein Fehler und bleibt einer – sie reißt
// nur nichts mehr mit.
package bg
import (
"runtime/debug"
"github.com/rs/zerolog/log"
)
// Go startet fn in einer Goroutine, die eine Panik überlebt.
//
// name steht im Logeintrag und sollte sagen, *was* da lief ("Vorschaubild",
// "Texterkennung") – eine Zeile „panic recovered" ohne Herkunft hilft um drei
// Uhr nachts niemandem.
func Go(name string, fn func()) {
go Run(name, fn)
}
// Run ist dasselbe ohne eigene Goroutine: für Schleifen, in denen **ein**
// Durchgang scheitern darf, ohne dass die Schleife endet.
//
// Der Unterschied ist keine Feinheit. Fängt man eine Panik um den ganzen
// Arbeiter herum ab, überlebt der Prozess – aber der Arbeiter ist tot, und
// von da an wird still keine Datei mehr erkannt. Fängt man sie um den
// einzelnen Auftrag ab, verliert man den einen Auftrag und macht weiter.
func Run(name string, fn func()) {
defer func() {
if r := recover(); r != nil {
log.Error().
Str("wo", name).
Interface("panik", r).
Str("stapel", string(debug.Stack())).
Msg("Hintergrundarbeit abgestürzt – aufgefangen")
}
}()
fn()
}