RED-6072 - As Operation I want to see why files are in an ERROR state #3

Merged
corina.olariu.ext1 merged 1 commits from RED-6072-timestamp into master 2023-06-14 09:40:35 +02:00
13 changed files with 48 additions and 16 deletions

View File

@ -1,5 +1,8 @@
package com.iqser.red.service.persistence.v1.internal.api.controller;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
@ -34,7 +37,7 @@ public class FileStatusProcessingUpdateInternalController implements FileStatusP
public void preprocessingFailed(@PathVariable(DOSSIER_ID_PARAM) String dossierId, @PathVariable(FILE_ID) String fileId) {
fileStatusProcessingUpdateService.preprocessingFailed(dossierId, fileId, new FileErrorInfo("preprocessing failed",
MessagingConfiguration.PRE_PROCESSING_DLQ, "pdftron-service"));
MessagingConfiguration.PRE_PROCESSING_DLQ, "pdftron-service", OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)));
}
@ -85,7 +88,7 @@ public class FileStatusProcessingUpdateInternalController implements FileStatusP
public void ocrFailed(@PathVariable(DOSSIER_ID_PARAM) String dossierId, @PathVariable(FILE_ID) String fileId) {
fileStatusProcessingUpdateService.ocrFailed(dossierId, fileId, new FileErrorInfo("ocr failed",
MessagingConfiguration.OCR_DLQ, "ocr-service"));
MessagingConfiguration.OCR_DLQ, "ocr-service", OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)));
}
@ -111,7 +114,7 @@ public class FileStatusProcessingUpdateInternalController implements FileStatusP
public void indexingFailed(@PathVariable(DOSSIER_ID_PARAM) String dossierId, @PathVariable(FILE_ID) String fileId) {
fileStatusProcessingUpdateService.indexingFailed(dossierId, fileId, new FileErrorInfo("indexing failed",
MessagingConfiguration.INDEXING_DQL, "search-service"));
MessagingConfiguration.INDEXING_DQL, "search-service", OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)));
}
public void indexingFailed(@PathVariable(DOSSIER_ID_PARAM) String dossierId, @PathVariable(FILE_ID) String fileId,

View File

@ -186,6 +186,8 @@ public class FileEntity {
private String errorQueue;
@Column
private String errorService;
@Column
private OffsetDateTime errorTimestamp;
public OffsetDateTime getLastOCRTime() {

View File

@ -1,5 +1,8 @@
package com.iqser.red.service.persistence.management.v1.processor.service;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
@ -43,7 +46,8 @@ public class CvAnalysisMessageReceiver {
log.warn("Received message from {} for dossierId {} and fileId {}", MessagingConfiguration.IMAGE_SERVICE_DLQ, response.getDossierId(), response.getFileId());
fileStatusProcessingUpdateService.analysisFailed(response.getDossierId(), response.getFileId(), new FileErrorInfo("cv analysis failed", MessagingConfiguration.IMAGE_SERVICE_DLQ, "cv-analysis-service-v1"));
fileStatusProcessingUpdateService.analysisFailed(response.getDossierId(), response.getFileId(), new FileErrorInfo("cv analysis failed", MessagingConfiguration.IMAGE_SERVICE_DLQ, "cv-analysis-service-v1", OffsetDateTime.now().truncatedTo(
ChronoUnit.MILLIS)));
}

View File

@ -170,7 +170,7 @@ public class FileStatusService {
}
if (settings.isImageServiceEnabled() && !fileManagementStorageService.objectExists(dossierId, fileId, FileType.IMAGE_INFO)) {
log.debug("Add file: {} from dossier {} to Image queue", fileId, dossierId);
log.info("Add file: {} from dossier {} to Image queue", fileId, dossierId);
addToImageQueue(dossierId, fileId);
return;
}
@ -313,6 +313,7 @@ public class FileStatusService {
return message;
});
} catch (JsonProcessingException e) {
log.warn("Error trying to send message to the image queue: {}", e.getMessage());
throw new RuntimeException(e);
}
}

View File

@ -1,6 +1,8 @@
package com.iqser.red.service.persistence.management.v1.processor.service;
import java.io.IOException;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import org.springframework.amqp.core.Message;
@ -53,7 +55,7 @@ public class ImageMessageReceiver {
String fileId = (String) imageResponse.get("fileId");
log.warn("Received message from {} for dossierId {} and fileId {}", MessagingConfiguration.IMAGE_SERVICE_DLQ, dossierId, fileId);
fileStatusProcessingUpdateService.analysisFailed(dossierId, fileId, new FileErrorInfo("image analysis failed", MessagingConfiguration.IMAGE_SERVICE_DLQ, "image-service-v3"));
fileStatusProcessingUpdateService.analysisFailed(dossierId, fileId, new FileErrorInfo("image analysis failed", MessagingConfiguration.IMAGE_SERVICE_DLQ, "image-service-v3", OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)));
}

View File

@ -1,6 +1,8 @@
package com.iqser.red.service.persistence.management.v1.processor.service;
import java.io.IOException;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import org.springframework.amqp.core.Message;
@ -51,7 +53,7 @@ public class NerMessageReceiver {
log.warn("Received message {} for dossierId {} and fileId {}", MessagingConfiguration.NER_SERVICE_DLQ, dossierId, fileId);
fileStatusProcessingUpdateService.analysisFailed(dossierId, fileId,
new FileErrorInfo("ner service failed", MessagingConfiguration.NER_SERVICE_DLQ, "entity-recognition-service-v3"));
new FileErrorInfo("ner service failed", MessagingConfiguration.NER_SERVICE_DLQ, "entity-recognition-service-v3", OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)));
}
}

View File

@ -167,9 +167,9 @@ public class FileStatusPersistenceService {
@Transactional
public void updateStatusErrorInfo(String fileId, FileErrorInfo fileErrorInfo) {
if (fileErrorInfo == null) {
fileRepository.updateStatusErrorInfo(fileId, null, null, null);
fileRepository.updateStatusErrorInfo(fileId, null, null, null, null);
} else {
fileRepository.updateStatusErrorInfo(fileId, fileErrorInfo.getCause(), fileErrorInfo.getQueue(), fileErrorInfo.getService());
fileRepository.updateStatusErrorInfo(fileId, fileErrorInfo.getCause(), fileErrorInfo.getQueue(), fileErrorInfo.getService(), fileErrorInfo.getTimestamp());
}
}
@ -182,7 +182,7 @@ public class FileStatusPersistenceService {
}
if (processingStatus == ProcessingStatus.PROCESSED) {
// reset the error info
fileRepository.updateStatusErrorInfo(fileId, null, null, null);
fileRepository.updateStatusErrorInfo(fileId, null, null, null, null);
// In case the file is updated to "processed", "lastProcessed" date should be updated to "now"
fileRepository.updateProcessingStatus(fileId,
processingStatus,

View File

@ -82,8 +82,8 @@ public interface FileRepository extends JpaRepository<FileEntity, String> {
void updateProcessingStatus(String fileId, ProcessingStatus processingStatus, OffsetDateTime lastUpdated, int processingErrorCounter);
@Modifying
@Query("update FileEntity f set f.errorCause = :cause, f.errorQueue = :queue, f.errorService = :service where f.id = :fileId")
void updateStatusErrorInfo(String fileId, String cause, String queue, String service);
@Query("update FileEntity f set f.errorCause = :cause, f.errorQueue = :queue, f.errorService = :service, f.errorTimestamp = :timestamp where f.id = :fileId")
void updateStatusErrorInfo(String fileId, String cause, String queue, String service, OffsetDateTime timestamp);
@Modifying(clearAutomatically = true, flushAutomatically = true)
@ -142,7 +142,7 @@ public interface FileRepository extends JpaRepository<FileEntity, String> {
@Modifying(clearAutomatically = true)
@Query("update FileEntity f set f.filename = :filename, f.uploader = :uploader, f.processingStatus = :processingStatus, " + "f.workflowStatus = :workflowStatus, f.lastUploaded = :lastUploaded, f.lastUpdated = :lastUpdated, f.fileManipulationDate = :lastUploaded, " + "f.ocrEndTime = null, f.ocrStartTime = null, f.numberOfPagesToOCR = null, f.numberOfOCRedPages = null, f.excluded = false, f.lastProcessed = null, f.lastReviewer = null, f.lastApprover = null, " + "f.assignee = null, f.approvalDate = null, f.numberOfAnalyses = 0, f.lastManualChangeDate = null, f.redactionModificationDate = null, " + "f.dictionaryVersion = 0, f.dossierDictionaryVersion = 0, f.rulesVersion = 0, f.hasImages = false, " + "f.hasHints = false, f.hasRedactions = false, f.hasSuggestions = false, f.hasUpdates = false, " + "f.deleted = null, f.hardDeletedTime = null, f.hasHighlights = false, f.excludedFromAutomaticAnalysis = false, f.processingErrorCounter = 0 where f.id = :fileId")
@Query("update FileEntity f set f.filename = :filename, f.uploader = :uploader, f.processingStatus = :processingStatus, " + "f.workflowStatus = :workflowStatus, f.lastUploaded = :lastUploaded, f.lastUpdated = :lastUpdated, f.fileManipulationDate = :lastUploaded, " + "f.ocrEndTime = null, f.ocrStartTime = null, f.numberOfPagesToOCR = null, f.numberOfOCRedPages = null, f.excluded = false, f.lastProcessed = null, f.lastReviewer = null, f.lastApprover = null, " + "f.assignee = null, f.approvalDate = null, f.numberOfAnalyses = 0, f.lastManualChangeDate = null, f.redactionModificationDate = null, " + "f.dictionaryVersion = 0, f.dossierDictionaryVersion = 0, f.rulesVersion = 0, f.hasImages = false, " + "f.hasHints = false, f.hasRedactions = false, f.hasSuggestions = false, f.hasUpdates = false, " + "f.deleted = null, f.hardDeletedTime = null, f.hasHighlights = false, f.excludedFromAutomaticAnalysis = false, f.processingErrorCounter = 0, f.errorCause = null, f.errorQueue = null, f.errorService = null, f.errorTimestamp = null where f.id = :fileId")
int overwriteFile(String fileId,
String filename,
String uploader,
@ -153,7 +153,7 @@ public interface FileRepository extends JpaRepository<FileEntity, String> {
@Modifying(clearAutomatically = true)
@Query("update FileEntity f set f.filename = :filename, f.uploader = :uploader, f.processingStatus = :processingStatus, " + "f.lastUploaded = :lastUploaded, f.lastUpdated = :lastUpdated, f.fileManipulationDate = :lastUploaded, " + "f.lastProcessed = null," + "f.approvalDate = null, f.numberOfAnalyses = 0, f.lastManualChangeDate = null, f.redactionModificationDate = null, " + "f.dictionaryVersion = 0, f.dossierDictionaryVersion = 0, f.rulesVersion = 0, f.hasImages = false, " + "f.hasHints = false, f.hasRedactions = false, f.hasSuggestions = false, f.hasUpdates = false, " + "f.deleted = null, f.hardDeletedTime = null, f.hasHighlights = false, f.processingErrorCounter = 0, f.ocrStartTime = null, f.ocrEndTime = null, f.numberOfPagesToOCR = null, f.numberOfOCRedPages = null where f.id = :fileId")
@Query("update FileEntity f set f.filename = :filename, f.uploader = :uploader, f.processingStatus = :processingStatus, " + "f.lastUploaded = :lastUploaded, f.lastUpdated = :lastUpdated, f.fileManipulationDate = :lastUploaded, " + "f.lastProcessed = null," + "f.approvalDate = null, f.numberOfAnalyses = 0, f.lastManualChangeDate = null, f.redactionModificationDate = null, " + "f.dictionaryVersion = 0, f.dossierDictionaryVersion = 0, f.rulesVersion = 0, f.hasImages = false, " + "f.hasHints = false, f.hasRedactions = false, f.hasSuggestions = false, f.hasUpdates = false, " + "f.deleted = null, f.hardDeletedTime = null, f.hasHighlights = false, f.processingErrorCounter = 0, f.ocrStartTime = null, f.ocrEndTime = null, f.numberOfPagesToOCR = null, f.numberOfOCRedPages = null, f.errorCause = null, f.errorQueue = null, f.errorService = null, f.errorTimestamp = null where f.id = :fileId")
int overwriteFileAndKeepManualRedactions(String fileId,
String filename,
String uploader,

View File

@ -12,7 +12,7 @@ public class FileModelMapper implements BiConsumer<FileEntity, FileModel> {
public void accept(FileEntity fileEntity, FileModel fileModel) {
fileEntity.getFileAttributes().forEach(fa -> fileModel.getFileAttributes().put(fa.getFileAttributeId().getFileAttributeConfigId(), fa.getValue()));
fileModel.setFileErrorInfo(new FileErrorInfo(fileEntity.getErrorCause(), fileEntity.getErrorQueue(), fileEntity.getErrorService()));
fileModel.setFileErrorInfo(new FileErrorInfo(fileEntity.getErrorCause(), fileEntity.getErrorQueue(), fileEntity.getErrorService(), fileEntity.getErrorTimestamp()));
}
}

View File

@ -141,3 +141,5 @@ databaseChangeLog:
file: db/changelog/tenant/103-added-remove-from-all-dossier-to-manual-remove-redaction.yaml
- include:
file: db/changelog/tenant/104-added-add-to-all-dossier-to-manual-add-redaction.yaml
- include:
file: db/changelog/tenant/52-add-file-status-error-timestamp.yaml

View File

@ -0,0 +1,11 @@
databaseChangeLog:
- changeSet:
id: add-file-status-error-timestamp
author: corinaolariu
changes:
- addColumn:
columns:
- column:
name: error_timestamp
type: TIMESTAMP WITHOUT TIME ZONE
tableName: file

View File

@ -2,6 +2,8 @@ package com.iqser.red.service.peristence.v1.server.integration.tests;
import static org.assertj.core.api.Assertions.assertThat;
import java.time.OffsetDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import org.junit.jupiter.api.Test;
@ -104,7 +106,7 @@ public class FileProcessingTest extends AbstractPersistenceServerServiceTest {
assertThat(file.getOcrStartTime()).isNull();
var queue = "queue1";
fileProcessingClient.analysisFailed(dossier.getId(), file.getId(), new FileErrorInfo("something failed", queue, "service"));
fileProcessingClient.analysisFailed(dossier.getId(), file.getId(), new FileErrorInfo("something failed", queue, "service", OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS)));
var loadedFile = fileClient.getFileStatus(dossier.getId(), file.getId());
assertThat(loadedFile.getProcessingStatus()).isEqualTo(ProcessingStatus.ERROR);
assertThat(loadedFile.getFileErrorInfo().getQueue()).isEqualTo(queue);

View File

@ -1,5 +1,7 @@
package com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file;
import java.time.OffsetDateTime;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@ -14,4 +16,5 @@ public class FileErrorInfo {
private String cause;
private String queue;
private String service;
private OffsetDateTime timestamp;
}