From 75aa8aa4679512c27191b141a0eb97b24f925c18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominique=20Eifl=C3=A4nder?= Date: Mon, 6 Nov 2023 13:06:49 +0100 Subject: [PATCH] RED-7382: Implemented Saas migration --- .../controller/MigrationStatusController.java | 45 ++++++ .../resource/MigrationStatusResource.java | 23 +++ .../configuration/MessagingConfiguration.java | 29 ++++ .../migration/SaasMigrationStatusEntity.java | 34 ++++ .../SaasAnnotationIdMigrationService.java | 152 ++++++++++++++++++ .../migration/SaasMigrationService.java | 141 ++++++++++++++++ .../processor/service/FileStatusService.java | 2 +- .../service/job/AutomaticAnalysisJob.java | 15 +- .../LayoutParsingRequestFactory.java | 2 +- ...SaasMigrationStatusPersistenceService.java | 69 ++++++++ .../repository/CommentRepository.java | 4 + .../SaasMigrationStatusRepository.java | 33 ++++ .../LayoutParsingFinishedMessageReceiver.java | 31 +++- ...onServiceSaasMigrationMessageReceiver.java | 45 ++++++ .../db/changelog/db.changelog-tenant.yaml | 4 +- .../115-add-saas-migration-status-table.yaml | 28 ++++ .../dossier/file/SaasMigrationStatus.java | 10 ++ .../migration/MigrationStatusResponse.java | 21 +++ persistence-service-v1/pom.xml | 2 +- 19 files changed, 677 insertions(+), 13 deletions(-) create mode 100644 persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/MigrationStatusController.java create mode 100644 persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/MigrationStatusResource.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/migration/SaasMigrationStatusEntity.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/migration/SaasAnnotationIdMigrationService.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/migration/SaasMigrationService.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/SaasMigrationStatusPersistenceService.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/SaasMigrationStatusRepository.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/queue/RedactionServiceSaasMigrationMessageReceiver.java create mode 100644 persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/115-add-saas-migration-status-table.yaml create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/dossiertemplate/dossier/file/SaasMigrationStatus.java create mode 100644 persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/saas/migration/MigrationStatusResponse.java diff --git a/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/MigrationStatusController.java b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/MigrationStatusController.java new file mode 100644 index 000000000..f85573a13 --- /dev/null +++ b/persistence-service-v1/persistence-service-external-api-impl-v1/src/main/java/com/iqser/red/persistence/service/v1/external/api/impl/controller/MigrationStatusController.java @@ -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 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 errorCauses = new HashMap<>(); + filesInErrorState.forEach(errorFile -> { + errorCauses.put(errorFile.getFileId(), errorFile.getErrorCause()); + }); + + return MigrationStatusResponse.builder() + .numberOfFilesToMigrate(numberOfFilesToMigrate) + .filesInStatus(filesInStatus) + .errorCauses(errorCauses) + .build(); + } +} diff --git a/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/MigrationStatusResource.java b/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/MigrationStatusResource.java new file mode 100644 index 000000000..a46bc2e81 --- /dev/null +++ b/persistence-service-v1/persistence-service-external-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/external/resource/MigrationStatusResource.java @@ -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(); + + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/configuration/MessagingConfiguration.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/configuration/MessagingConfiguration.java index 2d6bc486e..2d6d113c8 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/configuration/MessagingConfiguration.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/configuration/MessagingConfiguration.java @@ -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_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 public Queue nerRequestQueue() { diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/migration/SaasMigrationStatusEntity.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/migration/SaasMigrationStatusEntity.java new file mode 100644 index 000000000..e0b660f02 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/entity/migration/SaasMigrationStatusEntity.java @@ -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; + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/migration/SaasAnnotationIdMigrationService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/migration/SaasAnnotationIdMigrationService.java new file mode 100644 index 000000000..67bd1dbdf --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/migration/SaasAnnotationIdMigrationService.java @@ -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 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(); + } + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/migration/SaasMigrationService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/migration/SaasMigrationService.java new file mode 100644 index 000000000..0b4335c44 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/migration/SaasMigrationService.java @@ -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 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()); + } + } + + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/FileStatusService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/FileStatusService.java index 474fdfcb1..74cd03b42 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/FileStatusService.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/FileStatusService.java @@ -186,7 +186,7 @@ public class FileStatusService { } 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); rabbitTemplate.convertAndSend(LAYOUT_PARSING_REQUEST_QUEUE, layoutParsingRequest); return; diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/job/AutomaticAnalysisJob.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/job/AutomaticAnalysisJob.java index 32a7e3313..3abb8fef3 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/job/AutomaticAnalysisJob.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/job/AutomaticAnalysisJob.java @@ -1,7 +1,9 @@ package com.iqser.red.service.persistence.management.v1.processor.service.job; import java.util.Comparator; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.quartz.Job; import org.quartz.JobExecutionContext; @@ -34,6 +36,8 @@ public class AutomaticAnalysisJob implements Job { @Setter private boolean schedulingStopped; + private Set stoppedTenants = new HashSet<>(); + @Override public void execute(JobExecutionContext jobExecutionContext) { @@ -45,7 +49,7 @@ public class AutomaticAnalysisJob implements Job { tenantProvider.getTenants().forEach(tenant -> { - if (!TenantUtils.isTenantReadyForPersistence(tenant)) { + if (!TenantUtils.isTenantReadyForPersistence(tenant) || stoppedTenants.contains(tenant.getTenantId())) { return; } @@ -100,4 +104,13 @@ public class AutomaticAnalysisJob implements Job { return fileStatusService.getAllRelevantStatusesForReanalysisScheduler(); } + + public void stopForTenant(String tenantId){ + stoppedTenants.add(tenantId); + } + + public void startForTenant(String tenantId){ + stoppedTenants.remove(tenantId); + } + } diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/layoutparsing/LayoutParsingRequestFactory.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/layoutparsing/LayoutParsingRequestFactory.java index 76785a0b0..796db6f24 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/layoutparsing/LayoutParsingRequestFactory.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/layoutparsing/LayoutParsingRequestFactory.java @@ -25,7 +25,7 @@ public class LayoutParsingRequestFactory { 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) { case "DocuMine" -> LayoutParsingType.DOCUMINE; diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/SaasMigrationStatusPersistenceService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/SaasMigrationStatusPersistenceService.java new file mode 100644 index 000000000..e49895a98 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/SaasMigrationStatusPersistenceService.java @@ -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 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(); + } +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/CommentRepository.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/CommentRepository.java index 19f0f264b..4c60bc891 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/CommentRepository.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/CommentRepository.java @@ -26,4 +26,8 @@ public interface CommentRepository extends JpaRepository { @Query("update CommentEntity c set c.softDeletedTime = :softDeleteTime where c.id = :id") 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); + } diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/SaasMigrationStatusRepository.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/SaasMigrationStatusRepository.java new file mode 100644 index 000000000..26f9cf5f2 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/persistence/repository/SaasMigrationStatusRepository.java @@ -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 { + + List 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(); + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/queue/LayoutParsingFinishedMessageReceiver.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/queue/LayoutParsingFinishedMessageReceiver.java index 5a0bb92c2..fb43103a4 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/queue/LayoutParsingFinishedMessageReceiver.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/queue/LayoutParsingFinishedMessageReceiver.java @@ -1,25 +1,25 @@ 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.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.FileStatusService; 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.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.LayoutParsingRequest; - 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 java.time.OffsetDateTime; +import java.time.temporal.ChronoUnit; @Slf4j @Service @@ -30,12 +30,20 @@ public class LayoutParsingFinishedMessageReceiver { private final FileStatusProcessingUpdateService fileStatusProcessingUpdateService; private final ObjectMapper objectMapper; private final LayoutParsingRequestIdentifierService layoutParsingRequestIdentifierService; + private final SaasMigrationStatusPersistenceService saasMigrationStatusPersistenceService; + private final SaasMigrationService saasMigrationService; @SneakyThrows @RabbitListener(queues = LayoutParsingQueueNames.LAYOUT_PARSING_FINISHED_EVENT_QUEUE) 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()), layoutParsingRequestIdentifierService.parseFileId(response.identifier()), layoutParsingRequestIdentifierService.parsePriority(response.identifier())); @@ -53,6 +61,13 @@ public class LayoutParsingFinishedMessageReceiver { var analyzeRequest = objectMapper.readValue(failedMessage.getBody(), LayoutParsingRequest.class); log.info("Failed to process analyze request: {}", analyzeRequest); 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); timestamp = timestamp != null ? timestamp : OffsetDateTime.now().truncatedTo(ChronoUnit.MILLIS); log.info("Failed to process layout parsing request, errorCause: {}, timestamp: {}", errorCause, timestamp); diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/queue/RedactionServiceSaasMigrationMessageReceiver.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/queue/RedactionServiceSaasMigrationMessageReceiver.java new file mode 100644 index 000000000..a4ee11967 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/queue/RedactionServiceSaasMigrationMessageReceiver.java @@ -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); + + } + +} diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/db.changelog-tenant.yaml b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/db.changelog-tenant.yaml index 3992cf973..fabc20128 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/db.changelog-tenant.yaml +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/db.changelog-tenant.yaml @@ -166,4 +166,6 @@ databaseChangeLog: - include: file: db/changelog/tenant/112-modify-section-length.yaml - include: - file: db/changelog/tenant/114-add-download-redaction-file-status-table.yaml \ No newline at end of file + file: db/changelog/tenant/114-add-download-redaction-file-status-table.yaml + - include: + file: db/changelog/tenant/115-add-saas-migration-status-table.yaml \ No newline at end of file diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/115-add-saas-migration-status-table.yaml b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/db/changelog/tenant/115-add-saas-migration-status-table.yaml new file mode 100644 index 000000000..250758013 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/resources/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 + diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/dossiertemplate/dossier/file/SaasMigrationStatus.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/dossiertemplate/dossier/file/SaasMigrationStatus.java new file mode 100644 index 000000000..1ce683e0a --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/dossiertemplate/dossier/file/SaasMigrationStatus.java @@ -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 +} diff --git a/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/saas/migration/MigrationStatusResponse.java b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/saas/migration/MigrationStatusResponse.java new file mode 100644 index 000000000..ec3b28ea6 --- /dev/null +++ b/persistence-service-v1/persistence-service-shared-api-v1/src/main/java/com/iqser/red/service/persistence/service/v1/api/shared/model/saas/migration/MigrationStatusResponse.java @@ -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 filesInStatus = new HashMap<>(); + @Builder.Default + private Map errorCauses = new HashMap<>(); + +} diff --git a/persistence-service-v1/pom.xml b/persistence-service-v1/pom.xml index 51a38b5ce..1625a1844 100755 --- a/persistence-service-v1/pom.xml +++ b/persistence-service-v1/pom.xml @@ -31,7 +31,7 @@ - 4.157.0 + 4.165.0 2.71.0 4.29.0 4.13.0