fix(ocr): resume polling on page reload + track single-doc job status
Single-document OCR now creates an OcrJobDocument row so
GET /api/documents/{id}/ocr-status can find running jobs.
OcrAsyncRunner updates the job document status (RUNNING → DONE/FAILED).
Frontend checks OCR status when entering transcription mode —
if a job is running, resumes polling and shows the spinner.
Refs #226
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -39,16 +39,32 @@ public class OcrAsyncRunner {
|
||||
job.setStatus(OcrJobStatus.RUNNING);
|
||||
ocrJobRepository.save(job);
|
||||
|
||||
OcrJobDocument jobDoc = ocrJobDocumentRepository.findByJobIdAndDocumentId(jobId, documentId)
|
||||
.orElse(null);
|
||||
if (jobDoc != null) {
|
||||
jobDoc.setStatus(OcrDocumentStatus.RUNNING);
|
||||
ocrJobDocumentRepository.save(jobDoc);
|
||||
}
|
||||
|
||||
Document doc = documentService.getDocumentById(documentId);
|
||||
|
||||
try {
|
||||
processDocument(documentId, doc, userId);
|
||||
job.setStatus(OcrJobStatus.DONE);
|
||||
job.setProcessedDocuments(1);
|
||||
if (jobDoc != null) {
|
||||
jobDoc.setStatus(OcrDocumentStatus.DONE);
|
||||
ocrJobDocumentRepository.save(jobDoc);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("OCR processing failed for document {}", documentId, e);
|
||||
job.setStatus(OcrJobStatus.FAILED);
|
||||
job.setErrorCount(1);
|
||||
if (jobDoc != null) {
|
||||
jobDoc.setStatus(OcrDocumentStatus.FAILED);
|
||||
jobDoc.setErrorMessage(e.getMessage());
|
||||
ocrJobDocumentRepository.save(jobDoc);
|
||||
}
|
||||
}
|
||||
|
||||
ocrJobRepository.save(job);
|
||||
|
||||
@@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.raddatz.familienarchiv.exception.DomainException;
|
||||
import org.raddatz.familienarchiv.exception.ErrorCode;
|
||||
import org.raddatz.familienarchiv.model.*;
|
||||
import org.raddatz.familienarchiv.repository.OcrJobDocumentRepository;
|
||||
import org.raddatz.familienarchiv.repository.OcrJobRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -18,6 +19,7 @@ public class OcrService {
|
||||
private final OcrHealthClient ocrHealthClient;
|
||||
private final DocumentService documentService;
|
||||
private final OcrJobRepository ocrJobRepository;
|
||||
private final OcrJobDocumentRepository ocrJobDocumentRepository;
|
||||
private final OcrAsyncRunner ocrAsyncRunner;
|
||||
|
||||
public UUID startOcr(UUID documentId, ScriptType scriptTypeOverride, UUID userId) {
|
||||
@@ -44,6 +46,13 @@ public class OcrService {
|
||||
.build();
|
||||
job = ocrJobRepository.save(job);
|
||||
|
||||
OcrJobDocument jobDoc = OcrJobDocument.builder()
|
||||
.jobId(job.getId())
|
||||
.documentId(documentId)
|
||||
.status(OcrDocumentStatus.PENDING)
|
||||
.build();
|
||||
ocrJobDocumentRepository.save(jobDoc);
|
||||
|
||||
ocrAsyncRunner.runSingleDocument(job.getId(), documentId, userId);
|
||||
return job.getId();
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.raddatz.familienarchiv.exception.DomainException;
|
||||
import org.raddatz.familienarchiv.exception.ErrorCode;
|
||||
import org.raddatz.familienarchiv.model.*;
|
||||
import org.raddatz.familienarchiv.repository.OcrJobDocumentRepository;
|
||||
import org.raddatz.familienarchiv.repository.OcrJobRepository;
|
||||
|
||||
import java.util.UUID;
|
||||
@@ -24,6 +25,7 @@ class OcrServiceTest {
|
||||
@Mock OcrHealthClient ocrHealthClient;
|
||||
@Mock DocumentService documentService;
|
||||
@Mock OcrJobRepository ocrJobRepository;
|
||||
@Mock OcrJobDocumentRepository ocrJobDocumentRepository;
|
||||
@Mock OcrAsyncRunner ocrAsyncRunner;
|
||||
|
||||
@InjectMocks OcrService ocrService;
|
||||
|
||||
Reference in New Issue
Block a user