Erste von fuenf Erweiterungen aus M6 - Nachruestung eines in M2 bewusst offen gelassenen
Punkts: PolicyApplicationDraft (Ersatz fuer den zustandsbehafteten
PolicyApplicationWizardBean) konnte bislang unbegrenzt lange im Status STARTED,
COVERAGE_SUBMITTED oder UNDERWRITING_SUBMITTED verharren, wenn ein Kunde den
Online-Antragsprozess abbricht - anders als beim EJB-Original, dessen @Stateful-Bean nach
Session-Timeout automatisch vom Container entfernt wurde. Die bewusste Abkehr von
Session-Affinitaet (siehe 02-component-mapping.md) hat diesen Cleanup-Mechanismus
mitgenommen, ohne ihn zu ersetzen.
Ohne Cleanup wachsen liegen gebliebene Entwuerfe unbegrenzt in der Datenbank - kein
funktionaler Fehler, aber ein Daten- und Reporting-Problem (z. B. verzerrte
"Antraege in Bearbeitung"-Zaehler). Ein @Scheduled-Job ist die naheliegende
Spring-Entsprechung zum weggefallenen Session-Timeout: statt impliziter
Container-Verwaltung eine explizite, fachlich benannte Aufraeumregel.
PolicyApplicationDraft.lastModifiedAt (Instant) - wird in jeder
zustandsaendernden Methode (submitCoverageDetails, submitUnderwritingAnswers,
markBound, markCancelled) sowie im Konstruktor aktualisiert.PolicyApplicationDraftRepository.findByCurrentStepInAndLastModifiedAtBefore(...) - liefert
alle Entwuerfe in einem der drei nicht-terminalen Schritte, deren letzte Aenderung laenger als
der Schwellwert zurueckliegt.PolicyDraftCleanupScheduler (@Component, @Scheduled(fixedDelay = 5 Minuten)):
markiert alle so gefundenen Entwuerfe als CANCELLED. Schwellwert STALE_THRESHOLD = 30
Minuten - bewusst kurz gewaehlt fuer dieses Lernprojekt, in einer echten Landschaft waere das
ein konfigurierbarer Wert.PolicyDraftCleanupSchedulerTest (Mockito, containerfrei): zwei Tests - (1) ein Entwurf
jenseits des Schwellwerts wird gefunden, auf CANCELLED gesetzt und gespeichert, (2) ein
frischer Entwurf innerhalb des Schwellwerts wird von der Repository-Query gar nicht erst
zurueckgegeben und bleibt unangetastet. Kein Docker/Zeit-Mocking noetig, da die
Schwellwert-Berechnung (Instant.now().minus(STALE_THRESHOLD)) an der Repository-Query-Grenze
getestet wird, nicht ueber echtes Warten.
Kein produktionsreifer Verteilte-Cluster-Schutz (z. B. Shedlock/ein verteiltes Lock) - bei
mehreren parallel laufenden Pod-Instanzen auf OpenShift wuerde jede Instanz denselben
@Scheduled-Job unabhaengig ausfuehren. Fuer dieses Lernprojekt mit einer Replika
akzeptiert; bei echtem horizontalem Scale-out waere ein verteilter Scheduler-Lock der
naechste Schritt.