From 55088354ab6ea31710d499649a2a3784f54a16aa Mon Sep 17 00:00:00 2001 From: Marcus van Elst Date: Thu, 23 Apr 2026 15:00:22 +0200 Subject: [PATCH] =?UTF-8?q?Diagnoselogs=20und=20Test=20f=C3=BCr=20DB-Reset?= =?UTF-8?q?-Verifikation=20(FAILED=5FFINAL)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - [TEMP-TRACE] INFO-Logs in SqliteDocumentRecordRepositoryAdapter: deleteByFingerprint() zeigt Fingerprint, jdbcUrl und rowsAffected; findByFingerprint() zeigt Fingerprint, jdbcUrl und Lookup-Ergebnis - [TEMP-TRACE] Log in DocumentProcessingCoordinator.processDeferredOutcome() zeigt Fingerprint und Lookup-Ergebnis-Typ nach DB-Abfrage - Bestehende [TEMP-TRACE] Logs in GuiBatchRunCoordinator und SqliteUnitOfWorkAdapter sind ebenfalls enthalten - Neuer Test resetDocumentByFingerprint_deletesFailedFinalRecord_resultIsDocumentUnknown: legt FAILED_FINAL-Datensatz in echter SQLite-DB an, führt Reset aus und prüft, dass der Datensatz danach DocumentUnknown zurückliefert Co-Authored-By: Claude Haiku 4.5 --- .../gui/batchrun/GuiBatchRunCoordinator.java | 6 +++ ...SqliteDocumentRecordRepositoryAdapter.java | 12 ++++-- .../out/sqlite/SqliteUnitOfWorkAdapter.java | 4 ++ .../sqlite/SqliteUnitOfWorkAdapterTest.java | 42 +++++++++++++++++++ .../DocumentProcessingCoordinator.java | 2 + 5 files changed, 62 insertions(+), 4 deletions(-) diff --git a/pdf-umbenenner-adapter-in-gui/src/main/java/de/gecheckt/pdf/umbenenner/adapter/in/gui/batchrun/GuiBatchRunCoordinator.java b/pdf-umbenenner-adapter-in-gui/src/main/java/de/gecheckt/pdf/umbenenner/adapter/in/gui/batchrun/GuiBatchRunCoordinator.java index 9639fcc..bbe16b7 100644 --- a/pdf-umbenenner-adapter-in-gui/src/main/java/de/gecheckt/pdf/umbenenner/adapter/in/gui/batchrun/GuiBatchRunCoordinator.java +++ b/pdf-umbenenner-adapter-in-gui/src/main/java/de/gecheckt/pdf/umbenenner/adapter/in/gui/batchrun/GuiBatchRunCoordinator.java @@ -298,7 +298,13 @@ public final class GuiBatchRunCoordinator { // Reset the database status synchronously before starting the mini-run. // This ensures that documents are not skipped due to FAILED_FINAL or other // terminal states. + LOG.info("[TEMP-TRACE] startReprocessing: Konfiguration={}, Fingerprints={}", + configFilePath, fingerprintFilter.stream() + .map(f -> f.sha256Hex().substring(0, 8) + "…") + .collect(java.util.stream.Collectors.joining(", "))); ResetDocumentStatusResult resetResult = resetPort.reset(configFilePath, fingerprintFilter); + LOG.info("[TEMP-TRACE] startReprocessing: Reset-Ergebnis: {} erfolgreich, {} fehlgeschlagen; Fehler={}", + resetResult.successCount(), resetResult.failureCount(), resetResult.failures()); if (resetResult.successCount() == 0) { LOG.warn("GUI-Reprocessing: Reset für alle {} Dokumente fehlgeschlagen; " + "Mini-Lauf wird nicht gestartet.", fingerprintFilter.size()); diff --git a/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteDocumentRecordRepositoryAdapter.java b/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteDocumentRecordRepositoryAdapter.java index b8c4f95..02d2f22 100644 --- a/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteDocumentRecordRepositoryAdapter.java +++ b/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteDocumentRecordRepositoryAdapter.java @@ -101,16 +101,20 @@ public class SqliteDocumentRecordRepositoryAdapter implements DocumentRecordRepo if (rs.next()) { // Document exists - map to appropriate result type based on status DocumentRecord record = mapResultSetToDocumentRecord(rs, fingerprint); - - return switch (record.overallStatus()) { + DocumentRecordLookupResult result = switch (record.overallStatus()) { case SUCCESS -> new DocumentTerminalSuccess(record); case FAILED_FINAL -> new DocumentTerminalFinalFailure(record); case READY_FOR_AI, PROPOSAL_READY, PROCESSING, FAILED_RETRYABLE, SKIPPED_ALREADY_PROCESSED, SKIPPED_FINAL_FAILURE -> new DocumentKnownProcessable(record); }; + logger.info("[TEMP-TRACE] findByFingerprint: fingerprint={}, jdbcUrl={}, Ergebnis={}", + fingerprint.sha256Hex(), jdbcUrl, result.getClass().getSimpleName()); + return result; } else { // Document not found + logger.info("[TEMP-TRACE] findByFingerprint: fingerprint={}, jdbcUrl={}, Ergebnis=DocumentUnknown", + fingerprint.sha256Hex(), jdbcUrl); return new DocumentUnknown(); } } @@ -318,8 +322,8 @@ public class SqliteDocumentRecordRepositoryAdapter implements DocumentRecordRepo statement.setString(1, fingerprint.sha256Hex()); int rowsAffected = statement.executeUpdate(); - logger.debug("Deleted {} document_record row(s) for fingerprint: {}", - rowsAffected, fingerprint.sha256Hex()); + logger.info("[TEMP-TRACE] deleteByFingerprint: fingerprint={}, jdbcUrl={}, rowsAffected={}", + fingerprint.sha256Hex(), jdbcUrl, rowsAffected); } catch (SQLException e) { String message = "Failed to delete document record for fingerprint '" diff --git a/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteUnitOfWorkAdapter.java b/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteUnitOfWorkAdapter.java index d113ac8..99cd12c 100644 --- a/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteUnitOfWorkAdapter.java +++ b/pdf-umbenenner-adapter-out/src/main/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteUnitOfWorkAdapter.java @@ -178,6 +178,8 @@ public class SqliteUnitOfWorkAdapter implements UnitOfWorkPort { */ @Override public void resetDocumentByFingerprint(DocumentFingerprint fingerprint) { + logger.info("[TEMP-TRACE] resetDocumentByFingerprint: Fingerprint={}, jdbcUrl={}", + fingerprint.sha256Hex(), jdbcUrl); // Delete attempts first (FK constraint: processing_attempt → document_record) SqliteProcessingAttemptRepositoryAdapter attemptRepo = new SqliteProcessingAttemptRepositoryAdapter(jdbcUrl) { @@ -197,6 +199,8 @@ public class SqliteUnitOfWorkAdapter implements UnitOfWorkPort { } }; recordRepo.deleteByFingerprint(fingerprint); + logger.info("[TEMP-TRACE] resetDocumentByFingerprint: Löschung abgeschlossen für Fingerprint={}", + fingerprint.sha256Hex()); } } } \ No newline at end of file diff --git a/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteUnitOfWorkAdapterTest.java b/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteUnitOfWorkAdapterTest.java index f93cfe8..aeff06b 100644 --- a/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteUnitOfWorkAdapterTest.java +++ b/pdf-umbenenner-adapter-out/src/test/java/de/gecheckt/pdf/umbenenner/adapter/out/sqlite/SqliteUnitOfWorkAdapterTest.java @@ -16,6 +16,7 @@ import org.junit.jupiter.api.io.TempDir; import de.gecheckt.pdf.umbenenner.application.port.out.DocumentPersistenceException; import de.gecheckt.pdf.umbenenner.application.port.out.DocumentRecord; +import de.gecheckt.pdf.umbenenner.application.port.out.DocumentTerminalFinalFailure; import de.gecheckt.pdf.umbenenner.application.port.out.DocumentUnknown; import de.gecheckt.pdf.umbenenner.application.port.out.FailureCounters; import de.gecheckt.pdf.umbenenner.application.port.out.ProcessingAttempt; @@ -295,4 +296,45 @@ class SqliteUnitOfWorkAdapterTest { assertThat(docRepository.findByFingerprint(fingerprint)).isInstanceOf(DocumentUnknown.class); } + /** + * Stellt sicher, dass ein Dokument mit Status FAILED_FINAL nach dem Reset nicht mehr + * auffindbar ist. Dieser Test deckt den Reprocessing-Pfad ab, bei dem der GUI-Nutzer + * ein final fehlgeschlagenes Dokument erneut verarbeiten lässt. + */ + @Test + void resetDocumentByFingerprint_deletesFailedFinalRecord_resultIsDocumentUnknown() { + DocumentFingerprint fingerprint = new DocumentFingerprint( + "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"); + Instant now = Instant.now().truncatedTo(ChronoUnit.MICROS); + DocumentRecord record = new DocumentRecord( + fingerprint, + new SourceDocumentLocator("/source/failed-final.pdf"), + "failed-final.pdf", + ProcessingStatus.FAILED_FINAL, + new FailureCounters(2, 0), + now.minusSeconds(10), + null, + now.minusSeconds(20), + now, + null, + null + ); + + SqliteDocumentRecordRepositoryAdapter docRepository = + new SqliteDocumentRecordRepositoryAdapter(jdbcUrl); + + // Datensatz mit FAILED_FINAL anlegen + unitOfWorkAdapter.executeInTransaction(txOps -> txOps.createDocumentRecord(record)); + assertThat(docRepository.findByFingerprint(fingerprint)) + .isInstanceOf(DocumentTerminalFinalFailure.class); + + // Reset ausführen + unitOfWorkAdapter.executeInTransaction(txOps -> + txOps.resetDocumentByFingerprint(fingerprint)); + + // Nach dem Reset muss der Datensatz vollständig entfernt sein + assertThat(docRepository.findByFingerprint(fingerprint)) + .isInstanceOf(DocumentUnknown.class); + } + } diff --git a/pdf-umbenenner-application/src/main/java/de/gecheckt/pdf/umbenenner/application/service/DocumentProcessingCoordinator.java b/pdf-umbenenner-application/src/main/java/de/gecheckt/pdf/umbenenner/application/service/DocumentProcessingCoordinator.java index aeb2e8f..f915f1d 100644 --- a/pdf-umbenenner-application/src/main/java/de/gecheckt/pdf/umbenenner/application/service/DocumentProcessingCoordinator.java +++ b/pdf-umbenenner-application/src/main/java/de/gecheckt/pdf/umbenenner/application/service/DocumentProcessingCoordinator.java @@ -351,6 +351,8 @@ public class DocumentProcessingCoordinator { // Step 1: Load the document master record DocumentRecordLookupResult lookupResult = documentRecordRepository.findByFingerprint(fingerprint); + logger.info("[TEMP-TRACE] processDeferredOutcome: Fingerprint={}, Lookup-Ergebnis={}", + fingerprint.sha256Hex(), lookupResult.getClass().getSimpleName()); // Step 2: Handle persistence lookup failure if (lookupResult instanceof PersistenceLookupTechnicalFailure failure) {