feat: add import status tracking to MassImportService

The async import previously ran fire-and-forget with no way to know
if it succeeded, failed, or was still running.

- Add ImportStatus record (state, message, processed count, startedAt)
  and a volatile currentStatus field updated throughout the async run
- POST /api/admin/trigger-import now returns 202 Accepted with initial status
- GET /api/admin/import-status lets callers poll for the current state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-03-15 12:37:09 +01:00
parent 82974170e9
commit ace57e9fc7
2 changed files with 22 additions and 13 deletions

View File

@@ -4,6 +4,7 @@ import org.raddatz.familienarchiv.security.Permission;
import org.raddatz.familienarchiv.security.RequirePermission;
import org.raddatz.familienarchiv.service.MassImportService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -19,8 +20,13 @@ public class AdminController {
private final MassImportService massImportService;
@PostMapping("/trigger-import")
public ResponseEntity<String> triggerMassImport() {
public ResponseEntity<MassImportService.ImportStatus> triggerMassImport() {
massImportService.runImportAsync();
return ResponseEntity.ok("Massenimport gestartet.");
return ResponseEntity.accepted().body(massImportService.getStatus());
}
@GetMapping("/import-status")
public ResponseEntity<MassImportService.ImportStatus> importStatus() {
return ResponseEntity.ok(massImportService.getStatus());
}
}

View File

@@ -22,6 +22,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Optional;
import java.util.UUID;
@@ -32,6 +33,16 @@ import java.util.stream.Stream;
@Slf4j
public class MassImportService {
public enum State { IDLE, RUNNING, DONE, FAILED }
public record ImportStatus(State state, String message, int processed, LocalDateTime startedAt) {}
private volatile ImportStatus currentStatus = new ImportStatus(State.IDLE, "Kein Import gestartet.", 0, null);
public ImportStatus getStatus() {
return currentStatus;
}
private final DocumentRepository documentRepository;
private final S3Client s3Client;
@@ -52,23 +63,15 @@ public class MassImportService {
@Async
public void runImportAsync() {
runImport();
}
public String runImport() {
currentStatus = new ImportStatus(State.RUNNING, "Import läuft...", 0, LocalDateTime.now());
try {
// 1. Excel finden
File excelFile = findExcelFile();
log.info("Starte Massenimport aus: {}", excelFile.getAbsolutePath());
// 2. Excel verarbeiten
int processed = processExcel(excelFile);
return "Import abgeschlossen. " + processed + " Dokumente verarbeitet.";
currentStatus = new ImportStatus(State.DONE, "Import abgeschlossen. " + processed + " Dokumente verarbeitet.", processed, currentStatus.startedAt());
} catch (Exception e) {
log.error("Massenimport fehlgeschlagen", e);
return "Fehler: " + e.getMessage();
currentStatus = new ImportStatus(State.FAILED, "Fehler: " + e.getMessage(), 0, currentStatus.startedAt());
}
}