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>
This commit is contained in:
1 parent
89f0817dcb
commit
c26bcba012
7 files changed
+156
-17
No files matched your search
@@ -38,6 +38,7 @@ import (
|
||||
"aether/internal/tags"
|
||||
"aether/internal/thumbnails"
|
||||
appwebdav "aether/internal/webdav"
|
||||
"aether/pkg/bg"
|
||||
"aether/pkg/config"
|
||||
appdb "aether/pkg/db"
|
||||
"aether/pkg/middleware"
|
||||
@@ -176,13 +177,16 @@ func main() {
|
||||
Timeout: cfg.OCRTimeout,
|
||||
TmpDir: cfg.TmpPath,
|
||||
}, log.Logger)
|
||||
go worker.Run(ctx)
|
||||
// Die Schleife darin sichert jeden Auftrag einzeln ab (siehe
|
||||
// worker.Run). Diese Hülle fängt, was **davor** passiert – das
|
||||
// Aufräumen der Zwischendateien beim Start.
|
||||
bg.Go("OCR-Arbeiter", func() { worker.Run(ctx) })
|
||||
|
||||
// Bestand nachtragen: Beim ersten Start nach dem Einbau hat noch
|
||||
// keine einzige Datei einen Auftrag. Ohne das bliebe alles
|
||||
// unauffindbar, was vorher hochgeladen wurde – und das ist am
|
||||
// Anfang der gesamte Bestand.
|
||||
go func() {
|
||||
bg.Go("Bestand nachtragen", func() {
|
||||
n, err := docStore.EnqueueMissing(ctx, 5000)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msg("Bestand nachtragen fehlgeschlagen")
|
||||
@@ -205,7 +209,7 @@ func main() {
|
||||
log.Info().Int("files", m).Int("version", documents.ExtractVersion).
|
||||
Msg("veraltete Texteintraege zur erneuten Erkennung eingeplant")
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -633,6 +637,10 @@ func main() {
|
||||
done := make(chan struct{})
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
// Die einzige nackte Goroutine, die bleibt – und das mit Absicht: Sie
|
||||
// wartet auf ein Signal und schließt `done`. Ein recover brächte hier
|
||||
// nichts, denn stürbe sie vor dem close, wartete main ohnehin für immer.
|
||||
// Sie berührt außerdem keine fremden Daten.
|
||||
go func() {
|
||||
<-quit
|
||||
log.Info().Msg("shutting down...")
|
||||
@@ -698,8 +706,14 @@ func afterUpload(fh *files.Handler, fileStore *files.Store, st storage.Storage,
|
||||
return
|
||||
}
|
||||
|
||||
// Generate thumbnail in background – non-fatal if it fails.
|
||||
go func() {
|
||||
// Vorschaubild im Hintergrund – ein Fehlschlag ist nicht schlimm.
|
||||
//
|
||||
// **Über bg.Go, nicht als nackte Goroutine.** Hier wird eine
|
||||
// hochgeladene Datei dekodiert. Chis Recoverer hängt am
|
||||
// Anfragebehandler und sieht davon nichts; eine Panik im Dekodierer
|
||||
// nähme sonst den ganzen Prozess mit – ausgelöst durch einen
|
||||
// gewöhnlichen Upload.
|
||||
bg.Go("Vorschaubild", func() {
|
||||
ctx := context.Background()
|
||||
f, err := fileStore.GetFileByID(ctx, created.ID)
|
||||
if err != nil {
|
||||
@@ -715,7 +729,7 @@ func afterUpload(fh *files.Handler, fileStore *files.Store, st storage.Storage,
|
||||
return
|
||||
}
|
||||
_ = fileStore.UpdateThumbnail(ctx, created.ID, true)
|
||||
}()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user