fix: Crash-Robustheit + Performance in Backend und Frontend härten
Backend: recover() in allen langlebigen Goroutinen (neues internal/safego- Paket), MIME-Multipart-Tiefenlimit gegen Stack-Overflow, IMAP-Zeilenlängen- und FETCH-Result-Limits gegen OOM, MBOX-Buffer-Aliasing-Bug (Datenkorruption beim Import), ungeprüfte Type Assertions abgesichert, Data Race im API-Key-Rate-Limiter behoben, SMTP-Session-Panic führt jetzt zu 451-Retry statt Prozessabsturz. Performance: O(n²)-String-Concat in Mailparser und IMAP-Parser durch strings.Builder ersetzt. Frontend: Error Boundaries für Root und Mail-Detailansicht ergänzt (gab es vorher nicht), zahlreiche Guards gegen nil-Slices aus dem Backend-JSON die sonst .map()/.length-Crashes/White-Screens auslösten, defekte JSON-Antworten in api/core.ts abgefangen, zwei React-Key-Bugs bei löschbaren Listen korrigiert. Verifiziert auf 192.168.1.132: Build und Tests der geänderten Pakete fehlerfrei, keine Regressionen gegenüber vorbestehendem Stand. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019j28kGcaJAhBnrYX34hGdt
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
0fa4fad49d
commit
798cb2817c
@@ -183,7 +183,11 @@ func runImport(args []string) {
|
||||
|
||||
var messages [][]byte
|
||||
if fe.isMbox {
|
||||
messages = mailparser.SplitMbox(raw)
|
||||
var splitErr error
|
||||
messages, splitErr = mailparser.SplitMboxErr(raw)
|
||||
if splitErr != nil {
|
||||
fmt.Fprintf(os.Stderr, "warning: %s: %v\n", fe.path, splitErr)
|
||||
}
|
||||
if len(messages) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
+14
-7
@@ -32,6 +32,7 @@ import (
|
||||
"archivmail/internal/ocr"
|
||||
pop3store "archivmail/internal/pop3"
|
||||
"archivmail/internal/reconciliation"
|
||||
"archivmail/internal/safego"
|
||||
"archivmail/internal/smtpoutconfig"
|
||||
"archivmail/internal/smtpd"
|
||||
"archivmail/internal/storage"
|
||||
@@ -246,7 +247,7 @@ func main() {
|
||||
// queries only return genuinely outstanding jobs.
|
||||
// PROJ-58: skipped in batch mode — the cron job drains the backlog instead.
|
||||
if !cfg.OCR.BatchMode {
|
||||
go func() {
|
||||
safego.Go(logger, "ocr boot-resume", func() {
|
||||
ctx := context.Background()
|
||||
queueCap := 1000 // matches ocr.Options.QueueSize above
|
||||
processed := 0
|
||||
@@ -281,7 +282,7 @@ func main() {
|
||||
logger.Info("ocr boot-resume: enqueued batch",
|
||||
"batch", len(pending), "total_so_far", processed)
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
|
||||
// User store
|
||||
@@ -519,11 +520,15 @@ func main() {
|
||||
if cfg.OCR.BatchMode {
|
||||
backfillOCR = nil
|
||||
}
|
||||
go runBackfill(context.Background(), mailStore, idx, tenantWorker, logger, backfillOCR)
|
||||
safego.Go(logger, "backfill", func() {
|
||||
runBackfill(context.Background(), mailStore, idx, tenantWorker, logger, backfillOCR)
|
||||
})
|
||||
}
|
||||
|
||||
// Background integrity verification — runs every 5 minutes
|
||||
go runIntegrityCheck(context.Background(), mailStore, logger)
|
||||
safego.Go(logger, "integrity check", func() {
|
||||
runIntegrityCheck(context.Background(), mailStore, logger)
|
||||
})
|
||||
|
||||
// Start HTTP API
|
||||
go func() {
|
||||
@@ -538,11 +543,13 @@ func main() {
|
||||
// (which would otherwise drop SMTP/IMAP connections unnecessarily).
|
||||
reload := make(chan os.Signal, 1)
|
||||
signal.Notify(reload, syscall.SIGHUP)
|
||||
go func() {
|
||||
safego.Go(logger, "sighup reload", func() {
|
||||
for range reload {
|
||||
reloadOCRPauseWindow(*configPath, ocrWorker, logger)
|
||||
safego.Run(logger, "ocr pause-window reload", func() {
|
||||
reloadOCRPauseWindow(*configPath, ocrWorker, logger)
|
||||
})
|
||||
}
|
||||
}()
|
||||
})
|
||||
|
||||
// Graceful shutdown
|
||||
quit := make(chan os.Signal, 1)
|
||||
|
||||
Reference in New Issue
Block a user