RED-7382: Implemented Saas migration
This commit is contained in:
parent
3c374baf94
commit
75aa8aa467
@ -0,0 +1,45 @@
|
|||||||
|
package com.iqser.red.persistence.service.v1.external.api.impl.controller;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.SaasMigrationStatusPersistenceService;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.external.resource.MigrationStatusResource;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.SaasMigrationStatus;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.saas.migration.MigrationStatusResponse;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.SaasMigrationStatus.*;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class MigrationStatusController implements MigrationStatusResource {
|
||||||
|
|
||||||
|
private final SaasMigrationStatusPersistenceService saasMigrationStatusPersistenceService;
|
||||||
|
|
||||||
|
public MigrationStatusResponse migrationStatus() {
|
||||||
|
int numberOfFilesToMigrate = saasMigrationStatusPersistenceService.countAll();
|
||||||
|
|
||||||
|
Map<SaasMigrationStatus, Integer> filesInStatus = new HashMap<>();
|
||||||
|
filesInStatus.put(MIGRATION_REQUIRED, saasMigrationStatusPersistenceService.countByStatus(MIGRATION_REQUIRED));
|
||||||
|
filesInStatus.put(DOCUMENT_FILES_MIGRATED, saasMigrationStatusPersistenceService.countByStatus(DOCUMENT_FILES_MIGRATED));
|
||||||
|
filesInStatus.put(REDACTION_LOGS_MIGRATED, saasMigrationStatusPersistenceService.countByStatus(REDACTION_LOGS_MIGRATED));
|
||||||
|
filesInStatus.put(ANNOTATION_IDS_MIGRATED, saasMigrationStatusPersistenceService.countByStatus(ANNOTATION_IDS_MIGRATED));
|
||||||
|
filesInStatus.put(FINISHED, saasMigrationStatusPersistenceService.countByStatus(FINISHED));
|
||||||
|
filesInStatus.put(ERROR, saasMigrationStatusPersistenceService.countByStatus(ERROR));
|
||||||
|
|
||||||
|
var filesInErrorState = saasMigrationStatusPersistenceService.findAllByStatus(ERROR);
|
||||||
|
|
||||||
|
Map<String, String> errorCauses = new HashMap<>();
|
||||||
|
filesInErrorState.forEach(errorFile -> {
|
||||||
|
errorCauses.put(errorFile.getFileId(), errorFile.getErrorCause());
|
||||||
|
});
|
||||||
|
|
||||||
|
return MigrationStatusResponse.builder()
|
||||||
|
.numberOfFilesToMigrate(numberOfFilesToMigrate)
|
||||||
|
.filesInStatus(filesInStatus)
|
||||||
|
.errorCauses(errorCauses)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
package com.iqser.red.service.persistence.service.v1.api.external.resource;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.saas.migration.MigrationStatusResponse;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
public interface MigrationStatusResource {
|
||||||
|
|
||||||
|
String MIGRATION_STATUS_REST_PATH = ExternalApi.BASE_PATH + "/migration-status";
|
||||||
|
|
||||||
|
|
||||||
|
@ResponseBody
|
||||||
|
@PostMapping(value = MIGRATION_STATUS_REST_PATH, produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
@Operation(summary = "Show the status of the migration", description = "None")
|
||||||
|
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Success.")})
|
||||||
|
MigrationStatusResponse migrationStatus();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -65,6 +65,35 @@ public class MessagingConfiguration {
|
|||||||
public static final String X_ERROR_INFO_HEADER = "x-error-message";
|
public static final String X_ERROR_INFO_HEADER = "x-error-message";
|
||||||
public static final String X_ERROR_INFO_TIMESTAMP_HEADER = "x-error-message-timestamp";
|
public static final String X_ERROR_INFO_TIMESTAMP_HEADER = "x-error-message-timestamp";
|
||||||
|
|
||||||
|
// --- Saas Migration, can be removed later ----
|
||||||
|
|
||||||
|
public static final String MIGRATION_QUEUE = "migrationQueue";
|
||||||
|
public static final String MIGRATION_DLQ = "migrationDLQ";
|
||||||
|
public static final String MIGRATION_RESPONSE_QUEUE = "migrationResponseQueue";
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Queue migrationQueue() {
|
||||||
|
|
||||||
|
return QueueBuilder.durable(MIGRATION_QUEUE).withArgument("x-dead-letter-exchange", "").withArgument("x-dead-letter-routing-key", MIGRATION_DLQ).maxPriority(2).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Queue migrationDLQ() {
|
||||||
|
|
||||||
|
return QueueBuilder.durable(MIGRATION_DLQ).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Queue migrationResponseQueue() {
|
||||||
|
|
||||||
|
return QueueBuilder.durable(MIGRATION_RESPONSE_QUEUE).withArgument("x-dead-letter-exchange", "").withArgument("x-dead-letter-routing-key", MIGRATION_DLQ).maxPriority(2).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- End Saas Migration
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Queue nerRequestQueue() {
|
public Queue nerRequestQueue() {
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,34 @@
|
|||||||
|
package com.iqser.red.service.persistence.management.v1.processor.entity.migration;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.SaasMigrationStatus;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Entity
|
||||||
|
@Table(name = "saas_migration_status")
|
||||||
|
public class SaasMigrationStatusEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private String fileId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
private String dossierId;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private SaasMigrationStatus status;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
private Integer processingErrorCounter;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
private String errorCause;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,152 @@
|
|||||||
|
package com.iqser.red.service.persistence.management.v1.processor.migration;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.*;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.CommentRepository;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.FileRepository;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.annotationentity.*;
|
||||||
|
import com.knecon.fforesight.databasetenantcommons.providers.utils.MagicConverter;
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SaasAnnotationIdMigrationService {
|
||||||
|
|
||||||
|
private final ManualRedactionRepository manualRedactionRepository;
|
||||||
|
private final RemoveRedactionRepository removeRedactionRepository;
|
||||||
|
private final ForceRedactionRepository forceRedactionRepository;
|
||||||
|
private final ResizeRedactionRepository resizeRedactionRepository;
|
||||||
|
private final RecategorizationRepository recategorizationRepository;
|
||||||
|
private final LegalBasisChangeRepository legalBasisChangeRepository;
|
||||||
|
private final CommentRepository commentRepository;
|
||||||
|
private final FileRepository fileRepository;
|
||||||
|
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateAnnotationIds(String fileId, Map<String, String> oldToNewMapping) {
|
||||||
|
|
||||||
|
AtomicInteger numUpdates = new AtomicInteger(0);
|
||||||
|
AtomicInteger numCommentUpdates = new AtomicInteger(0);
|
||||||
|
oldToNewMapping.forEach((key, value) -> {
|
||||||
|
AnnotationEntityId oldAnnotationEntityId = buildAnnotationId(fileId, key);
|
||||||
|
AnnotationEntityId newAnnotationEntityId = buildAnnotationId(fileId, value);
|
||||||
|
numUpdates.getAndAdd(updateManualAddRedaction(oldAnnotationEntityId, newAnnotationEntityId));
|
||||||
|
numUpdates.getAndAdd(updateRemoveRedaction(oldAnnotationEntityId, newAnnotationEntityId));
|
||||||
|
numUpdates.getAndAdd(updateForceRedaction(oldAnnotationEntityId, newAnnotationEntityId));
|
||||||
|
numUpdates.getAndAdd(updateResizeRedaction(oldAnnotationEntityId, newAnnotationEntityId));
|
||||||
|
numUpdates.getAndAdd(updateRecategorizationRedaction(oldAnnotationEntityId, newAnnotationEntityId));
|
||||||
|
numUpdates.getAndAdd(updateLegalBasisChangeRedaction(oldAnnotationEntityId, newAnnotationEntityId));
|
||||||
|
numCommentUpdates.getAndAdd(commentRepository.saasMigrationUpdateAnnotationIds(fileId, key, value));
|
||||||
|
});
|
||||||
|
log.info("Migrated {} annotationIds and {} comments for file {}", numUpdates.get(), numCommentUpdates, fileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int updateManualAddRedaction(AnnotationEntityId oldAnnotationEntityId, AnnotationEntityId newAnnotationEntityId) {
|
||||||
|
var oldEntry = manualRedactionRepository.findById(oldAnnotationEntityId);
|
||||||
|
if (oldEntry.isPresent()) {
|
||||||
|
|
||||||
|
var newEntry = MagicConverter.convert(oldEntry.get(), ManualRedactionEntryEntity.class);
|
||||||
|
newEntry.setPositions(MagicConverter.convert(oldEntry.get().getPositions(), RectangleEntity.class));
|
||||||
|
newEntry.setFileStatus(fileRepository.findById(oldAnnotationEntityId.getFileId()).get());
|
||||||
|
newEntry.setId(newAnnotationEntityId);
|
||||||
|
|
||||||
|
manualRedactionRepository.save(newEntry);
|
||||||
|
manualRedactionRepository.deleteById(oldAnnotationEntityId);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int updateRemoveRedaction(AnnotationEntityId oldAnnotationEntityId, AnnotationEntityId newAnnotationEntityId) {
|
||||||
|
var oldEntry = removeRedactionRepository.findById(oldAnnotationEntityId);
|
||||||
|
if (oldEntry.isPresent()) {
|
||||||
|
|
||||||
|
var newEntry = MagicConverter.convert(oldEntry.get(), IdRemovalEntity.class);
|
||||||
|
newEntry.setFileStatus(fileRepository.findById(oldAnnotationEntityId.getFileId()).get());
|
||||||
|
newEntry.setId(newAnnotationEntityId);
|
||||||
|
|
||||||
|
removeRedactionRepository.save(newEntry);
|
||||||
|
removeRedactionRepository.deleteById(oldAnnotationEntityId);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int updateForceRedaction(AnnotationEntityId oldAnnotationEntityId, AnnotationEntityId newAnnotationEntityId) {
|
||||||
|
var oldEntry = forceRedactionRepository.findById(oldAnnotationEntityId);
|
||||||
|
if (oldEntry.isPresent()) {
|
||||||
|
|
||||||
|
var newEntry = MagicConverter.convert(oldEntry.get(), ManualForceRedactionEntity.class);
|
||||||
|
newEntry.setFileStatus(fileRepository.findById(oldAnnotationEntityId.getFileId()).get());
|
||||||
|
newEntry.setId(newAnnotationEntityId);
|
||||||
|
|
||||||
|
forceRedactionRepository.save(newEntry);
|
||||||
|
forceRedactionRepository.deleteById(oldAnnotationEntityId);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int updateResizeRedaction(AnnotationEntityId oldAnnotationEntityId, AnnotationEntityId newAnnotationEntityId) {
|
||||||
|
var oldEntry = resizeRedactionRepository.findById(oldAnnotationEntityId);
|
||||||
|
if (oldEntry.isPresent()) {
|
||||||
|
|
||||||
|
var newEntry = MagicConverter.convert(oldEntry.get(), ManualResizeRedactionEntity.class);
|
||||||
|
newEntry.setId(newAnnotationEntityId);
|
||||||
|
newEntry.setPositions(MagicConverter.convert(oldEntry.get().getPositions(), RectangleEntity.class));
|
||||||
|
newEntry.setFileStatus(fileRepository.findById(oldAnnotationEntityId.getFileId()).get());
|
||||||
|
|
||||||
|
resizeRedactionRepository.save(newEntry);
|
||||||
|
resizeRedactionRepository.deleteById(oldAnnotationEntityId);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int updateRecategorizationRedaction(AnnotationEntityId oldAnnotationEntityId, AnnotationEntityId newAnnotationEntityId) {
|
||||||
|
var oldEntry = recategorizationRepository.findById(oldAnnotationEntityId);
|
||||||
|
if (oldEntry.isPresent()) {
|
||||||
|
|
||||||
|
var newEntry = MagicConverter.convert(oldEntry.get(), ManualRecategorizationEntity.class);
|
||||||
|
newEntry.setId(newAnnotationEntityId);
|
||||||
|
newEntry.setFileStatus(fileRepository.findById(oldAnnotationEntityId.getFileId()).get());
|
||||||
|
|
||||||
|
recategorizationRepository.save(newEntry);
|
||||||
|
recategorizationRepository.deleteById(oldAnnotationEntityId);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int updateLegalBasisChangeRedaction(AnnotationEntityId oldAnnotationEntityId, AnnotationEntityId newAnnotationEntityId) {
|
||||||
|
var oldEntry = legalBasisChangeRepository.findById(oldAnnotationEntityId);
|
||||||
|
if (oldEntry.isPresent()) {
|
||||||
|
|
||||||
|
var newEntry = MagicConverter.convert(oldEntry.get(), ManualLegalBasisChangeEntity.class);
|
||||||
|
newEntry.setId(newAnnotationEntityId);
|
||||||
|
newEntry.setFileStatus(fileRepository.findById(oldAnnotationEntityId.getFileId()).get());
|
||||||
|
|
||||||
|
legalBasisChangeRepository.save(newEntry);
|
||||||
|
legalBasisChangeRepository.deleteById(oldAnnotationEntityId);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private AnnotationEntityId buildAnnotationId(String fileId, String annotationId) {
|
||||||
|
return AnnotationEntityId.builder().fileId(fileId).annotationId(annotationId).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,141 @@
|
|||||||
|
package com.iqser.red.service.persistence.management.v1.processor.migration;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.exception.InternalServerErrorException;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.DossierService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.job.AutomaticAnalysisJob;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.layoutparsing.LayoutParsingRequestFactory;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.FileStatusPersistenceService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.SaasMigrationStatusPersistenceService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.settings.FileManagementServiceSettings;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.utils.StorageIdUtils;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.migration.MigratedIds;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileType;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.SaasMigrationStatus;
|
||||||
|
import com.iqser.red.service.redaction.v1.model.MigrationRequest;
|
||||||
|
import com.iqser.red.storage.commons.exception.StorageException;
|
||||||
|
import com.iqser.red.storage.commons.exception.StorageObjectDoesNotExist;
|
||||||
|
import com.iqser.red.storage.commons.service.StorageService;
|
||||||
|
import com.knecon.fforesight.tenantcommons.TenantContext;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.iqser.red.service.persistence.management.v1.processor.configuration.MessagingConfiguration.MIGRATION_QUEUE;
|
||||||
|
import static com.knecon.fforesight.service.layoutparser.internal.api.queue.LayoutParsingQueueNames.LAYOUT_PARSING_REQUEST_QUEUE;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SaasMigrationService {
|
||||||
|
|
||||||
|
private final AutomaticAnalysisJob automaticAnalysisJob;
|
||||||
|
private final FileStatusPersistenceService fileStatusPersistenceService;
|
||||||
|
private final SaasMigrationStatusPersistenceService saasMigrationStatusPersistenceService;
|
||||||
|
private final DossierService dossierService;
|
||||||
|
|
||||||
|
private final LayoutParsingRequestFactory layoutParsingRequestFactory;
|
||||||
|
private final RabbitTemplate rabbitTemplate;
|
||||||
|
private final FileManagementServiceSettings settings;
|
||||||
|
private final StorageService storageService;
|
||||||
|
|
||||||
|
|
||||||
|
private final SaasAnnotationIdMigrationService saasAnnotationIdMigrationService;
|
||||||
|
|
||||||
|
// Persistence-Service needs to be scaled to 1.
|
||||||
|
|
||||||
|
public void startMigrationForTenant(String tenantId) {
|
||||||
|
|
||||||
|
// TODO migrate rules.
|
||||||
|
|
||||||
|
automaticAnalysisJob.stopForTenant(tenantId);
|
||||||
|
|
||||||
|
int numberOfFiles = 0;
|
||||||
|
var dossiers = dossierService.getAllDossiers().stream().filter(dossier -> dossier.getHardDeletedTime() == null).toList();
|
||||||
|
for (var dossier : dossiers) {
|
||||||
|
var files = fileStatusPersistenceService.getStatusesForDossier(dossier.getId()).stream().filter(file -> file.getHardDeletedTime() == null).toList();
|
||||||
|
for (var file : files) {
|
||||||
|
saasMigrationStatusPersistenceService.createMigrationRequiredStatus(dossier.getId(), file.getId());
|
||||||
|
var layoutParsingRequest = layoutParsingRequestFactory.build(dossier.getId(), file.getId(), false);
|
||||||
|
rabbitTemplate.convertAndSend(LAYOUT_PARSING_REQUEST_QUEUE, layoutParsingRequest);
|
||||||
|
numberOfFiles++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("Added {} for tenant {} to Layout-Parsing queue for saas migration", numberOfFiles, TenantContext.getTenantId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void handleLayoutParsingFinished(String dossierId, String fileId) {
|
||||||
|
saasMigrationStatusPersistenceService.updateStatus(fileId, SaasMigrationStatus.DOCUMENT_FILES_MIGRATED);
|
||||||
|
rabbitTemplate.convertAndSend(MIGRATION_QUEUE, MigrationRequest.builder()
|
||||||
|
.dossierId(dossierId)
|
||||||
|
.fileId(fileId)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
log.info("Layout Parsing finished for saas migration for tenant {} dossier {} and file {}", TenantContext.getTenantId(), dossierId, fileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void handleEntityLogMigrationFinished(String dossierId, String fileId) {
|
||||||
|
saasMigrationStatusPersistenceService.updateStatus(fileId, SaasMigrationStatus.REDACTION_LOGS_MIGRATED);
|
||||||
|
|
||||||
|
log.info("EntityLog migration finished for saas migration for tenant {} dossier {} and file {}", TenantContext.getTenantId(), dossierId, fileId);
|
||||||
|
migrateAnnotationIds(dossierId, fileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void handleError(String dossierId, String fileId, String errorCause, String retryQueue) {
|
||||||
|
var migrationEntry = saasMigrationStatusPersistenceService.findById(fileId);
|
||||||
|
int numErrors = migrationEntry.getProcessingErrorCounter();
|
||||||
|
if (numErrors <= settings.getMaxErrorRetries()) {
|
||||||
|
saasMigrationStatusPersistenceService.updateErrorCounter(fileId, numErrors + 1, errorCause);
|
||||||
|
rabbitTemplate.convertAndSend(retryQueue, MigrationRequest.builder()
|
||||||
|
.dossierId(dossierId)
|
||||||
|
.fileId(fileId)
|
||||||
|
.build());
|
||||||
|
log.error("Retrying error during saas migration for tenant {} dossier {} and file {}, cause {}", TenantContext.getTenantId(), dossierId, fileId, errorCause);
|
||||||
|
} else {
|
||||||
|
saasMigrationStatusPersistenceService.updateErrorStatus(fileId, errorCause);
|
||||||
|
log.error("Error during saas migration for tenant {} dossier {} and file {}, cause {}", TenantContext.getTenantId(), dossierId, fileId, errorCause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void migrateAnnotationIds(String dossierId, String fileId) {
|
||||||
|
|
||||||
|
MigratedIds migratedIds = getMigratedIds(dossierId, fileId);
|
||||||
|
Map<String, String> oldToNewMapping = migratedIds.buildOldToNewMapping();
|
||||||
|
try {
|
||||||
|
saasAnnotationIdMigrationService.updateAnnotationIds(fileId, oldToNewMapping);
|
||||||
|
} catch (Exception e) {
|
||||||
|
saasMigrationStatusPersistenceService.updateErrorStatus(fileId, e.getMessage());
|
||||||
|
log.error("Error during saas migration for tenant {} dossier {} and file {}, cause {}", TenantContext.getTenantId(), dossierId, fileId, e.getMessage());
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
saasMigrationStatusPersistenceService.updateStatus(fileId, SaasMigrationStatus.FINISHED);
|
||||||
|
|
||||||
|
log.info("AnnotationIds migration finished for saas migration for tenant {} dossier {} and file {}", TenantContext.getTenantId(), dossierId, fileId);
|
||||||
|
if (saasMigrationStatusPersistenceService.countByStatus(SaasMigrationStatus.FINISHED) == saasMigrationStatusPersistenceService.countAll()) {
|
||||||
|
automaticAnalysisJob.startForTenant(TenantContext.getTenantId());
|
||||||
|
log.info("Saas migration finished for tenantId {}, re-enabled scheduler", TenantContext.getTenantId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private MigratedIds getMigratedIds(String dossierId, String fileId) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return storageService.readJSONObject(TenantContext.getTenantId(), StorageIdUtils.getStorageId(dossierId, fileId, FileType.MIGRATED_IDS), MigratedIds.class);
|
||||||
|
} catch (StorageObjectDoesNotExist e) {
|
||||||
|
throw new NotFoundException(String.format("MigratedIds does not exist for Dossier ID \"%s\" and File ID \"%s\"!", dossierId, fileId));
|
||||||
|
} catch (StorageException e) {
|
||||||
|
throw new InternalServerErrorException(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -186,7 +186,7 @@ public class FileStatusService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!fileManagementStorageService.objectExists(dossierId, fileId, FileType.DOCUMENT_TEXT)) {
|
if (!fileManagementStorageService.objectExists(dossierId, fileId, FileType.DOCUMENT_TEXT)) {
|
||||||
var layoutParsingRequest = layoutParsingRequestFactory.build(dossierId, fileId, priority, dossier);
|
var layoutParsingRequest = layoutParsingRequestFactory.build(dossierId, fileId, priority);
|
||||||
setStatusFullProcessing(fileId);
|
setStatusFullProcessing(fileId);
|
||||||
rabbitTemplate.convertAndSend(LAYOUT_PARSING_REQUEST_QUEUE, layoutParsingRequest);
|
rabbitTemplate.convertAndSend(LAYOUT_PARSING_REQUEST_QUEUE, layoutParsingRequest);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
package com.iqser.red.service.persistence.management.v1.processor.service.job;
|
package com.iqser.red.service.persistence.management.v1.processor.service.job;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.quartz.Job;
|
import org.quartz.Job;
|
||||||
import org.quartz.JobExecutionContext;
|
import org.quartz.JobExecutionContext;
|
||||||
@ -34,6 +36,8 @@ public class AutomaticAnalysisJob implements Job {
|
|||||||
@Setter
|
@Setter
|
||||||
private boolean schedulingStopped;
|
private boolean schedulingStopped;
|
||||||
|
|
||||||
|
private Set<String> stoppedTenants = new HashSet<>();
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(JobExecutionContext jobExecutionContext) {
|
public void execute(JobExecutionContext jobExecutionContext) {
|
||||||
@ -45,7 +49,7 @@ public class AutomaticAnalysisJob implements Job {
|
|||||||
|
|
||||||
tenantProvider.getTenants().forEach(tenant -> {
|
tenantProvider.getTenants().forEach(tenant -> {
|
||||||
|
|
||||||
if (!TenantUtils.isTenantReadyForPersistence(tenant)) {
|
if (!TenantUtils.isTenantReadyForPersistence(tenant) || stoppedTenants.contains(tenant.getTenantId())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,4 +104,13 @@ public class AutomaticAnalysisJob implements Job {
|
|||||||
return fileStatusService.getAllRelevantStatusesForReanalysisScheduler();
|
return fileStatusService.getAllRelevantStatusesForReanalysisScheduler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void stopForTenant(String tenantId){
|
||||||
|
stoppedTenants.add(tenantId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startForTenant(String tenantId){
|
||||||
|
stoppedTenants.remove(tenantId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ public class LayoutParsingRequestFactory {
|
|||||||
private final LayoutParsingRequestIdentifierService layoutParsingRequestIdentifierService;
|
private final LayoutParsingRequestIdentifierService layoutParsingRequestIdentifierService;
|
||||||
|
|
||||||
|
|
||||||
public LayoutParsingRequest build(String dossierId, String fileId, boolean priority, DossierEntity dossier) {
|
public LayoutParsingRequest build(String dossierId, String fileId, boolean priority) {
|
||||||
|
|
||||||
LayoutParsingType type = switch (applicationType) {
|
LayoutParsingType type = switch (applicationType) {
|
||||||
case "DocuMine" -> LayoutParsingType.DOCUMINE;
|
case "DocuMine" -> LayoutParsingType.DOCUMINE;
|
||||||
|
|||||||
@ -0,0 +1,69 @@
|
|||||||
|
package com.iqser.red.service.persistence.management.v1.processor.service.persistence;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.migration.SaasMigrationStatusEntity;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.SaasMigrationStatusRepository;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.SaasMigrationStatus;
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SaasMigrationStatusPersistenceService {
|
||||||
|
|
||||||
|
private final SaasMigrationStatusRepository saasMigrationStatusRepository;
|
||||||
|
|
||||||
|
public List<SaasMigrationStatusEntity> findAllByStatus(SaasMigrationStatus status) {
|
||||||
|
return saasMigrationStatusRepository.findAllByStatus(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SaasMigrationStatusEntity findById(String fileId) {
|
||||||
|
|
||||||
|
var migrationStatusOptional = saasMigrationStatusRepository.findById(fileId);
|
||||||
|
if (migrationStatusOptional.isPresent()) {
|
||||||
|
return migrationStatusOptional.get();
|
||||||
|
}
|
||||||
|
throw new NotFoundException("No migration entry found for fileId" + fileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMigrating(String fileId) {
|
||||||
|
var migrationStatusOptional = saasMigrationStatusRepository.findById(fileId);
|
||||||
|
return migrationStatusOptional.isPresent() && migrationStatusOptional.get().getStatus() != SaasMigrationStatus.FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void createMigrationRequiredStatus(String dossierId, String fileId) {
|
||||||
|
saasMigrationStatusRepository.save(SaasMigrationStatusEntity.builder()
|
||||||
|
.fileId(fileId)
|
||||||
|
.dossierId(dossierId)
|
||||||
|
.status(SaasMigrationStatus.MIGRATION_REQUIRED)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateStatus(String fileId, SaasMigrationStatus status) {
|
||||||
|
saasMigrationStatusRepository.updateStatus(fileId, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateErrorStatus(String fileId, String errorCause) {
|
||||||
|
saasMigrationStatusRepository.updateErrorStatus(fileId, SaasMigrationStatus.ERROR, errorCause);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateErrorCounter(String fileId, Integer processingErrorCounter, String errorCause) {
|
||||||
|
saasMigrationStatusRepository.updateErrorCounter(fileId, processingErrorCounter, errorCause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int countByStatus(SaasMigrationStatus status) {
|
||||||
|
return saasMigrationStatusRepository.countByStatus(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int countAll() {
|
||||||
|
return saasMigrationStatusRepository.countAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -26,4 +26,8 @@ public interface CommentRepository extends JpaRepository<CommentEntity, Long> {
|
|||||||
@Query("update CommentEntity c set c.softDeletedTime = :softDeleteTime where c.id = :id")
|
@Query("update CommentEntity c set c.softDeletedTime = :softDeleteTime where c.id = :id")
|
||||||
int updateSoftDelete(long id, OffsetDateTime softDeleteTime);
|
int updateSoftDelete(long id, OffsetDateTime softDeleteTime);
|
||||||
|
|
||||||
|
@Modifying
|
||||||
|
@Query("update CommentEntity c set c.annotationId = :newAnnotationId where c.annotationId = :oldAnnotationId and c.fileId = :fileId")
|
||||||
|
int saasMigrationUpdateAnnotationIds(String fileId, String oldAnnotationId, String newAnnotationId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,33 @@
|
|||||||
|
package com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.entity.migration.SaasMigrationStatusEntity;
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.SaasMigrationStatus;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface SaasMigrationStatusRepository extends JpaRepository<SaasMigrationStatusEntity, String> {
|
||||||
|
|
||||||
|
List<SaasMigrationStatusEntity> findAllByStatus(SaasMigrationStatus status);
|
||||||
|
|
||||||
|
@Modifying
|
||||||
|
@Query("update SaasMigrationStatusEntity e set e.status = :status where e.fileId = :fileId")
|
||||||
|
void updateStatus(String fileId, SaasMigrationStatus status);
|
||||||
|
|
||||||
|
@Modifying
|
||||||
|
@Query("update SaasMigrationStatusEntity e set e.status = :status, e.errorCause = :errorCause where e.fileId = :fileId")
|
||||||
|
void updateErrorStatus(String fileId, SaasMigrationStatus status, String errorCause);
|
||||||
|
|
||||||
|
@Modifying
|
||||||
|
@Query("update SaasMigrationStatusEntity e set e.processingErrorCounter = :processingErrorCounter, e.errorCause = :errorCause where e.fileId = :fileId")
|
||||||
|
void updateErrorCounter(String fileId, Integer processingErrorCounter, String errorCause);
|
||||||
|
|
||||||
|
@Query("select count(*) from SaasMigrationStatusEntity e where e.status = :status")
|
||||||
|
int countByStatus(SaasMigrationStatus status);
|
||||||
|
|
||||||
|
@Query("select count(*) from SaasMigrationStatusEntity")
|
||||||
|
int countAll();
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,25 +1,25 @@
|
|||||||
package com.iqser.red.service.persistence.management.v1.processor.service.queue;
|
package com.iqser.red.service.persistence.management.v1.processor.service.queue;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.configuration.MessagingConfiguration;
|
import com.iqser.red.service.persistence.management.v1.processor.configuration.MessagingConfiguration;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.migration.SaasMigrationService;
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusProcessingUpdateService;
|
import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusProcessingUpdateService;
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusService;
|
import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusService;
|
||||||
import com.iqser.red.service.persistence.management.v1.processor.service.layoutparsing.LayoutParsingRequestIdentifierService;
|
import com.iqser.red.service.persistence.management.v1.processor.service.layoutparsing.LayoutParsingRequestIdentifierService;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.SaasMigrationStatusPersistenceService;
|
||||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileErrorInfo;
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileErrorInfo;
|
||||||
import com.knecon.fforesight.service.layoutparser.internal.api.queue.LayoutParsingFinishedEvent;
|
import com.knecon.fforesight.service.layoutparser.internal.api.queue.LayoutParsingFinishedEvent;
|
||||||
import com.knecon.fforesight.service.layoutparser.internal.api.queue.LayoutParsingQueueNames;
|
import com.knecon.fforesight.service.layoutparser.internal.api.queue.LayoutParsingQueueNames;
|
||||||
import com.knecon.fforesight.service.layoutparser.internal.api.queue.LayoutParsingRequest;
|
import com.knecon.fforesight.service.layoutparser.internal.api.queue.LayoutParsingRequest;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.amqp.core.Message;
|
||||||
|
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@ -30,12 +30,20 @@ public class LayoutParsingFinishedMessageReceiver {
|
|||||||
private final FileStatusProcessingUpdateService fileStatusProcessingUpdateService;
|
private final FileStatusProcessingUpdateService fileStatusProcessingUpdateService;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
private final LayoutParsingRequestIdentifierService layoutParsingRequestIdentifierService;
|
private final LayoutParsingRequestIdentifierService layoutParsingRequestIdentifierService;
|
||||||
|
private final SaasMigrationStatusPersistenceService saasMigrationStatusPersistenceService;
|
||||||
|
private final SaasMigrationService saasMigrationService;
|
||||||
|
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@RabbitListener(queues = LayoutParsingQueueNames.LAYOUT_PARSING_FINISHED_EVENT_QUEUE)
|
@RabbitListener(queues = LayoutParsingQueueNames.LAYOUT_PARSING_FINISHED_EVENT_QUEUE)
|
||||||
public void receive(LayoutParsingFinishedEvent response) {
|
public void receive(LayoutParsingFinishedEvent response) {
|
||||||
|
|
||||||
|
if (saasMigrationStatusPersistenceService.isMigrating(layoutParsingRequestIdentifierService.parseFileId(response.identifier()))) {
|
||||||
|
saasMigrationService.handleLayoutParsingFinished(layoutParsingRequestIdentifierService.parseDossierId(response.identifier()),
|
||||||
|
layoutParsingRequestIdentifierService.parseFileId(response.identifier()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
fileStatusService.setStatusAnalyse(layoutParsingRequestIdentifierService.parseDossierId(response.identifier()),
|
fileStatusService.setStatusAnalyse(layoutParsingRequestIdentifierService.parseDossierId(response.identifier()),
|
||||||
layoutParsingRequestIdentifierService.parseFileId(response.identifier()),
|
layoutParsingRequestIdentifierService.parseFileId(response.identifier()),
|
||||||
layoutParsingRequestIdentifierService.parsePriority(response.identifier()));
|
layoutParsingRequestIdentifierService.parsePriority(response.identifier()));
|
||||||
@ -53,6 +61,13 @@ public class LayoutParsingFinishedMessageReceiver {
|
|||||||
var analyzeRequest = objectMapper.readValue(failedMessage.getBody(), LayoutParsingRequest.class);
|
var analyzeRequest = objectMapper.readValue(failedMessage.getBody(), LayoutParsingRequest.class);
|
||||||
log.info("Failed to process analyze request: {}", analyzeRequest);
|
log.info("Failed to process analyze request: {}", analyzeRequest);
|
||||||
String errorCause = failedMessage.getMessageProperties().getHeader(MessagingConfiguration.X_ERROR_INFO_HEADER);
|
String errorCause = failedMessage.getMessageProperties().getHeader(MessagingConfiguration.X_ERROR_INFO_HEADER);
|
||||||
|
|
||||||
|
if (saasMigrationStatusPersistenceService.isMigrating(layoutParsingRequestIdentifierService.parseFileId(analyzeRequest.identifier()))) {
|
||||||
|
saasMigrationService.handleError(layoutParsingRequestIdentifierService.parseDossierId(analyzeRequest.identifier()),
|
||||||
|
layoutParsingRequestIdentifierService.parseFileId(analyzeRequest.identifier()), errorCause, LayoutParsingQueueNames.LAYOUT_PARSING_REQUEST_QUEUE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
OffsetDateTime timestamp = failedMessage.getMessageProperties().getHeader(MessagingConfiguration.X_ERROR_INFO_TIMESTAMP_HEADER);
|
OffsetDateTime timestamp = failedMessage.getMessageProperties().getHeader(MessagingConfiguration.X_ERROR_INFO_TIMESTAMP_HEADER);
|
||||||
timestamp = timestamp != null ? timestamp : OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS);
|
timestamp = timestamp != null ? timestamp : OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS);
|
||||||
log.info("Failed to process layout parsing request, errorCause: {}, timestamp: {}", errorCause, timestamp);
|
log.info("Failed to process layout parsing request, errorCause: {}, timestamp: {}", errorCause, timestamp);
|
||||||
|
|||||||
@ -0,0 +1,45 @@
|
|||||||
|
package com.iqser.red.service.persistence.management.v1.processor.service.queue;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.configuration.MessagingConfiguration;
|
||||||
|
import com.iqser.red.service.persistence.management.v1.processor.migration.SaasMigrationService;
|
||||||
|
import com.iqser.red.service.redaction.v1.model.MigrationRequest;
|
||||||
|
import com.iqser.red.service.redaction.v1.model.MigrationResponse;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.amqp.core.Message;
|
||||||
|
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import static com.iqser.red.service.persistence.management.v1.processor.configuration.MessagingConfiguration.*;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RedactionServiceSaasMigrationMessageReceiver {
|
||||||
|
|
||||||
|
private final SaasMigrationService saasMigrationService;
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
@RabbitListener(queues = MIGRATION_RESPONSE_QUEUE)
|
||||||
|
public void receive(MigrationResponse response) {
|
||||||
|
|
||||||
|
saasMigrationService.handleEntityLogMigrationFinished(response.getDossierId(), response.getFileId());
|
||||||
|
|
||||||
|
log.info("Received message {} in {}", response, MIGRATION_RESPONSE_QUEUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
@RabbitListener(queues = MIGRATION_DLQ)
|
||||||
|
public void handleDLQMessage(Message failedMessage) {
|
||||||
|
|
||||||
|
var migrationRequest = objectMapper.readValue(failedMessage.getBody(), MigrationRequest.class);
|
||||||
|
String errorCause = failedMessage.getMessageProperties().getHeader(MessagingConfiguration.X_ERROR_INFO_HEADER);
|
||||||
|
saasMigrationService.handleError(migrationRequest.getDossierId(), migrationRequest.getFileId(), errorCause, MIGRATION_QUEUE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -167,3 +167,5 @@ databaseChangeLog:
|
|||||||
file: db/changelog/tenant/112-modify-section-length.yaml
|
file: db/changelog/tenant/112-modify-section-length.yaml
|
||||||
- include:
|
- include:
|
||||||
file: db/changelog/tenant/114-add-download-redaction-file-status-table.yaml
|
file: db/changelog/tenant/114-add-download-redaction-file-status-table.yaml
|
||||||
|
- include:
|
||||||
|
file: db/changelog/tenant/115-add-saas-migration-status-table.yaml
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
databaseChangeLog:
|
||||||
|
- changeSet:
|
||||||
|
id: add-saas-migration-status-table
|
||||||
|
author: dom
|
||||||
|
changes:
|
||||||
|
- createTable:
|
||||||
|
columns:
|
||||||
|
- column:
|
||||||
|
constraints:
|
||||||
|
nullable: false
|
||||||
|
primaryKey: true
|
||||||
|
primaryKeyName: add-saas-migration-status-table_pkey
|
||||||
|
name: file_id
|
||||||
|
type: VARCHAR(255)
|
||||||
|
- column:
|
||||||
|
name: dossier_id
|
||||||
|
type: VARCHAR(255)
|
||||||
|
- column:
|
||||||
|
name: status
|
||||||
|
type: VARCHAR(255)
|
||||||
|
- column:
|
||||||
|
name: processing_error_counter
|
||||||
|
type: INTEGER
|
||||||
|
- column:
|
||||||
|
name: error_cause
|
||||||
|
type: VARCHAR(1024)
|
||||||
|
tableName: saas_migration_status
|
||||||
|
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file;
|
||||||
|
|
||||||
|
public enum SaasMigrationStatus {
|
||||||
|
MIGRATION_REQUIRED,
|
||||||
|
DOCUMENT_FILES_MIGRATED,
|
||||||
|
REDACTION_LOGS_MIGRATED,
|
||||||
|
ANNOTATION_IDS_MIGRATED,
|
||||||
|
FINISHED,
|
||||||
|
ERROR
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package com.iqser.red.service.persistence.service.v1.api.shared.model.saas.migration;
|
||||||
|
|
||||||
|
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.SaasMigrationStatus;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||||
|
public class MigrationStatusResponse {
|
||||||
|
|
||||||
|
private Integer numberOfFilesToMigrate;
|
||||||
|
@Builder.Default
|
||||||
|
private Map<SaasMigrationStatus, Integer> filesInStatus = new HashMap<>();
|
||||||
|
@Builder.Default
|
||||||
|
private Map<String, String> errorCauses = new HashMap<>();
|
||||||
|
|
||||||
|
}
|
||||||
@ -31,7 +31,7 @@
|
|||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<redaction-service.version>4.157.0</redaction-service.version>
|
<redaction-service.version>4.165.0</redaction-service.version>
|
||||||
<search-service.version>2.71.0</search-service.version>
|
<search-service.version>2.71.0</search-service.version>
|
||||||
<pdftron-redaction-service.version>4.29.0</pdftron-redaction-service.version>
|
<pdftron-redaction-service.version>4.29.0</pdftron-redaction-service.version>
|
||||||
<redaction-report-service.version>4.13.0</redaction-report-service.version>
|
<redaction-report-service.version>4.13.0</redaction-report-service.version>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user