From 3f02198dae197eaa2adc61a7d98d95b8c27b0295 Mon Sep 17 00:00:00 2001 From: karen-hedges <133129444+karen-hedges@users.noreply.github.com> Date: Tue, 28 Apr 2026 07:20:40 +0100 Subject: [PATCH 01/14] DMP-5486 Disable ARM connections Created environment variable to represent ARM down for maintenance --- charts/darts-api/values.dev.template.yaml | 3 +++ charts/darts-api/values.yaml | 2 ++ .../ArmDownForMaintenanceException.java | 7 ++++++ .../api/DataManagementFacade.java | 12 ++++++---- .../api/DataManagementFacadeImpl.java | 22 ++++++++++++++----- .../config/DataManagementConfiguration.java | 3 +++ src/main/resources/application.yaml | 2 ++ src/main/resources/openapi/common.yaml | 12 ++++++++++ 8 files changed, 53 insertions(+), 10 deletions(-) create mode 100644 src/main/java/uk/gov/hmcts/darts/arm/exception/ArmDownForMaintenanceException.java diff --git a/charts/darts-api/values.dev.template.yaml b/charts/darts-api/values.dev.template.yaml index 03b27f581c4..501d2c2c01e 100644 --- a/charts/darts-api/values.dev.template.yaml +++ b/charts/darts-api/values.dev.template.yaml @@ -135,6 +135,7 @@ java: SHEDLOCK_LOG_LEVEL: INFO ARM_RPO_TOTAL_CATCHUP_HOURS: 5 ARM_RPO_TOTAL_CATCHUP_MAX_HOURS_ENDING_POINT: 50 + ARM_DOWN_FOR_MAINTENANCE: false secrets: DARTS_API_DB_PASSWORD: secretRef: "postgres" @@ -168,6 +169,7 @@ darts-portal: DARTS_AZUREAD_B2C_ORIGIN_HOST: https://hmctsstgextid.b2clogin.com DARTS_AZUREAD_B2C_HOSTNAME: https://darts.staging.apps.hmcts.net MANUAL_DELETION_ENABLED: true + ARM_DOWN_FOR_MAINTENANCE: false darts-gateway: enabled: ${DEV_ENABLE_DARTS_GATEWAY} @@ -340,6 +342,7 @@ function: ENABLE_ARM_V5_2_UPGRADE: true ARM_RPO_TOTAL_CATCHUP_HOURS: 5 ARM_RPO_TOTAL_CATCHUP_MAX_HOURS_ENDING_POINT: 50 + ARM_DOWN_FOR_MAINTENANCE: false secrets: DARTS_API_DB_PASSWORD: diff --git a/charts/darts-api/values.yaml b/charts/darts-api/values.yaml index d7a597bf0fa..76ad27d5636 100644 --- a/charts/darts-api/values.yaml +++ b/charts/darts-api/values.yaml @@ -131,6 +131,7 @@ java: SHEDLOCK_LOG_LEVEL: INFO ARM_RPO_TOTAL_CATCHUP_HOURS: 5 ARM_RPO_TOTAL_CATCHUP_MAX_HOURS_ENDING_POINT: 50 + ARM_DOWN_FOR_MAINTENANCE: false function: scaleType: Job @@ -256,6 +257,7 @@ function: ARM_RPO_FEATURE_FLAG_LOGS_ENABLED: false DETS_TO_ARM_PUSH_FEATURE_FLAG_LOGS_ENABLED: false ARM_PULL_FEATURE_FLAG_LOGS_ENABLED: false + ARM_DOWN_FOR_MAINTENANCE: false secrets: DARTS_API_DB_CONNECTION_STRING: secretRef: darts-api-function-values diff --git a/src/main/java/uk/gov/hmcts/darts/arm/exception/ArmDownForMaintenanceException.java b/src/main/java/uk/gov/hmcts/darts/arm/exception/ArmDownForMaintenanceException.java new file mode 100644 index 00000000000..c49c80b5ff4 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/darts/arm/exception/ArmDownForMaintenanceException.java @@ -0,0 +1,7 @@ +package uk.gov.hmcts.darts.arm.exception; + +public class ArmDownForMaintenanceException extends Exception { + public ArmDownForMaintenanceException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/src/main/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacade.java b/src/main/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacade.java index 7ede0522c6a..fde5f6dae27 100644 --- a/src/main/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacade.java +++ b/src/main/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacade.java @@ -1,5 +1,6 @@ package uk.gov.hmcts.darts.common.datamanagement.api; +import uk.gov.hmcts.darts.arm.exception.ArmDownForMaintenanceException; import uk.gov.hmcts.darts.common.datamanagement.component.impl.DownloadResponseMetaData; import uk.gov.hmcts.darts.common.entity.AnnotationDocumentEntity; import uk.gov.hmcts.darts.common.entity.ExternalObjectDirectoryEntity; @@ -17,11 +18,14 @@ */ public interface DataManagementFacade { - DownloadResponseMetaData retrieveFileFromStorage(MediaEntity mediaEntity) throws FileNotDownloadedException; + DownloadResponseMetaData retrieveFileFromStorage(MediaEntity mediaEntity) throws FileNotDownloadedException, ArmDownForMaintenanceException; - DownloadResponseMetaData retrieveFileFromStorage(TranscriptionDocumentEntity transcriptionDocumentEntity) throws FileNotDownloadedException; + DownloadResponseMetaData retrieveFileFromStorage( + TranscriptionDocumentEntity transcriptionDocumentEntity) throws FileNotDownloadedException, ArmDownForMaintenanceException; - DownloadResponseMetaData retrieveFileFromStorage(AnnotationDocumentEntity annotationDocumentEntity) throws FileNotDownloadedException; + DownloadResponseMetaData retrieveFileFromStorage( + AnnotationDocumentEntity annotationDocumentEntity) throws FileNotDownloadedException, ArmDownForMaintenanceException; - DownloadResponseMetaData retrieveFileFromStorage(List eodEntities) throws FileNotDownloadedException; + DownloadResponseMetaData retrieveFileFromStorage( + List eodEntities) throws FileNotDownloadedException, ArmDownForMaintenanceException; } \ No newline at end of file diff --git a/src/main/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImpl.java b/src/main/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImpl.java index 51a1c38f28c..d614a8944a1 100644 --- a/src/main/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImpl.java +++ b/src/main/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImpl.java @@ -6,6 +6,7 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.io.FileUtils; import org.springframework.stereotype.Service; +import uk.gov.hmcts.darts.arm.exception.ArmDownForMaintenanceException; import uk.gov.hmcts.darts.arm.service.ArmApiService; import uk.gov.hmcts.darts.audio.helper.UnstructuredDataHelper; import uk.gov.hmcts.darts.common.datamanagement.component.impl.DownloadResponseMetaData; @@ -58,7 +59,8 @@ public class DataManagementFacadeImpl implements DataManagementFacade { private final ObjectRetrievalQueueRepository objectRetrievalQueueRepository; @Override - public DownloadResponseMetaData retrieveFileFromStorage(MediaEntity mediaEntity) throws FileNotDownloadedException { + public DownloadResponseMetaData retrieveFileFromStorage(MediaEntity mediaEntity) + throws FileNotDownloadedException, ArmDownForMaintenanceException { ObjectRecordStatusEntity storedStatus = objectRecordStatusRepository.getReferenceById(STORED.getId()); List storedEodEntities = externalObjectDirectoryRepository.findByEntityAndStatus(mediaEntity, storedStatus); if (CollectionUtils.isEmpty(storedEodEntities)) { @@ -82,7 +84,8 @@ public DownloadResponseMetaData retrieveFileFromStorage(MediaEntity mediaEntity) } @Override - public DownloadResponseMetaData retrieveFileFromStorage(TranscriptionDocumentEntity transcriptionDocumentEntity) throws FileNotDownloadedException { + public DownloadResponseMetaData retrieveFileFromStorage(TranscriptionDocumentEntity transcriptionDocumentEntity) + throws FileNotDownloadedException, ArmDownForMaintenanceException { ObjectRecordStatusEntity storedStatus = objectRecordStatusRepository.getReferenceById(STORED.getId()); List storedEodEntities = externalObjectDirectoryRepository.findByEntityAndStatus(transcriptionDocumentEntity, storedStatus); @@ -108,7 +111,8 @@ public DownloadResponseMetaData retrieveFileFromStorage(TranscriptionDocumentEnt } @Override - public DownloadResponseMetaData retrieveFileFromStorage(AnnotationDocumentEntity annotationDocumentEntity) throws FileNotDownloadedException { + public DownloadResponseMetaData retrieveFileFromStorage( + AnnotationDocumentEntity annotationDocumentEntity) throws FileNotDownloadedException, ArmDownForMaintenanceException { ObjectRecordStatusEntity storedStatus = objectRecordStatusRepository.getReferenceById(STORED.getId()); List storedEodEntities = externalObjectDirectoryRepository.findByEntityAndStatus(annotationDocumentEntity, storedStatus); if (CollectionUtils.isEmpty(storedEodEntities)) { @@ -125,7 +129,8 @@ public DownloadResponseMetaData retrieveFileFromStorage(AnnotationDocumentEntity } @Override - public DownloadResponseMetaData retrieveFileFromStorage(List eodEntities) throws FileNotDownloadedException { + public DownloadResponseMetaData retrieveFileFromStorage( + List eodEntities) throws FileNotDownloadedException, ArmDownForMaintenanceException { if (CollectionUtils.isEmpty(eodEntities)) { log.error("Supplied list of EodEntities is empty"); throw new FileNotDownloadedException("Supplied list of EodEntities is empty"); @@ -160,10 +165,11 @@ private DownloadResponseMetaData retrieveFileFromStorage(DatastoreContainerType } /** - * Loop through each storage type in order to see if it has a matched EodEntity, and if it does, try to download the file from there, if it fails, + * Loop through each storage type in order to see if it has a matched EodEntity, and if it does, try to download the file from there. If it fails, * move to the next one, if they all fail then throw a FileNotDownloadedException. */ - private DownloadResponseMetaData getDataFromStorage(List storedEodEntities) throws FileNotDownloadedException { + private DownloadResponseMetaData getDataFromStorage( + List storedEodEntities) throws FileNotDownloadedException, ArmDownForMaintenanceException { List storageOrder = storageOrderHelper.getStorageOrder(); StringBuilder logBuilder = new StringBuilder(134) .append("Starting to search for files with ") @@ -182,6 +188,10 @@ private DownloadResponseMetaData getDataFromStorage(List Date: Tue, 28 Apr 2026 08:37:18 +0100 Subject: [PATCH 02/14] DMP-5486 Disable ARM connections Created environment variable to represent ARM down for maintenance --- .../impl/AnnotationDataManagement.java | 6 ++++ .../hmcts/darts/arm/enums/ArmApiError.java | 31 +++++++++++++++++++ .../service/AudioTransformationService.java | 3 +- .../audio/service/impl/AudioServiceImpl.java | 5 +++ .../impl/AudioTransformationServiceImpl.java | 5 +-- .../service/impl/TranscriptionDownloader.java | 4 +++ .../impl/AnnotationDataManagementTest.java | 5 +-- .../impl/TranscriptionDownloaderTest.java | 10 +++--- 8 files changed, 59 insertions(+), 10 deletions(-) create mode 100644 src/main/java/uk/gov/hmcts/darts/arm/enums/ArmApiError.java diff --git a/src/main/java/uk/gov/hmcts/darts/annotation/service/impl/AnnotationDataManagement.java b/src/main/java/uk/gov/hmcts/darts/annotation/service/impl/AnnotationDataManagement.java index 67ce3d410a0..2ff2a3238e5 100644 --- a/src/main/java/uk/gov/hmcts/darts/annotation/service/impl/AnnotationDataManagement.java +++ b/src/main/java/uk/gov/hmcts/darts/annotation/service/impl/AnnotationDataManagement.java @@ -5,6 +5,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.Resource; import org.springframework.stereotype.Service; +import uk.gov.hmcts.darts.arm.exception.ArmDownForMaintenanceException; import uk.gov.hmcts.darts.common.datamanagement.api.DataManagementFacade; import uk.gov.hmcts.darts.common.datamanagement.component.impl.DownloadResponseMetaData; import uk.gov.hmcts.darts.common.entity.ExternalObjectDirectoryEntity; @@ -20,6 +21,7 @@ import static uk.gov.hmcts.darts.annotation.errors.AnnotationApiError.FAILED_TO_DOWNLOAD_ANNOTATION_DOCUMENT; import static uk.gov.hmcts.darts.annotation.errors.AnnotationApiError.FAILED_TO_UPLOAD_ANNOTATION_DOCUMENT; +import static uk.gov.hmcts.darts.arm.enums.ArmApiError.ARM_DOWN_FOR_MAINTENANCE; import static uk.gov.hmcts.darts.common.enums.ExternalLocationTypeEnum.INBOUND; import static uk.gov.hmcts.darts.common.enums.ExternalLocationTypeEnum.UNSTRUCTURED; @@ -58,6 +60,10 @@ public Resource download(List externalObjectDirec DownloadResponseMetaData downloadResponseMetaData = dataManagementFacade.retrieveFileFromStorage(externalObjectDirectoryEntities); return downloadResponseMetaData.getResource(); + } catch (ArmDownForMaintenanceException e) { + log.error("ARM is down for maintenance, failed to download annotation document {}", + externalObjectDirectoryEntities.getFirst().getAnnotationDocumentEntity().getId(), e); + throw new DartsApiException(ARM_DOWN_FOR_MAINTENANCE, e); } catch (IOException | FileNotDownloadedException e) { log.error("Failed to download annotation document {}", externalObjectDirectoryEntities.getFirst().getAnnotationDocumentEntity().getId(), e); diff --git a/src/main/java/uk/gov/hmcts/darts/arm/enums/ArmApiError.java b/src/main/java/uk/gov/hmcts/darts/arm/enums/ArmApiError.java new file mode 100644 index 00000000000..a03fa64da56 --- /dev/null +++ b/src/main/java/uk/gov/hmcts/darts/arm/enums/ArmApiError.java @@ -0,0 +1,31 @@ +package uk.gov.hmcts.darts.arm.enums; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import uk.gov.hmcts.darts.common.exception.DartsApiError; +import uk.gov.hmcts.darts.common.model.ArmErrorCode; +import uk.gov.hmcts.darts.common.model.ArmTitleErrors; + +@Getter +@RequiredArgsConstructor +public enum ArmApiError implements DartsApiError { + + ARM_DOWN_FOR_MAINTENANCE( + ArmErrorCode.ARM_DOWN_FOR_MAINTENTANCE.getValue(), + HttpStatus.NOT_IMPLEMENTED, + ArmTitleErrors.ARM_DOWN_FOR_MAINTENTANCE.getValue() + ); + + private static final String ERROR_TYPE_PREFIX = "ARM"; + + private final String errorTypeNumeric; + private final HttpStatus httpStatus; + private final String title; + + @Override + public String getErrorTypePrefix() { + return ERROR_TYPE_PREFIX; + } + +} diff --git a/src/main/java/uk/gov/hmcts/darts/audio/service/AudioTransformationService.java b/src/main/java/uk/gov/hmcts/darts/audio/service/AudioTransformationService.java index cb9f2bd811c..a7055b7d9b4 100644 --- a/src/main/java/uk/gov/hmcts/darts/audio/service/AudioTransformationService.java +++ b/src/main/java/uk/gov/hmcts/darts/audio/service/AudioTransformationService.java @@ -1,5 +1,6 @@ package uk.gov.hmcts.darts.audio.service; +import uk.gov.hmcts.darts.arm.exception.ArmDownForMaintenanceException; import uk.gov.hmcts.darts.common.entity.MediaEntity; import java.io.IOException; @@ -18,7 +19,7 @@ List filterMediaByMediaRequestTimeframeAndSortByStartTimeAndChannel OffsetDateTime startTime, OffsetDateTime endTime); - Path retrieveFromStorageAndSaveToTempWorkspace(MediaEntity mediaEntity) throws IOException; + Path retrieveFromStorageAndSaveToTempWorkspace(MediaEntity mediaEntity) throws IOException, ArmDownForMaintenanceException; void handleKedaInvocationForMediaRequests(); diff --git a/src/main/java/uk/gov/hmcts/darts/audio/service/impl/AudioServiceImpl.java b/src/main/java/uk/gov/hmcts/darts/audio/service/impl/AudioServiceImpl.java index 506451d36a6..637f68f6080 100644 --- a/src/main/java/uk/gov/hmcts/darts/audio/service/impl/AudioServiceImpl.java +++ b/src/main/java/uk/gov/hmcts/darts/audio/service/impl/AudioServiceImpl.java @@ -4,6 +4,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import uk.gov.hmcts.darts.arm.enums.ArmApiError; +import uk.gov.hmcts.darts.arm.exception.ArmDownForMaintenanceException; import uk.gov.hmcts.darts.audio.component.AudioBeingProcessedFromArchiveQuery; import uk.gov.hmcts.darts.audio.exception.AudioApiError; import uk.gov.hmcts.darts.audio.model.AudioBeingProcessedFromArchiveQueryResult; @@ -71,6 +73,9 @@ public BinaryData encode(Long mediaId) { Path encodedAudioPath = encodedAudioFileInfo.getPath(); mediaBinaryData = fileOperationService.convertFileToBinaryData(encodedAudioPath.toFile().getAbsolutePath()); + + } catch (ArmDownForMaintenanceException e) { + throw new DartsApiException(ArmApiError.ARM_DOWN_FOR_MAINTENANCE, e); } catch (InterruptedException exception) { Thread.currentThread().interrupt(); throw new DartsApiException(AudioApiError.FAILED_TO_PROCESS_AUDIO_REQUEST, exception); diff --git a/src/main/java/uk/gov/hmcts/darts/audio/service/impl/AudioTransformationServiceImpl.java b/src/main/java/uk/gov/hmcts/darts/audio/service/impl/AudioTransformationServiceImpl.java index 5fe3afcd8ec..b544bb5afce 100644 --- a/src/main/java/uk/gov/hmcts/darts/audio/service/impl/AudioTransformationServiceImpl.java +++ b/src/main/java/uk/gov/hmcts/darts/audio/service/impl/AudioTransformationServiceImpl.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import uk.gov.hmcts.darts.arm.exception.ArmDownForMaintenanceException; import uk.gov.hmcts.darts.arm.service.ExternalObjectDirectoryService; import uk.gov.hmcts.darts.audio.component.OutboundFileProcessor; import uk.gov.hmcts.darts.audio.component.OutboundFileZipGenerator; @@ -256,7 +257,7 @@ public List filterMediaByMediaRequestTimeframeAndSortByStartTimeAnd } private Map downloadAndSaveMediaToWorkspace(List mediaEntitiesForRequest) - throws IOException { + throws IOException, ArmDownForMaintenanceException { Map downloadedMedias = new LinkedHashMap<>(); for (MediaEntity mediaEntity : mediaEntitiesForRequest) { Path downloadPath = retrieveFromStorageAndSaveToTempWorkspace(mediaEntity); @@ -268,7 +269,7 @@ private Map downloadAndSaveMediaToWorkspace(List @Override @SuppressWarnings({"PMD.AvoidThrowingRawExceptionTypes"}) - public Path retrieveFromStorageAndSaveToTempWorkspace(MediaEntity mediaEntity) throws IOException { + public Path retrieveFromStorageAndSaveToTempWorkspace(MediaEntity mediaEntity) throws IOException, ArmDownForMaintenanceException { try (DownloadResponseMetaData downloadResponseMetaData = dataManagementFacade.retrieveFileFromStorage(mediaEntity)) { String id = downloadResponseMetaData.getEodEntity().getExternalLocation(); diff --git a/src/main/java/uk/gov/hmcts/darts/transcriptions/service/impl/TranscriptionDownloader.java b/src/main/java/uk/gov/hmcts/darts/transcriptions/service/impl/TranscriptionDownloader.java index fcea5162ca9..a34ecfc97ad 100644 --- a/src/main/java/uk/gov/hmcts/darts/transcriptions/service/impl/TranscriptionDownloader.java +++ b/src/main/java/uk/gov/hmcts/darts/transcriptions/service/impl/TranscriptionDownloader.java @@ -4,6 +4,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.core.io.Resource; import org.springframework.stereotype.Service; +import uk.gov.hmcts.darts.arm.enums.ArmApiError; +import uk.gov.hmcts.darts.arm.exception.ArmDownForMaintenanceException; import uk.gov.hmcts.darts.audit.api.AuditApi; import uk.gov.hmcts.darts.authorisation.component.UserIdentity; import uk.gov.hmcts.darts.common.datamanagement.api.DataManagementFacade; @@ -68,6 +70,8 @@ private Resource getResourceStreamFor(TranscriptionDocumentEntity latestTranscri try { DownloadResponseMetaData downloadResponseMetaData = dataManagementFacade.retrieveFileFromStorage(latestTranscriptionDocument); return downloadResponseMetaData.getResource(); + } catch (ArmDownForMaintenanceException e) { + throw new DartsApiException(ArmApiError.ARM_DOWN_FOR_MAINTENANCE, e); } catch (IOException | FileNotDownloadedException ex) { log.error("Failed to download transcript file using latestTranscriptionDocument ID {}", latestTranscriptionDocument.getId(), diff --git a/src/test/java/uk/gov/hmcts/darts/annotation/service/impl/AnnotationDataManagementTest.java b/src/test/java/uk/gov/hmcts/darts/annotation/service/impl/AnnotationDataManagementTest.java index cabab182d26..79e40a1eab9 100644 --- a/src/test/java/uk/gov/hmcts/darts/annotation/service/impl/AnnotationDataManagementTest.java +++ b/src/test/java/uk/gov/hmcts/darts/annotation/service/impl/AnnotationDataManagementTest.java @@ -6,6 +6,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import uk.gov.hmcts.darts.arm.exception.ArmDownForMaintenanceException; import uk.gov.hmcts.darts.common.datamanagement.api.DataManagementFacade; import uk.gov.hmcts.darts.common.datamanagement.component.impl.DownloadResponseMetaData; import uk.gov.hmcts.darts.common.datamanagement.component.impl.FileBasedDownloadResponseMetaData; @@ -120,7 +121,7 @@ void throwsWhenDeleteFails() throws AzureDeleteBlobException { } @Test - void throwsIfDownloadAnnotationDocumentResponseFails() throws FileNotDownloadedException { + void throwsIfDownloadAnnotationDocumentResponseFails() throws FileNotDownloadedException, ArmDownForMaintenanceException { when(dataManagementFacade.retrieveFileFromStorage(anyList())).thenThrow(new FileNotDownloadedException()); assertThatThrownBy(() -> annotationDataManagement.download(Arrays.asList(someExternalObjectDirectoryEntity()))) .isInstanceOf(DartsApiException.class) @@ -129,7 +130,7 @@ void throwsIfDownloadAnnotationDocumentResponseFails() throws FileNotDownloadedE @Test @SuppressWarnings("PMD.CloseResource") - void throwsIfDownloadAnnotationDocumentInputStreamFails() throws FileNotDownloadedException, IOException { + void throwsIfDownloadAnnotationDocumentInputStreamFails() throws FileNotDownloadedException, IOException, ArmDownForMaintenanceException { var mockFileBasedDownloadResponseMetaData = mock(FileBasedDownloadResponseMetaData.class); when(dataManagementFacade.retrieveFileFromStorage(anyList())).thenReturn(mockFileBasedDownloadResponseMetaData); diff --git a/src/test/java/uk/gov/hmcts/darts/transcriptions/service/impl/TranscriptionDownloaderTest.java b/src/test/java/uk/gov/hmcts/darts/transcriptions/service/impl/TranscriptionDownloaderTest.java index 792827cb3ee..9ec704638a8 100644 --- a/src/test/java/uk/gov/hmcts/darts/transcriptions/service/impl/TranscriptionDownloaderTest.java +++ b/src/test/java/uk/gov/hmcts/darts/transcriptions/service/impl/TranscriptionDownloaderTest.java @@ -7,6 +7,7 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.core.io.Resource; +import uk.gov.hmcts.darts.arm.exception.ArmDownForMaintenanceException; import uk.gov.hmcts.darts.audit.api.AuditApi; import uk.gov.hmcts.darts.authorisation.component.UserIdentity; import uk.gov.hmcts.darts.common.datamanagement.api.DataManagementFacade; @@ -104,7 +105,7 @@ void throwsExceptionIfTranscriptionHasNoTranscriptionDocuments() { } @Test - void throwsExceptionIfTranscriptionDocumentHasNoExternalObjectDirectories() throws IOException, FileNotDownloadedException { + void throwsExceptionIfTranscriptionDocumentHasNoExternalObjectDirectories() throws FileNotDownloadedException, ArmDownForMaintenanceException { var transcriptionDocument = someTranscriptionDocumentWithUploadDate(now()); transcriptionDocument.setExternalObjectDirectoryEntities(emptyList()); @@ -123,7 +124,7 @@ void throwsExceptionIfTranscriptionDocumentHasNoExternalObjectDirectories() thro @Test - void throwsExceptionIfFailsToGetDownloadResponseInputStream() throws IOException, FileNotDownloadedException { + void throwsExceptionIfFailsToGetDownloadResponseInputStream() throws IOException, FileNotDownloadedException, ArmDownForMaintenanceException { var transcriptionDocument = someTranscriptionDocumentWithUploadDate(now()); transcriptionDocument.setExternalObjectDirectoryEntities(List.of(someExternalObjectDirectoryWithCreationDate(now()))); @@ -143,7 +144,7 @@ void throwsExceptionIfFailsToGetDownloadResponseInputStream() throws IOException } @Test - void retrievesTranscriptionFromUnstructuredContainer() throws IOException, FileNotDownloadedException { + void retrievesTranscriptionFromUnstructuredContainer() throws IOException, FileNotDownloadedException, ArmDownForMaintenanceException { // Given var inboundExternalObjectDirectoryCreatedToday = someExternalObjectDirectoryWithCreationDate(now()); inboundExternalObjectDirectoryCreatedToday.setExternalLocationType(externalLocationTypeFor(INBOUND)); @@ -160,7 +161,6 @@ void retrievesTranscriptionFromUnstructuredContainer() throws IOException, FileN when(transcriptionRepository.findById(transcription.getId())).thenReturn(Optional.of(transcription)); when(dataManagementFacade.retrieveFileFromStorage(any(TranscriptionDocumentEntity.class))).thenReturn(fileBasedDownloadResponseMetaData); - Resource resource = Mockito.mock(Resource.class); when(fileBasedDownloadResponseMetaData.getResource()).thenReturn(resource); @@ -197,7 +197,7 @@ void throwsNotFoundExceptionIfTranscriptionDocumentHiddenAndUserIsNotSuperAdmin( } @Test - void downloadsDocumentIfTranscriptionDocumentHiddenAndUserIsSuperAdmin() throws FileNotDownloadedException, IOException { + void downloadsDocumentIfTranscriptionDocumentHiddenAndUserIsSuperAdmin() throws FileNotDownloadedException, IOException, ArmDownForMaintenanceException { when(userIdentity.userHasGlobalAccess(Set.of(SUPER_ADMIN))).thenReturn(true); var transcriptionDocuments = someTranscriptionDocumentsUploadedAtLeast2DaysAgo(1); From 2289c32ac3215e7def20e417d2d32ddf08168507 Mon Sep 17 00:00:00 2001 From: karen-hedges <133129444+karen-hedges@users.noreply.github.com> Date: Tue, 28 Apr 2026 11:45:32 +0100 Subject: [PATCH 03/14] DMP-5486 Disable ARM connections Created environment variable to represent ARM down for maintenance --- .../common/datamanagement/api/DataManagementFacadeImpl.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImpl.java b/src/main/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImpl.java index d614a8944a1..954f3f607ab 100644 --- a/src/main/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImpl.java +++ b/src/main/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImpl.java @@ -38,6 +38,7 @@ import static java.util.Objects.nonNull; import static uk.gov.hmcts.darts.common.datamanagement.enums.DatastoreContainerType.ARM; +import static uk.gov.hmcts.darts.common.datamanagement.enums.DatastoreContainerType.UNSTRUCTURED; import static uk.gov.hmcts.darts.common.enums.ObjectRecordStatusEnum.STORED; @Slf4j @@ -168,6 +169,7 @@ private DownloadResponseMetaData retrieveFileFromStorage(DatastoreContainerType * Loop through each storage type in order to see if it has a matched EodEntity, and if it does, try to download the file from there. If it fails, * move to the next one, if they all fail then throw a FileNotDownloadedException. */ + @SuppressWarnings("PMD.CyclomaticComplexity") private DownloadResponseMetaData getDataFromStorage( List storedEodEntities) throws FileNotDownloadedException, ArmDownForMaintenanceException { List storageOrder = storageOrderHelper.getStorageOrder(); @@ -189,10 +191,10 @@ private DownloadResponseMetaData getDataFromStorage( continue; } if (dataManagementConfiguration.getArmDownForMaintenance() - && datastoreContainerType.equals(DatastoreContainerType.ARM)) { + && datastoreContainerType.equals(ARM)) { throw new ArmDownForMaintenanceException("ARM is currently down for maintenance, cannot download files from ARM at this time"); } - if (datastoreContainerType.equals(DatastoreContainerType.UNSTRUCTURED)) { + if (datastoreContainerType.equals(UNSTRUCTURED)) { eodEntityToDelete = eodEntity; } Optional container = getSupportedContainer(datastoreContainerType); From 27c4f6dd2b057a4f01be65dbb7c1681965140302 Mon Sep 17 00:00:00 2001 From: karen-hedges <133129444+karen-hedges@users.noreply.github.com> Date: Thu, 30 Apr 2026 09:57:47 +0100 Subject: [PATCH 04/14] DMP-5486 Disable ARM connections Created environment variable to represent ARM down for maintenance --- src/main/java/uk/gov/hmcts/darts/arm/enums/ArmApiError.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/uk/gov/hmcts/darts/arm/enums/ArmApiError.java b/src/main/java/uk/gov/hmcts/darts/arm/enums/ArmApiError.java index a03fa64da56..783fa3941f1 100644 --- a/src/main/java/uk/gov/hmcts/darts/arm/enums/ArmApiError.java +++ b/src/main/java/uk/gov/hmcts/darts/arm/enums/ArmApiError.java @@ -13,7 +13,7 @@ public enum ArmApiError implements DartsApiError { ARM_DOWN_FOR_MAINTENANCE( ArmErrorCode.ARM_DOWN_FOR_MAINTENTANCE.getValue(), - HttpStatus.NOT_IMPLEMENTED, + HttpStatus.SERVICE_UNAVAILABLE, ArmTitleErrors.ARM_DOWN_FOR_MAINTENTANCE.getValue() ); From 2839d0af1edc209476412e4f1b843766470a523e Mon Sep 17 00:00:00 2001 From: karen-hedges <133129444+karen-hedges@users.noreply.github.com> Date: Mon, 11 May 2026 17:25:03 +0100 Subject: [PATCH 05/14] DMP-5486 Disable ARM connections Created environment variable to represent ARM down for maintenance --- .../datamanagement/config/DataManagementConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/uk/gov/hmcts/darts/datamanagement/config/DataManagementConfiguration.java b/src/main/java/uk/gov/hmcts/darts/datamanagement/config/DataManagementConfiguration.java index 53bf649a771..ce6d26ff9ff 100644 --- a/src/main/java/uk/gov/hmcts/darts/datamanagement/config/DataManagementConfiguration.java +++ b/src/main/java/uk/gov/hmcts/darts/datamanagement/config/DataManagementConfiguration.java @@ -60,7 +60,7 @@ public class DataManagementConfiguration extends StorageConfiguration { @Value("${darts.storage.blob.az-copy-output-level}") private String azCopyOutputLevel; - @Value("${darts.storage.arm-down-for-maintenance}") + @Value("${darts.storage.blob.arm-down-for-maintenance}") private Boolean armDownForMaintenance; @Override From 4a330950a06807eca6a8b4e992dfd46094885eb2 Mon Sep 17 00:00:00 2001 From: karen-hedges <133129444+karen-hedges@users.noreply.github.com> Date: Wed, 13 May 2026 11:54:46 +0100 Subject: [PATCH 06/14] DMP-5486 Disable ARM connections Created environment variable to represent ARM down for maintenance --- .../hmcts/darts/arm/enums/ArmApiError.java | 1 + .../helper/UnstructuredDataHelperTest.java | 144 +++++++ .../api/DataManagementFacadeImplTest.java | 387 ++++++++++++------ 3 files changed, 406 insertions(+), 126 deletions(-) create mode 100644 src/test/java/uk/gov/hmcts/darts/audio/helper/UnstructuredDataHelperTest.java diff --git a/src/main/java/uk/gov/hmcts/darts/arm/enums/ArmApiError.java b/src/main/java/uk/gov/hmcts/darts/arm/enums/ArmApiError.java index 783fa3941f1..9cda743d470 100644 --- a/src/main/java/uk/gov/hmcts/darts/arm/enums/ArmApiError.java +++ b/src/main/java/uk/gov/hmcts/darts/arm/enums/ArmApiError.java @@ -9,6 +9,7 @@ @Getter @RequiredArgsConstructor +@SuppressWarnings("java:S6548") public enum ArmApiError implements DartsApiError { ARM_DOWN_FOR_MAINTENANCE( diff --git a/src/test/java/uk/gov/hmcts/darts/audio/helper/UnstructuredDataHelperTest.java b/src/test/java/uk/gov/hmcts/darts/audio/helper/UnstructuredDataHelperTest.java new file mode 100644 index 00000000000..a9d9e6959e8 --- /dev/null +++ b/src/test/java/uk/gov/hmcts/darts/audio/helper/UnstructuredDataHelperTest.java @@ -0,0 +1,144 @@ +package uk.gov.hmcts.darts.audio.helper; + +import com.azure.core.util.BinaryData; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import uk.gov.hmcts.darts.common.entity.ExternalLocationTypeEntity; +import uk.gov.hmcts.darts.common.entity.ExternalObjectDirectoryEntity; +import uk.gov.hmcts.darts.common.entity.MediaEntity; +import uk.gov.hmcts.darts.common.entity.ObjectRecordStatusEntity; +import uk.gov.hmcts.darts.common.entity.UserAccountEntity; +import uk.gov.hmcts.darts.common.enums.ExternalLocationTypeEnum; +import uk.gov.hmcts.darts.common.enums.ObjectRecordStatusEnum; +import uk.gov.hmcts.darts.common.enums.SystemUsersEnum; +import uk.gov.hmcts.darts.common.repository.ExternalLocationTypeRepository; +import uk.gov.hmcts.darts.common.repository.ExternalObjectDirectoryRepository; +import uk.gov.hmcts.darts.common.repository.ObjectRecordStatusRepository; +import uk.gov.hmcts.darts.common.repository.UserAccountRepository; +import uk.gov.hmcts.darts.datamanagement.config.DataManagementConfiguration; +import uk.gov.hmcts.darts.datamanagement.model.BlobClientUploadResponseImpl; +import uk.gov.hmcts.darts.datamanagement.service.DataManagementService; + +import java.io.InputStream; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class UnstructuredDataHelperTest { + + @Mock + private ExternalObjectDirectoryRepository externalObjectDirectoryRepository; + @Mock + private ObjectRecordStatusRepository objectRecordStatusRepository; + @Mock + private ExternalLocationTypeRepository externalLocationTypeRepository; + @Mock + private UserAccountRepository userAccountRepository; + @Mock + private DataManagementService dataManagementService; + @Mock + private DataManagementConfiguration dataManagementConfiguration; + @Mock + private BlobClientUploadResponseImpl blobClientUploadResponseImpl; + + private UnstructuredDataHelper unstructuredDataHelper; + + @BeforeEach + void setUp() { + unstructuredDataHelper = new UnstructuredDataHelper( + externalObjectDirectoryRepository, + objectRecordStatusRepository, + externalLocationTypeRepository, + userAccountRepository, + dataManagementService, + dataManagementConfiguration + ); + } + + @Test + void createUnstructuredDataFromEod_shouldCreateAndDeleteRecords() { + when(dataManagementConfiguration.getUnstructuredContainerName()).thenReturn("unstructured"); + when(dataManagementService.saveBlobData(anyString(), any(InputStream.class))).thenReturn(blobClientUploadResponseImpl); + when(blobClientUploadResponseImpl.getBlobName()).thenReturn("blob-id"); + + ObjectRecordStatusEntity storedStatus = new ObjectRecordStatusEntity(); + storedStatus.setId(ObjectRecordStatusEnum.STORED.getId()); + when(objectRecordStatusRepository.getReferenceById(ObjectRecordStatusEnum.STORED.getId())).thenReturn(storedStatus); + + ExternalLocationTypeEntity unstructuredType = new ExternalLocationTypeEntity(); + unstructuredType.setId(ExternalLocationTypeEnum.UNSTRUCTURED.getId()); + when(externalLocationTypeRepository.getReferenceById(ExternalLocationTypeEnum.UNSTRUCTURED.getId())).thenReturn(unstructuredType); + + UserAccountEntity systemUser = new UserAccountEntity(); + systemUser.setId(SystemUsersEnum.DEFAULT.getId()); + when(userAccountRepository.getReferenceById(SystemUsersEnum.DEFAULT.getId())).thenReturn(systemUser); + + MediaEntity mediaEntity = new MediaEntity(); + ExternalObjectDirectoryEntity eodEntity = new ExternalObjectDirectoryEntity(); + eodEntity.setMedia(mediaEntity); + ExternalObjectDirectoryEntity eodEntityToDelete = new ExternalObjectDirectoryEntity(); + eodEntityToDelete.setMedia(mediaEntity); + + BinaryData data = BinaryData.fromString("Test String"); + + boolean created = unstructuredDataHelper.createUnstructuredDataFromEod( + eodEntityToDelete, + eodEntity, + data.toStream() + ); + + assertTrue(created); + verify(externalObjectDirectoryRepository).save(any(ExternalObjectDirectoryEntity.class)); + verify(externalObjectDirectoryRepository).delete(eq(eodEntityToDelete)); + } + + @Test + void createUnstructuredDataFromEod_whenUploadThrows_shouldReturnFalseAndSkipDbUpdates() { + when(dataManagementConfiguration.getUnstructuredContainerName()).thenReturn("unstructured"); + when(dataManagementService.saveBlobData(anyString(), any(InputStream.class))) + .thenThrow(new RuntimeException("upload failed")); + + ExternalObjectDirectoryEntity eodEntity = new ExternalObjectDirectoryEntity(); + ExternalObjectDirectoryEntity eodEntityToDelete = new ExternalObjectDirectoryEntity(); + + boolean created = unstructuredDataHelper.createUnstructuredDataFromEod( + eodEntityToDelete, + eodEntity, + BinaryData.fromString("Test String").toStream() + ); + + assertFalse(created); + verify(externalObjectDirectoryRepository, never()).save(any(ExternalObjectDirectoryEntity.class)); + verify(externalObjectDirectoryRepository, never()).delete(any(ExternalObjectDirectoryEntity.class)); + } + + @Test + void createUnstructuredDataFromEod_whenBlobNameMissing_shouldReturnFalse() { + when(dataManagementConfiguration.getUnstructuredContainerName()).thenReturn("unstructured"); + when(dataManagementService.saveBlobData(anyString(), any(InputStream.class))).thenReturn(blobClientUploadResponseImpl); + when(blobClientUploadResponseImpl.getBlobName()).thenReturn(null); + + ExternalObjectDirectoryEntity eodEntity = new ExternalObjectDirectoryEntity(); + ExternalObjectDirectoryEntity eodEntityToDelete = new ExternalObjectDirectoryEntity(); + + boolean created = unstructuredDataHelper.createUnstructuredDataFromEod( + eodEntityToDelete, + eodEntity, + BinaryData.fromString("Test String").toStream() + ); + + assertFalse(created); + verify(externalObjectDirectoryRepository, never()).save(any(ExternalObjectDirectoryEntity.class)); + verify(externalObjectDirectoryRepository, never()).delete(any(ExternalObjectDirectoryEntity.class)); + } +} \ No newline at end of file diff --git a/src/test/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImplTest.java b/src/test/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImplTest.java index 1b948bb8e76..ac43e4acb28 100644 --- a/src/test/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImplTest.java +++ b/src/test/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImplTest.java @@ -15,6 +15,7 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.core.io.Resource; +import uk.gov.hmcts.darts.arm.exception.ArmDownForMaintenanceException; import uk.gov.hmcts.darts.arm.service.impl.ArmApiServiceImpl; import uk.gov.hmcts.darts.audio.helper.UnstructuredDataHelper; import uk.gov.hmcts.darts.common.datamanagement.component.impl.DownloadResponseMetaData; @@ -70,6 +71,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -81,9 +83,10 @@ @Slf4j class DataManagementFacadeImplTest { - private static final String SOME_TEMP_WORKSPACE = "some/temp/workspace"; private static final String DOWNLOAD_RESPONSE_META_DATA = "DownloadResponseMetaData: {}"; + private String tempWorkspace; + @Mock private ExternalObjectDirectoryRepository externalObjectDirectoryRepository; @Mock @@ -121,7 +124,8 @@ class DataManagementFacadeImplTest { @SneakyThrows @BeforeEach void setup() { - Files.createDirectories(Paths.get(SOME_TEMP_WORKSPACE)); + tempWorkspace = tempDirectory.toPath().resolve("workspace").toString(); + Files.createDirectories(Paths.get(tempWorkspace)); List datastoreOrder = new ArrayList<>(); datastoreOrder.add(DatastoreContainerType.UNSTRUCTURED); datastoreOrder.add(DatastoreContainerType.DETS); @@ -156,7 +160,7 @@ void setup() { lenient().when(objectRecordStatusRepository.getReferenceById(anyInt())).thenReturn(storedStatus); - lenient().when(dataManagementConfiguration.getTempBlobWorkspace()).thenReturn("/tmp"); + lenient().when(dataManagementConfiguration.getTempBlobWorkspace()).thenReturn(tempWorkspace); lenient().when(resource.getInputStream()).thenReturn(toInputStream("testInputStream", UTF_8)); lenient().when(downloadResponseMetaDataMock.getResource()).thenReturn(resource); lenient().when(downloadResponseMetaDataMock.getContainerTypeUsedToDownload()).thenReturn(DatastoreContainerType.ARM); @@ -169,14 +173,14 @@ public void teardown() throws IOException { downloadResponseMetaData.close(); FileStore.getFileStore().remove(); - FileUtils.cleanDirectory(new File(SOME_TEMP_WORKSPACE)); + FileUtils.deleteQuietly(new File(tempWorkspace)); try (Stream files = Files.list(tempDirectory.toPath())) { assertEquals(0, files.count()); } } @Test - void testDownloadOfFacadeWithArm() throws Exception { + void retrieveFileFromStorage_shouldDownloadFacadeWithArm() throws Exception { final List blobContainerDownloadables = new ArrayList<>(); @@ -194,18 +198,20 @@ void testDownloadOfFacadeWithArm() throws Exception { when(armApiService.downloadArmData(arm.getExternalRecordId(), arm.getExternalFileId())).thenReturn(downloadResponseMetaDataMock); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelperTest, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelperTest, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); // make the assertion on the response - try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dmFacade.retrieveFileFromStorage(entitiesToDownload)) { + try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dataManagementFacade.retrieveFileFromStorage(entitiesToDownload)) { assertEquals(DatastoreContainerType.ARM, downloadResponseMetaDataAutoClose.getContainerTypeUsedToDownload()); } } @Test - void testDownloadOfFacadeWithUnstructured() throws Exception { + void retrieveFileFromStorage_shouldDownloadFacadeWithUnstructured() throws Exception { final List blobContainerDownloadables = new ArrayList<>(); BlobContainerDownloadable downloadable = mock(BlobContainerDownloadable.class); @@ -218,18 +224,20 @@ void testDownloadOfFacadeWithUnstructured() throws Exception { List entitiesToDownload = List.of(dets); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); // make the assertion on the response - try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dmFacade.retrieveFileFromStorage(entitiesToDownload)) { + try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dataManagementFacade.retrieveFileFromStorage(entitiesToDownload)) { assertEquals(DatastoreContainerType.UNSTRUCTURED, downloadResponseMetaDataAutoClose.getContainerTypeUsedToDownload()); } } @Test - void testThrowErrorNoStoredEodEntities() { + void retrieveFileFromStorage_shouldThrowError_WhenNoStoredEodEntities() { final List blobContainerDownloadables = new ArrayList<>(); BlobContainerDownloadable downloadable = mock(BlobContainerDownloadable.class); @@ -241,15 +249,17 @@ void testThrowErrorNoStoredEodEntities() { List entitiesToDownload = List.of(dets); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); // make the assertion on the response var exception = assertThrows( FileNotDownloadedException.class, () -> { - try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dmFacade.retrieveFileFromStorage(entitiesToDownload)) { + try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dataManagementFacade.retrieveFileFromStorage(entitiesToDownload)) { // add for try close with resources log.info(DOWNLOAD_RESPONSE_META_DATA, downloadResponseMetaDataAutoClose); } @@ -260,7 +270,7 @@ void testThrowErrorNoStoredEodEntities() { } @Test - void testDownloadOfFacadeWithDetsEnabled() throws Exception { + void downloadOfFacadeWithDetsEnabled() throws Exception { final List blobContainerDownloadables = new ArrayList<>(); BlobContainerDownloadable downloadable = mock(BlobContainerDownloadable.class); @@ -273,18 +283,20 @@ void testDownloadOfFacadeWithDetsEnabled() throws Exception { List entitiesToDownload = List.of(dets); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); // make the assertion on the response - try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dmFacade.retrieveFileFromStorage(entitiesToDownload)) { + try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dataManagementFacade.retrieveFileFromStorage(entitiesToDownload)) { assertEquals(DatastoreContainerType.DETS, downloadResponseMetaDataAutoClose.getContainerTypeUsedToDownload()); } } @Test - void testDownloadOfFacadeWithNoneProcessed() throws Exception { + void downloadOfFacadeWithNoneProcessed() throws Exception { final List blobContainerDownloadables = new ArrayList<>(); blobContainerDownloadables.add(setupDownloadableContainer(DatastoreContainerType.INBOUND, false)); @@ -298,15 +310,17 @@ void testDownloadOfFacadeWithNoneProcessed() throws Exception { List entitiesToDownload = List.of(inboundEntity); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); // make the assertion on the response var exception = assertThrows( FileNotDownloadedException.class, () -> { - try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dmFacade.retrieveFileFromStorage(entitiesToDownload)) { + try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dataManagementFacade.retrieveFileFromStorage(entitiesToDownload)) { // add for try close with resources log.info(DOWNLOAD_RESPONSE_META_DATA, downloadResponseMetaDataAutoClose); } @@ -317,7 +331,7 @@ void testDownloadOfFacadeWithNoneProcessed() throws Exception { } @Test - void testDownloadOfFacadeWithUnstructuredAndArmProcessedInPriorityOrder() throws Exception { + void downloadOfFacadeWithUnstructuredAndArmProcessedInPriorityOrder() throws Exception { final List blobContainerDownloadables = new ArrayList<>(); blobContainerDownloadables.add(setupDownloadableContainer(DatastoreContainerType.ARM, false)); @@ -331,15 +345,17 @@ void testDownloadOfFacadeWithUnstructuredAndArmProcessedInPriorityOrder() throws when(armApiService.downloadArmData(any(), any())).thenThrow(FileNotDownloadedException.class); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); // make the assertion on the response var exception = assertThrows( FileNotDownloadedException.class, () -> { - try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dmFacade.retrieveFileFromStorage(entitiesToDownload)) { + try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dataManagementFacade.retrieveFileFromStorage(entitiesToDownload)) { // add for try close with resources log.info(DOWNLOAD_RESPONSE_META_DATA, downloadResponseMetaDataAutoClose); } @@ -357,15 +373,17 @@ void retrieveFileFromStorageListEmpty() throws Exception { List entitiesToDownload = new ArrayList<>(); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); // make the assertion on the response var exception = assertThrows( FileNotDownloadedException.class, () -> { - try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dmFacade.retrieveFileFromStorage(entitiesToDownload)) { + try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dataManagementFacade.retrieveFileFromStorage(entitiesToDownload)) { // add for try close with resources log.info(DOWNLOAD_RESPONSE_META_DATA, downloadResponseMetaDataAutoClose); } @@ -385,15 +403,17 @@ void retrieveFileFromStorageMediaEmpty() throws Exception { mediaEntity.setContentObjectId("2"); mediaEntity.setClipId("clip-id"); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); // make the assertion on the response var exception = assertThrows( FileNotDownloadedException.class, () -> { - try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dmFacade.retrieveFileFromStorage(mediaEntity)) { + try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dataManagementFacade.retrieveFileFromStorage(mediaEntity)) { // add for try close with resources log.info(DOWNLOAD_RESPONSE_META_DATA, downloadResponseMetaDataAutoClose); } @@ -417,9 +437,11 @@ void duplicateObjectRetrievalQueueNotAddedWhenRetrieveFileFromStorageMediaEmpty( ObjectRetrievalQueueEntity objectRetrievalQueueEntity = new ObjectRetrievalQueueEntity(); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); when(objectRetrievalQueueRepository.findMatchingObjectRetrievalQueueItem(mediaEntity, null, @@ -431,7 +453,7 @@ void duplicateObjectRetrievalQueueNotAddedWhenRetrieveFileFromStorageMediaEmpty( var exception = assertThrows( FileNotDownloadedException.class, () -> { - try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dmFacade.retrieveFileFromStorage(mediaEntity)) { + try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dataManagementFacade.retrieveFileFromStorage(mediaEntity)) { // add for try close with resources log.info(DOWNLOAD_RESPONSE_META_DATA, downloadResponseMetaDataAutoClose); } @@ -457,15 +479,17 @@ void insertMediaEntityInObjectRetrievalQueueWhenNotFoundIn() { ObjectRetrievalQueueEntity objectRetrievalQueueEntity = createObjectRetrievalQueueEntity(mediaEntity, userAccount); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); // make the assertion on the response assertThrows( FileNotDownloadedException.class, () -> { - try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dmFacade.retrieveFileFromStorage(mediaEntity)) { + try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dataManagementFacade.retrieveFileFromStorage(mediaEntity)) { // add for try close with resources log.info(DOWNLOAD_RESPONSE_META_DATA, downloadResponseMetaDataAutoClose); } @@ -497,15 +521,17 @@ void insertTranscriptionEntityInObjectRetrievalQueueWhenNotFoundIn() { userAccount); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); // make the assertion on the response assertThrows( FileNotDownloadedException.class, () -> { - try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dmFacade.retrieveFileFromStorage(transcriptionDocumentEntity)) { + try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dataManagementFacade.retrieveFileFromStorage(transcriptionDocumentEntity)) { // add for try close with resources log.info(DOWNLOAD_RESPONSE_META_DATA, downloadResponseMetaDataAutoClose); } @@ -552,14 +578,16 @@ void retrieveFileFromStorageMediaFail() throws Exception { when(externalObjectDirectoryRepository.findByEntityAndStatus(any(MediaEntity.class), any(ObjectRecordStatusEntity.class))) .thenReturn(List.of(inboundEntity)); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); assertThrows( FileNotDownloadedException.class, () -> { - try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dmFacade.retrieveFileFromStorage(mediaEntity)) { + try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dataManagementFacade.retrieveFileFromStorage(mediaEntity)) { // add for try close with resources log.info(DOWNLOAD_RESPONSE_META_DATA, downloadResponseMetaDataAutoClose); } @@ -580,15 +608,17 @@ void retrieveFileFromStorageTranscriptionEmpty() throws Exception { transcriptionDocumentEntity.setClipId("clip-id"); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); // make the assertion on the response var exception = assertThrows( FileNotDownloadedException.class, () -> { - try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dmFacade.retrieveFileFromStorage(transcriptionDocumentEntity)) { + try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dataManagementFacade.retrieveFileFromStorage(transcriptionDocumentEntity)) { // add for try close with resources log.info(DOWNLOAD_RESPONSE_META_DATA, downloadResponseMetaDataAutoClose); } @@ -610,14 +640,16 @@ void retrieveFileFromStorageTranscriptionFail() throws Exception { when(externalObjectDirectoryRepository.findByEntityAndStatus(any(TranscriptionDocumentEntity.class), any(ObjectRecordStatusEntity.class))) .thenReturn(List.of(inboundEntity)); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); assertThrows( FileNotDownloadedException.class, () -> { - try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dmFacade.retrieveFileFromStorage(transcriptionDocumentEntity)) { + try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dataManagementFacade.retrieveFileFromStorage(transcriptionDocumentEntity)) { // add for try close with resources log.info(DOWNLOAD_RESPONSE_META_DATA, downloadResponseMetaDataAutoClose); } @@ -634,15 +666,17 @@ void retrieveFileFromStorageAnnotationDocumentEmpty() throws Exception { AnnotationDocumentEntity annotationDocumentEntity = new AnnotationDocumentEntity(); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); // make the assertion on the response var exception = assertThrows( FileNotDownloadedException.class, () -> { - try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dmFacade.retrieveFileFromStorage(annotationDocumentEntity)) { + try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dataManagementFacade.retrieveFileFromStorage(annotationDocumentEntity)) { // add for try close with resources log.info(DOWNLOAD_RESPONSE_META_DATA, downloadResponseMetaDataAutoClose); } @@ -664,14 +698,16 @@ void retrieveFileFromStorageAnnotationFail() throws Exception { when(externalObjectDirectoryRepository.findByEntityAndStatus(any(AnnotationDocumentEntity.class), any(ObjectRecordStatusEntity.class))) .thenReturn(List.of(inboundEntity)); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); assertThrows( FileNotDownloadedException.class, () -> { - try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dmFacade.retrieveFileFromStorage(annotationDocumentEntity)) { + try (DownloadResponseMetaData downloadResponseMetaDataAutoClose = dataManagementFacade.retrieveFileFromStorage(annotationDocumentEntity)) { // add for try close with resources log.info(DOWNLOAD_RESPONSE_META_DATA, downloadResponseMetaDataAutoClose); } @@ -679,32 +715,9 @@ void retrieveFileFromStorageAnnotationFail() throws Exception { ); } - @Test - void testUnstructuredDataHelperCreate() { - when(blobClientUploadResponseImpl.getBlobName()).thenReturn(UUID.randomUUID().toString()); - - when(dataManagementConfiguration.getUnstructuredContainerName()).thenReturn("unstructured"); - when(dataManagementService.saveBlobData(anyString(), (InputStream) any())).thenReturn(blobClientUploadResponseImpl); - - UnstructuredDataHelper unstructuredDataHelperTest = getUnstructuredDataHelper(); - - MediaEntity mediaEntity = new MediaEntity(); - ExternalObjectDirectoryEntity eodEntity = createEodEntity(unstructuredLocationEntity); - eodEntity.setMedia(mediaEntity); - ExternalObjectDirectoryEntity eodEntityToDelete = createEodEntity(unstructuredLocationEntity); - eodEntityToDelete.setMedia(mediaEntity); - BinaryData data = BinaryData.fromString("Test String"); - - boolean created = unstructuredDataHelperTest.createUnstructuredDataFromEod( - eodEntityToDelete, - eodEntity, - data.toStream()); - - assertTrue(created); - } @Test - void testUnstructuredDataHelperCreateFailed() { + void unstructuredDataHelperCreateFailed() { UnstructuredDataHelper unstructuredDataHelperTest = getUnstructuredDataHelper(); @@ -724,7 +737,7 @@ void testUnstructuredDataHelperCreateFailed() { } @Test - void testDownloadOfFacadeCreatesUnstructuredWhenUnstructuredNotFound() throws Exception { + void downloadOfFacadeCreatesUnstructuredWhenUnstructuredNotFound() throws Exception { ExternalObjectDirectoryEntity inboundEntity = createEodEntity(inboundLocationEntity); ExternalObjectDirectoryEntity unstructuredEntity = createEodEntity(unstructuredLocationEntity); ExternalObjectDirectoryEntity armEntity = createEodEntity(armLocationEntity); @@ -740,11 +753,13 @@ void testDownloadOfFacadeCreatesUnstructuredWhenUnstructuredNotFound() throws Ex when(armApiService.downloadArmData(armEntity.getExternalRecordId(), armEntity.getExternalFileId())).thenReturn(downloadResponseMetaDataMock); // execute the code - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, - objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelperFacade, - dataManagementConfiguration, armApiService, objectRetrievalQueueRepository); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelperFacade, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); - downloadResponseMetaData = dmFacade.retrieveFileFromStorage(mediaEntity); + downloadResponseMetaData = dataManagementFacade.retrieveFileFromStorage(mediaEntity); assertEquals(DatastoreContainerType.ARM, downloadResponseMetaData.getContainerTypeUsedToDownload()); } @@ -755,12 +770,12 @@ void createCopyInUnstructuredDatastore_whenDeleteFileOnCompletionIsTrue_shouldDe File targetFile = Files.createTempFile("test", "txt").toFile(); - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(null, null, - null, null, unstructuredDataHelper, - null, null, null); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(null, null, + null, null, unstructuredDataHelper, + null, null, null); assertThat(targetFile).exists(); - dmFacade.createCopyInUnstructuredDatastore(eodEntityToUpload, eodEntityToDelete, targetFile, true); + dataManagementFacade.createCopyInUnstructuredDatastore(eodEntityToUpload, eodEntityToDelete, targetFile, true); verify(unstructuredDataHelper).createUnstructuredDataFromEod(eq(eodEntityToDelete), eq(eodEntityToUpload), any(InputStream.class)); assertThat(targetFile).doesNotExist(); @@ -773,12 +788,12 @@ void createCopyInUnstructuredDatastore_whenDeleteFileOnCompletionIsFalse_shouldN File targetFile = Files.createTempFile("test", "txt").toFile(); - final DataManagementFacadeImpl dmFacade = new DataManagementFacadeImpl(null, null, - null, null, unstructuredDataHelper, - null, null, null); + final DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(null, null, + null, null, unstructuredDataHelper, + null, null, null); assertThat(targetFile).exists(); - dmFacade.createCopyInUnstructuredDatastore(eodEntityToUpload, eodEntityToDelete, targetFile, false); + dataManagementFacade.createCopyInUnstructuredDatastore(eodEntityToUpload, eodEntityToDelete, targetFile, false); verify(unstructuredDataHelper).createUnstructuredDataFromEod(eq(eodEntityToDelete), eq(eodEntityToUpload), any(InputStream.class)); assertThat(targetFile).exists(); @@ -797,17 +812,17 @@ void processUnstructuredData_downloadResponseMetaDataIsFileBased_shouldNotCreate when(downloadResponseMetaData.getFileToBeDownloadedTo()).thenReturn(targetFile); - final DataManagementFacadeImpl dmFacade = spy(new DataManagementFacadeImpl(null, null, - null, null, null, - null, null, null)); + final DataManagementFacadeImpl dataManagementFacade = spy(new DataManagementFacadeImpl(null, null, + null, null, null, + null, null, null)); - doNothing().when(dmFacade).createCopyInUnstructuredDatastore(any(), any(), any(), anyBoolean()); + doNothing().when(dataManagementFacade).createCopyInUnstructuredDatastore(any(), any(), any(), anyBoolean()); - dmFacade + dataManagementFacade .processUnstructuredData(datastoreContainerType, downloadResponseMetaData, eodEntityToUpload, eodEntityToDelete); verify(downloadResponseMetaData).getFileToBeDownloadedTo(); - verify(dmFacade).createCopyInUnstructuredDatastore(eodEntityToUpload, eodEntityToDelete, targetFile, false); + verify(dataManagementFacade).createCopyInUnstructuredDatastore(eodEntityToUpload, eodEntityToDelete, targetFile, false); } @Test @@ -826,14 +841,14 @@ void processUnstructuredData_downloadResponseMetaDataIsNotFileBased_shouldCreate when(resource.getInputStream()).thenReturn(stream); DataManagementConfiguration dataManagementConfiguration = mock(DataManagementConfiguration.class); - when(dataManagementConfiguration.getTempBlobWorkspace()).thenReturn(SOME_TEMP_WORKSPACE); - final DataManagementFacadeImpl dmFacade = spy(new DataManagementFacadeImpl(null, null, - null, null, null, - dataManagementConfiguration, null, null)); + when(dataManagementConfiguration.getTempBlobWorkspace()).thenReturn(tempWorkspace); + final DataManagementFacadeImpl dataManagementFacade = spy(new DataManagementFacadeImpl(null, null, + null, null, null, + dataManagementConfiguration, null, null)); - doNothing().when(dmFacade).createCopyInUnstructuredDatastore(any(), any(), any(), anyBoolean()); + doNothing().when(dataManagementFacade).createCopyInUnstructuredDatastore(any(), any(), any(), anyBoolean()); - dmFacade + dataManagementFacade .processUnstructuredData(datastoreContainerType, downloadResponseMetaData, eodEntityToUpload, eodEntityToDelete); ArgumentCaptor targetFileArgumentCaptor = ArgumentCaptor.forClass(File.class); @@ -841,10 +856,11 @@ void processUnstructuredData_downloadResponseMetaDataIsNotFileBased_shouldCreate verify(dataManagementConfiguration).getTempBlobWorkspace(); verify(downloadResponseMetaData).getResource(); verify(resource).getInputStream(); - verify(dmFacade).createCopyInUnstructuredDatastore(eq(eodEntityToUpload), eq(eodEntityToDelete), targetFileArgumentCaptor.capture(), eq(true)); + verify(dataManagementFacade).createCopyInUnstructuredDatastore(eq(eodEntityToUpload), eq(eodEntityToDelete), targetFileArgumentCaptor.capture(), + eq(true)); File targetFileActual = targetFileArgumentCaptor.getValue(); - assertThat(targetFileActual.getAbsolutePath()).matches(".*/" + SOME_TEMP_WORKSPACE + "/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"); + assertThat(targetFileActual.getAbsolutePath()).matches(".*/workspace/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"); } @NotNull @@ -891,4 +907,123 @@ private ExternalObjectDirectoryEntity createEodEntity(ExternalLocationTypeEntity return entity; } -} \ No newline at end of file + + @Test + void retrieveFileFromStorage_whenArmDownForMaintenance_shouldThrow() throws Exception { + List datastoreOrder = List.of(DatastoreContainerType.ARM); + when(storageOrderHelper.getStorageOrder()).thenReturn(datastoreOrder); + when(dataManagementConfiguration.getArmDownForMaintenance()).thenReturn(true); + + ExternalObjectDirectoryEntity armEntity = createEodEntity(armLocationEntity); + List entitiesToDownload = List.of(armEntity); + + List blobContainerDownloadables = new ArrayList<>(); + blobContainerDownloadables.add(setupDownloadableContainer(DatastoreContainerType.ARM, true)); + + DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); + + assertThrows(ArmDownForMaintenanceException.class, () -> dataManagementFacade.retrieveFileFromStorage(entitiesToDownload)); + verify(armApiService, times(0)).downloadArmData(any(), any()); + } + + @Test + void retrieveFileFromStorage_whenSupportedContainerMissing_shouldContinueToNext() throws Exception { + List datastoreOrder = List.of(DatastoreContainerType.DETS, DatastoreContainerType.ARM); + when(storageOrderHelper.getStorageOrder()).thenReturn(datastoreOrder); + + ExternalObjectDirectoryEntity detsEntity = createEodEntity(detsLocationEntity); + ExternalObjectDirectoryEntity armEntity = createEodEntity(armLocationEntity); + + List entitiesToDownload = List.of(detsEntity, armEntity); + + BlobContainerDownloadable detsContainer = mock(BlobContainerDownloadable.class); + when(detsContainer.getContainerName(DatastoreContainerType.DETS)).thenReturn(Optional.empty()); + + BlobContainerDownloadable armContainer = setupDownloadableContainer(DatastoreContainerType.ARM, true); + when(armApiService.downloadArmData(any(), any())).thenReturn(downloadResponseMetaDataMock); + + List blobContainerDownloadables = List.of(detsContainer, armContainer); + + DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); + + try (DownloadResponseMetaData response = dataManagementFacade.retrieveFileFromStorage(entitiesToDownload)) { + assertEquals(DatastoreContainerType.ARM, response.getContainerTypeUsedToDownload()); + } + } + + @Test + void retrieveFileFromStorage_whenFirstContainerFails_shouldFallbackToNext() throws Exception { + List datastoreOrder = List.of(DatastoreContainerType.UNSTRUCTURED, DatastoreContainerType.DETS); + when(storageOrderHelper.getStorageOrder()).thenReturn(datastoreOrder); + + ExternalObjectDirectoryEntity unstructuredEntity = createEodEntity(unstructuredLocationEntity); + ExternalObjectDirectoryEntity detsEntity = createEodEntity(detsLocationEntity); + List entitiesToDownload = List.of(unstructuredEntity, detsEntity); + + BlobContainerDownloadable unstructuredContainer = setupDownloadableContainer(DatastoreContainerType.UNSTRUCTURED, false); + BlobContainerDownloadable detsContainer = setupDownloadableContainer(DatastoreContainerType.DETS, true); + + List blobContainerDownloadables = List.of(unstructuredContainer, detsContainer); + + DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); + + try (DownloadResponseMetaData response = dataManagementFacade.retrieveFileFromStorage(entitiesToDownload)) { + assertEquals(DatastoreContainerType.DETS, response.getContainerTypeUsedToDownload()); + } + } + + @Test + void retrieveFileFromStorage_whenMixedStatuses_shouldUseStoredOnly() throws Exception { + List datastoreOrder = List.of(DatastoreContainerType.DETS); + when(storageOrderHelper.getStorageOrder()).thenReturn(datastoreOrder); + + ExternalObjectDirectoryEntity detsEntityStored = createEodEntity(detsLocationEntity); + ExternalObjectDirectoryEntity detsEntityNotStored = createEodEntity(detsLocationEntity); + detsEntityNotStored.getStatus().setId(ObjectRecordStatusEnum.FAILURE.getId()); + + List entitiesToDownload = List.of(detsEntityNotStored, detsEntityStored); + + BlobContainerDownloadable detsContainer = setupDownloadableContainer(DatastoreContainerType.DETS, true); + + List blobContainerDownloadables = List.of(detsContainer); + + DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(blobContainerDownloadables, externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, unstructuredDataHelper, + dataManagementConfiguration, armApiService, + objectRetrievalQueueRepository); + + try (DownloadResponseMetaData response = dataManagementFacade.retrieveFileFromStorage(entitiesToDownload)) { + assertEquals(DatastoreContainerType.DETS, response.getContainerTypeUsedToDownload()); + } + } + + @Test + void createCopyInUnstructuredDatastore_whenHelperThrows_shouldNotDeleteFile() throws IOException { + ExternalObjectDirectoryEntity eodEntityToUpload = mock(ExternalObjectDirectoryEntity.class); + ExternalObjectDirectoryEntity eodEntityToDelete = mock(ExternalObjectDirectoryEntity.class); + when(eodEntityToUpload.getId()).thenReturn(1L); + + File targetFile = Files.createTempFile("test", "txt").toFile(); + + doThrow(new RuntimeException("boom")).when(unstructuredDataHelper) + .createUnstructuredDataFromEod(eq(eodEntityToDelete), eq(eodEntityToUpload), any(InputStream.class)); + + DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(null, null, + null, null, unstructuredDataHelper, + null, null, null); + + assertThat(targetFile).exists(); + dataManagementFacade.createCopyInUnstructuredDatastore(eodEntityToUpload, eodEntityToDelete, targetFile, true); + + assertThat(targetFile).exists(); + } +} From 1bca79188d6425a99648ed3ae77c6aabc36e0b78 Mon Sep 17 00:00:00 2001 From: karen-hedges <133129444+karen-hedges@users.noreply.github.com> Date: Wed, 13 May 2026 13:54:12 +0100 Subject: [PATCH 07/14] DMP-5486 Disable ARM connections Created environment variable to represent ARM down for maintenance --- .../common/datamanagement/api/DataManagementFacadeImplTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImplTest.java b/src/test/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImplTest.java index ac43e4acb28..27f2680e72e 100644 --- a/src/test/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImplTest.java +++ b/src/test/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImplTest.java @@ -55,7 +55,6 @@ import java.util.Arrays; import java.util.List; import java.util.Optional; -import java.util.UUID; import java.util.stream.Stream; import static java.nio.charset.StandardCharsets.UTF_8; @@ -68,7 +67,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; From 7320444e9e01bfc612a6527139532ff865ca1724 Mon Sep 17 00:00:00 2001 From: karen-hedges <133129444+karen-hedges@users.noreply.github.com> Date: Wed, 13 May 2026 14:33:50 +0100 Subject: [PATCH 08/14] DMP-5486 Disable ARM connections Created environment variable to represent ARM down for maintenance --- .../impl/TranscriptionDownloaderTest.java | 92 +++++++++++++++++-- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/src/test/java/uk/gov/hmcts/darts/transcriptions/service/impl/TranscriptionDownloaderTest.java b/src/test/java/uk/gov/hmcts/darts/transcriptions/service/impl/TranscriptionDownloaderTest.java index 9ec704638a8..75d7f46aa69 100644 --- a/src/test/java/uk/gov/hmcts/darts/transcriptions/service/impl/TranscriptionDownloaderTest.java +++ b/src/test/java/uk/gov/hmcts/darts/transcriptions/service/impl/TranscriptionDownloaderTest.java @@ -7,11 +7,13 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.core.io.Resource; +import uk.gov.hmcts.darts.arm.enums.ArmApiError; import uk.gov.hmcts.darts.arm.exception.ArmDownForMaintenanceException; import uk.gov.hmcts.darts.audit.api.AuditApi; import uk.gov.hmcts.darts.authorisation.component.UserIdentity; import uk.gov.hmcts.darts.common.datamanagement.api.DataManagementFacade; import uk.gov.hmcts.darts.common.datamanagement.component.impl.DownloadResponseMetaData; +import uk.gov.hmcts.darts.common.entity.CourtCaseEntity; import uk.gov.hmcts.darts.common.entity.ExternalLocationTypeEntity; import uk.gov.hmcts.darts.common.entity.ExternalObjectDirectoryEntity; import uk.gov.hmcts.darts.common.entity.TranscriptionDocumentEntity; @@ -44,6 +46,7 @@ import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import static uk.gov.hmcts.darts.audit.api.AuditActivity.DOWNLOAD_TRANSCRIPTION; import static uk.gov.hmcts.darts.common.enums.ExternalLocationTypeEnum.INBOUND; import static uk.gov.hmcts.darts.common.enums.ExternalLocationTypeEnum.UNSTRUCTURED; import static uk.gov.hmcts.darts.common.enums.SecurityRoleEnum.SUPER_ADMIN; @@ -82,7 +85,7 @@ void setUp() { } @Test - void throwsExceptionIfNoTranscriptionFound() { + void downloadTranscript_throwsExceptionIfNoTranscriptionFound() { when(transcriptionRepository.findById(any())).thenReturn(empty()); assertThatThrownBy(() -> transcriptionDownloader.downloadTranscript(random.nextLong())) @@ -93,7 +96,7 @@ void throwsExceptionIfNoTranscriptionFound() { } @Test - void throwsExceptionIfTranscriptionHasNoTranscriptionDocuments() { + void downloadTranscript_throwsExceptionIfTranscriptionHasNoTranscriptionDocuments() { var transcription = someTranscriptionWith(emptyList()); when(transcriptionRepository.findById(transcription.getId())).thenReturn(Optional.of(transcription)); @@ -105,7 +108,7 @@ void throwsExceptionIfTranscriptionHasNoTranscriptionDocuments() { } @Test - void throwsExceptionIfTranscriptionDocumentHasNoExternalObjectDirectories() throws FileNotDownloadedException, ArmDownForMaintenanceException { + void downloadTranscript_throwsExceptionIfTranscriptionDocumentHasNoExternalObjectDirectories() throws FileNotDownloadedException, ArmDownForMaintenanceException { var transcriptionDocument = someTranscriptionDocumentWithUploadDate(now()); transcriptionDocument.setExternalObjectDirectoryEntities(emptyList()); @@ -124,7 +127,7 @@ void throwsExceptionIfTranscriptionDocumentHasNoExternalObjectDirectories() thro @Test - void throwsExceptionIfFailsToGetDownloadResponseInputStream() throws IOException, FileNotDownloadedException, ArmDownForMaintenanceException { + void downloadTranscript_throwsExceptionIfFailsToGetDownloadResponseInputStream() throws IOException, FileNotDownloadedException, ArmDownForMaintenanceException { var transcriptionDocument = someTranscriptionDocumentWithUploadDate(now()); transcriptionDocument.setExternalObjectDirectoryEntities(List.of(someExternalObjectDirectoryWithCreationDate(now()))); @@ -178,7 +181,7 @@ void retrievesTranscriptionFromUnstructuredContainer() throws IOException, FileN } @Test - void throwsNotFoundExceptionIfTranscriptionDocumentHiddenAndUserIsNotSuperAdmin() { + void downloadTranscript_throwsNotFoundExceptionIfTranscriptionDocumentHiddenAndUserIsNotSuperAdmin() { when(transcriptionDocumentRepository.findByTranscriptionIdAndHiddenTrueIncludeDeleted(anyLong())) .thenReturn(List.of(new TranscriptionDocumentEntity())); @@ -219,6 +222,83 @@ void downloadsDocumentIfTranscriptionDocumentHiddenAndUserIsSuperAdmin() throws verifyNoMoreInteractions(dataManagementFacade, fileBasedDownloadResponseMetaData); } + @Test + void downloadTranscript_throwsArmDownForMaintenanceWhenArmUnavailable() throws FileNotDownloadedException, ArmDownForMaintenanceException { + var transcriptionDocument = someTranscriptionDocumentWithUploadDate(now()); + transcriptionDocument.setExternalObjectDirectoryEntities(List.of(someExternalObjectDirectoryWithCreationDate(now()))); + + var transcription = someTranscriptionWith(List.of(transcriptionDocument)); + when(transcriptionRepository.findById(transcription.getId())).thenReturn(Optional.of(transcription)); + + when(dataManagementFacade.retrieveFileFromStorage(any(TranscriptionDocumentEntity.class))) + .thenThrow(new ArmDownForMaintenanceException("ARM down")); + + assertThatThrownBy(() -> transcriptionDownloader.downloadTranscript(transcription.getId())) + .isExactlyInstanceOf(DartsApiException.class) + .hasFieldOrPropertyWithValue("error", ArmApiError.ARM_DOWN_FOR_MAINTENANCE); + + verify(dataManagementFacade).retrieveFileFromStorage(any(TranscriptionDocumentEntity.class)); + } + + @Test + void recordsAuditOnSuccessfulDownload() throws IOException, FileNotDownloadedException, ArmDownForMaintenanceException { + var transcriptionDocument = someTranscriptionDocumentWithUploadDate(now()); + transcriptionDocument.setExternalObjectDirectoryEntities(List.of(someExternalObjectDirectoryWithCreationDate(now()))); + + var transcription = someTranscriptionWith(List.of(transcriptionDocument)); + var courtCase = new CourtCaseEntity(); + transcription.addCase(courtCase); + when(transcriptionRepository.findById(transcription.getId())).thenReturn(Optional.of(transcription)); + when(dataManagementFacade.retrieveFileFromStorage(any(TranscriptionDocumentEntity.class))).thenReturn(fileBasedDownloadResponseMetaData); + + Resource resource = Mockito.mock(Resource.class); + when(fileBasedDownloadResponseMetaData.getResource()).thenReturn(resource); + + transcriptionDownloader.downloadTranscript(transcription.getId()); + + verify(auditApi).record(DOWNLOAD_TRANSCRIPTION, userIdentity.getUserAccount(), courtCase); + } + + @Test + void downloadsDocumentWhenNoHiddenDocumentsExistForNonSuperAdmin() throws IOException, FileNotDownloadedException, ArmDownForMaintenanceException { + when(transcriptionDocumentRepository.findByTranscriptionIdAndHiddenTrueIncludeDeleted(anyLong())) + .thenReturn(emptyList()); + + var transcriptionDocument = someTranscriptionDocumentWithUploadDate(now()); + transcriptionDocument.setExternalObjectDirectoryEntities(List.of(someExternalObjectDirectoryWithCreationDate(now()))); + var transcription = someTranscriptionWith(List.of(transcriptionDocument)); + when(transcriptionRepository.findById(transcription.getId())).thenReturn(Optional.of(transcription)); + when(dataManagementFacade.retrieveFileFromStorage(any(TranscriptionDocumentEntity.class))).thenReturn(fileBasedDownloadResponseMetaData); + + Resource resource = Mockito.mock(Resource.class); + when(fileBasedDownloadResponseMetaData.getResource()).thenReturn(resource); + + var downloadTranscriptResponse = transcriptionDownloader.downloadTranscript(transcription.getId()); + + assertThat(downloadTranscriptResponse.getTranscriptionDocumentId()).isEqualTo(transcriptionDocument.getId()); + verify(transcriptionDocumentRepository).findByTranscriptionIdAndHiddenTrueIncludeDeleted(transcription.getId()); + } + + @Test + void selectsLatestTranscriptionDocumentByUploadedDate() throws IOException, FileNotDownloadedException, ArmDownForMaintenanceException { + var olderDocument = someTranscriptionDocumentWithUploadDate(now().minusDays(1)); + olderDocument.setExternalObjectDirectoryEntities(List.of(someExternalObjectDirectoryWithCreationDate(now().minusDays(1)))); + + var latestDocument = someTranscriptionDocumentWithUploadDate(now()); + latestDocument.setExternalObjectDirectoryEntities(List.of(someExternalObjectDirectoryWithCreationDate(now()))); + + var transcription = someTranscriptionWith(List.of(olderDocument, latestDocument)); + when(transcriptionRepository.findById(transcription.getId())).thenReturn(Optional.of(transcription)); + when(dataManagementFacade.retrieveFileFromStorage(any(TranscriptionDocumentEntity.class))).thenReturn(fileBasedDownloadResponseMetaData); + + Resource resource = Mockito.mock(Resource.class); + when(fileBasedDownloadResponseMetaData.getResource()).thenReturn(resource); + + var downloadTranscriptResponse = transcriptionDownloader.downloadTranscript(transcription.getId()); + + assertThat(downloadTranscriptResponse.getTranscriptionDocumentId()).isEqualTo(latestDocument.getId()); + } + private ExternalLocationTypeEntity externalLocationTypeFor(ExternalLocationTypeEnum externalLocationTypeEnum) { var externalLocationType = new ExternalLocationTypeEntity(); externalLocationType.setId(externalLocationTypeEnum.getId()); @@ -271,4 +351,4 @@ private TranscriptionEntity someTranscriptionWith(List Date: Wed, 13 May 2026 15:48:32 +0100 Subject: [PATCH 09/14] DMP-5486 Disable ARM connections Added tests --- .../impl/AudioTransformationServiceImpl.java | 8 - .../impl/AnnotationDataManagementTest.java | 31 ++- .../AudioTransformationServiceImplTest.java | 4 - .../api/DataManagementFacadeImplTest.java | 193 ++++++++++++------ 4 files changed, 153 insertions(+), 83 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/darts/audio/service/impl/AudioTransformationServiceImpl.java b/src/main/java/uk/gov/hmcts/darts/audio/service/impl/AudioTransformationServiceImpl.java index b544bb5afce..7e0ff9f904b 100644 --- a/src/main/java/uk/gov/hmcts/darts/audio/service/impl/AudioTransformationServiceImpl.java +++ b/src/main/java/uk/gov/hmcts/darts/audio/service/impl/AudioTransformationServiceImpl.java @@ -18,7 +18,6 @@ import uk.gov.hmcts.darts.audio.enums.AudioRequestOutputFormat; import uk.gov.hmcts.darts.audio.exception.AudioApiError; import uk.gov.hmcts.darts.audio.helper.TransformedMediaHelper; -import uk.gov.hmcts.darts.audio.helper.UnstructuredDataHelper; import uk.gov.hmcts.darts.audio.model.AudioFileInfo; import uk.gov.hmcts.darts.audio.service.AudioTransformationService; import uk.gov.hmcts.darts.audio.service.MediaRequestService; @@ -72,17 +71,12 @@ public class AudioTransformationServiceImpl implements AudioTransformationServic private final OutboundFileZipGenerator outboundFileZipGenerator; private final FileOperationService fileOperationService; private final MediaRepository mediaRepository; - private final ExternalObjectDirectoryService eodService; - private final TransformedMediaHelper transformedMediaHelper; - private final LogApi logApi; private final DataManagementFacade dataManagementFacade; - private final UnstructuredDataHelper unstructuredDataHelper; private final CurrentTimeHelper currentTimeHelper; private final AudioTransformationServiceProperties config; private final ProcessMediaRequestsForKeda processMediaRequestsForKeda; private final MediaRequestService mediaRequestService; - private static final Comparator MEDIA_START_TIME_CHANNEL_COMPARATOR = (media1, media2) -> { if (media1.getStart().equals(media2.getStart())) { return media1.getChannel().compareTo(media2.getChannel()); @@ -135,7 +129,6 @@ public static class ProcessMediaRequestsForKeda { private final LogApi logApi; private AudioTransformationServiceImpl audioTransformationService; - /** * For all audio related to a given AudioRequest, download, transform and upload the processed file to outbound * storage. @@ -239,7 +232,6 @@ public void processAudioRequest(Integer requestId) { } } - @Override public List filterMediaByMediaRequestTimeframeAndSortByStartTimeAndChannel(List mediaEntitiesForRequest, OffsetDateTime startTime, diff --git a/src/test/java/uk/gov/hmcts/darts/annotation/service/impl/AnnotationDataManagementTest.java b/src/test/java/uk/gov/hmcts/darts/annotation/service/impl/AnnotationDataManagementTest.java index 79e40a1eab9..f18244f5b83 100644 --- a/src/test/java/uk/gov/hmcts/darts/annotation/service/impl/AnnotationDataManagementTest.java +++ b/src/test/java/uk/gov/hmcts/darts/annotation/service/impl/AnnotationDataManagementTest.java @@ -8,7 +8,6 @@ import org.mockito.junit.jupiter.MockitoExtension; import uk.gov.hmcts.darts.arm.exception.ArmDownForMaintenanceException; import uk.gov.hmcts.darts.common.datamanagement.api.DataManagementFacade; -import uk.gov.hmcts.darts.common.datamanagement.component.impl.DownloadResponseMetaData; import uk.gov.hmcts.darts.common.datamanagement.component.impl.FileBasedDownloadResponseMetaData; import uk.gov.hmcts.darts.common.entity.AnnotationDocumentEntity; import uk.gov.hmcts.darts.common.entity.ExternalObjectDirectoryEntity; @@ -36,6 +35,7 @@ import static org.mockito.Mockito.when; import static uk.gov.hmcts.darts.annotation.errors.AnnotationApiError.FAILED_TO_DOWNLOAD_ANNOTATION_DOCUMENT; import static uk.gov.hmcts.darts.annotation.errors.AnnotationApiError.FAILED_TO_UPLOAD_ANNOTATION_DOCUMENT; +import static uk.gov.hmcts.darts.arm.enums.ArmApiError.ARM_DOWN_FOR_MAINTENANCE; import static uk.gov.hmcts.darts.common.enums.ExternalLocationTypeEnum.INBOUND; import static uk.gov.hmcts.darts.common.enums.ExternalLocationTypeEnum.UNSTRUCTURED; @@ -46,8 +46,6 @@ class AnnotationDataManagementTest { private DataManagementApi dataManagementApi; @Mock private DataManagementFacade dataManagementFacade; - @Mock - private DownloadResponseMetaData downloadResponseMetaData; private AnnotationDataManagement annotationDataManagement; @@ -57,7 +55,7 @@ void setUp() { } @Test - void throwsWhenSavingToInboundContainerFails() { + void upload_throwsWhenSavingToInboundContainerFails() { var binaryData = BinaryData.fromBytes("some-binary-data".getBytes()); when(dataManagementApi.saveBlobDataToInboundContainer(binaryData)).thenThrow(new RuntimeException()); @@ -69,7 +67,7 @@ void throwsWhenSavingToInboundContainerFails() { } @Test - void throwsAndAttemptsToDeleteFromInboundContainerWhenSavingToUnstructuredContainerFails() throws AzureDeleteBlobException { + void upload_throwsAndAttemptsToDeleteFromInboundContainerWhenSavingToUnstructuredContainerFails() throws AzureDeleteBlobException { var binaryData = BinaryData.fromBytes("some-binary-data".getBytes()); var inboundLocationUuid = UUID.randomUUID().toString(); when(dataManagementApi.saveBlobDataToInboundContainer(binaryData)).thenReturn(inboundLocationUuid); @@ -84,7 +82,7 @@ void throwsAndAttemptsToDeleteFromInboundContainerWhenSavingToUnstructuredContai } @Test - void returnsContainerLocationsWhenUploadSucceeds() { + void upload_returnsContainerLocationsWhenUploadSucceeds() { var binaryData = BinaryData.fromBytes("some-binary-data".getBytes()); var inboundLocationUuid = UUID.randomUUID().toString(); var unstructuredLocationUuid = UUID.randomUUID().toString(); @@ -98,7 +96,7 @@ void returnsContainerLocationsWhenUploadSucceeds() { } @Test - void deletesFromCorrectContainer() throws AzureDeleteBlobException { + void attemptToDeleteDocuments_deletesFromCorrectContainer() throws AzureDeleteBlobException { var inboundLocation = UUID.randomUUID().toString(); var unstructuredLocation = UUID.randomUUID().toString(); annotationDataManagement.attemptToDeleteDocuments(Map.of( @@ -111,7 +109,7 @@ void deletesFromCorrectContainer() throws AzureDeleteBlobException { } @Test - void throwsWhenDeleteFails() throws AzureDeleteBlobException { + void retrieveFileFromStorage_throwsWhenDeleteFails() throws AzureDeleteBlobException { var externalLocationUuid = UUID.randomUUID().toString(); doThrow(new AzureDeleteBlobException("some-message")).when(dataManagementApi).deleteBlobDataFromInboundContainer(externalLocationUuid); @@ -121,7 +119,7 @@ void throwsWhenDeleteFails() throws AzureDeleteBlobException { } @Test - void throwsIfDownloadAnnotationDocumentResponseFails() throws FileNotDownloadedException, ArmDownForMaintenanceException { + void retrieveFileFromStorage_throwsIfDownloadAnnotationDocumentResponseFails() throws FileNotDownloadedException, ArmDownForMaintenanceException { when(dataManagementFacade.retrieveFileFromStorage(anyList())).thenThrow(new FileNotDownloadedException()); assertThatThrownBy(() -> annotationDataManagement.download(Arrays.asList(someExternalObjectDirectoryEntity()))) .isInstanceOf(DartsApiException.class) @@ -130,7 +128,7 @@ void throwsIfDownloadAnnotationDocumentResponseFails() throws FileNotDownloadedE @Test @SuppressWarnings("PMD.CloseResource") - void throwsIfDownloadAnnotationDocumentInputStreamFails() throws FileNotDownloadedException, IOException, ArmDownForMaintenanceException { + void retrieveFileFromStorage_throwsIfDownloadAnnotationDocumentInputStreamFails() throws FileNotDownloadedException, IOException, ArmDownForMaintenanceException { var mockFileBasedDownloadResponseMetaData = mock(FileBasedDownloadResponseMetaData.class); when(dataManagementFacade.retrieveFileFromStorage(anyList())).thenReturn(mockFileBasedDownloadResponseMetaData); @@ -142,6 +140,19 @@ void throwsIfDownloadAnnotationDocumentInputStreamFails() throws FileNotDownload .hasFieldOrPropertyWithValue("error", FAILED_TO_DOWNLOAD_ANNOTATION_DOCUMENT); } + @Test + void retrieveFileFromStorage_throwsWhenArmDownForMaintenance() throws FileNotDownloadedException, ArmDownForMaintenanceException { + when(dataManagementFacade.retrieveFileFromStorage(anyList())) + .thenThrow(new ArmDownForMaintenanceException("ARM down")); + + ExternalObjectDirectoryEntity externalObjectDirectoryEntity = someExternalObjectDirectoryEntity(); + externalObjectDirectoryEntity.getAnnotationDocumentEntity().setId(12L); + + assertThatThrownBy(() -> annotationDataManagement.download(List.of(externalObjectDirectoryEntity))) + .isInstanceOf(DartsApiException.class) + .hasFieldOrPropertyWithValue("error", ARM_DOWN_FOR_MAINTENANCE); + } + private ExternalObjectDirectoryEntity someExternalObjectDirectoryEntity() { ExternalObjectDirectoryEntity externalObjectDirectoryEntity = new ExternalObjectDirectoryEntity(); externalObjectDirectoryEntity.setId(1L); diff --git a/src/test/java/uk/gov/hmcts/darts/audio/service/impl/AudioTransformationServiceImplTest.java b/src/test/java/uk/gov/hmcts/darts/audio/service/impl/AudioTransformationServiceImplTest.java index d75ce3867f4..a7c7f5db376 100644 --- a/src/test/java/uk/gov/hmcts/darts/audio/service/impl/AudioTransformationServiceImplTest.java +++ b/src/test/java/uk/gov/hmcts/darts/audio/service/impl/AudioTransformationServiceImplTest.java @@ -164,10 +164,6 @@ void beforeEach() { mock(), mediaRepository, mock(), - transformedMediaHelper, - mock(), - mock(), - mock(), currentTimeHelper, mock(), processMediaRequestsForKeda, diff --git a/src/test/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImplTest.java b/src/test/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImplTest.java index 27f2680e72e..9d0e423c220 100644 --- a/src/test/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImplTest.java +++ b/src/test/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImplTest.java @@ -40,7 +40,6 @@ import uk.gov.hmcts.darts.common.repository.UserAccountRepository; import uk.gov.hmcts.darts.datamanagement.config.DataManagementConfiguration; import uk.gov.hmcts.darts.datamanagement.exception.FileNotDownloadedException; -import uk.gov.hmcts.darts.datamanagement.model.BlobClientUploadResponseImpl; import uk.gov.hmcts.darts.datamanagement.service.DataManagementService; import uk.gov.hmcts.darts.test.common.FileStore; @@ -107,15 +106,14 @@ class DataManagementFacadeImplTest { private ObjectRetrievalQueueRepository objectRetrievalQueueRepository; @Mock private DownloadResponseMetaData downloadResponseMetaDataMock; - @Mock - private BlobClientUploadResponseImpl blobClientUploadResponseImpl; private ExternalLocationTypeEntity inboundLocationEntity; private ExternalLocationTypeEntity unstructuredLocationEntity; private ExternalLocationTypeEntity detsLocationEntity; private ExternalLocationTypeEntity armLocationEntity; - FileBasedDownloadResponseMetaData fileBasedDownloadResponseMetaData = new FileBasedDownloadResponseMetaData(); - DownloadResponseMetaData downloadResponseMetaData = new FileBasedDownloadResponseMetaData(); + private FileBasedDownloadResponseMetaData fileBasedDownloadResponseMetaData = new FileBasedDownloadResponseMetaData(); + private DownloadResponseMetaData downloadResponseMetaData = new FileBasedDownloadResponseMetaData(); + @TempDir private File tempDirectory; @@ -497,17 +495,6 @@ void insertMediaEntityInObjectRetrievalQueueWhenNotFoundIn() { verify(objectRetrievalQueueRepository, times(1)).saveAndFlush(objectRetrievalQueueEntity); } - private static @NotNull ObjectRetrievalQueueEntity createObjectRetrievalQueueEntity(MediaEntity mediaEntity, UserAccountEntity userAccount) { - ObjectRetrievalQueueEntity objectRetrievalQueueEntity = new ObjectRetrievalQueueEntity(); - objectRetrievalQueueEntity.setMedia(mediaEntity); - objectRetrievalQueueEntity.setCreatedBy(userAccount); - objectRetrievalQueueEntity.setLastModifiedBy(userAccount); - objectRetrievalQueueEntity.setParentObjectId(String.valueOf(mediaEntity.getId())); - objectRetrievalQueueEntity.setContentObjectId(mediaEntity.getContentObjectId()); - objectRetrievalQueueEntity.setClipId(mediaEntity.getClipId()); - return objectRetrievalQueueEntity; - } - @Test void insertTranscriptionEntityInObjectRetrievalQueueWhenNotFoundIn() { final List blobContainerDownloadables = new ArrayList<>(); @@ -861,51 +848,6 @@ void processUnstructuredData_downloadResponseMetaDataIsNotFileBased_shouldCreate assertThat(targetFileActual.getAbsolutePath()).matches(".*/workspace/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"); } - @NotNull - private UnstructuredDataHelper getUnstructuredDataHelper() { - return new UnstructuredDataHelper( - externalObjectDirectoryRepository, - objectRecordStatusRepository, - externalLocationTypeRepository, - userAccountRepository, - dataManagementService, - dataManagementConfiguration - ); - } - - private BlobContainerDownloadable setupDownloadableContainer(DatastoreContainerType containerType, - boolean processSuccess) throws IOException, FileNotDownloadedException { - BlobContainerDownloadable downloadable = mock(BlobContainerDownloadable.class); - - BinaryData data = BinaryData.fromString("Test String"); - - fileBasedDownloadResponseMetaData.setInputStream(data.toStream(), dataManagementConfiguration); - - lenient().when(downloadable.getContainerName(containerType)).thenReturn(Optional.of("test")); - if (processSuccess) { - lenient().when(downloadable - .downloadBlobFromContainer(eq(containerType), - Mockito.notNull())).thenReturn(fileBasedDownloadResponseMetaData); - } else { - lenient().when(downloadable - .downloadBlobFromContainer(eq(containerType), - Mockito.notNull())).thenThrow(new FileNotDownloadedException()); - } - return downloadable; - } - - private ExternalObjectDirectoryEntity createEodEntity(ExternalLocationTypeEntity locationTypeEntity) { - ExternalObjectDirectoryEntity entity = new ExternalObjectDirectoryEntity(); - - entity.setExternalLocationType(locationTypeEntity); - - ObjectRecordStatusEntity storedStatus = new ObjectRecordStatusEntity(); - storedStatus.setId(2); - entity.setStatus(storedStatus); - - return entity; - } - @Test void retrieveFileFromStorage_whenArmDownForMaintenance_shouldThrow() throws Exception { List datastoreOrder = List.of(DatastoreContainerType.ARM); @@ -1024,4 +966,133 @@ void createCopyInUnstructuredDatastore_whenHelperThrows_shouldNotDeleteFile() th assertThat(targetFile).exists(); } + + @Test + void retrieveFileFromStorageMedia_whenArmDownForMaintenance_shouldThrow() throws Exception { + List datastoreOrder = List.of(DatastoreContainerType.ARM); + when(storageOrderHelper.getStorageOrder()).thenReturn(datastoreOrder); + when(dataManagementConfiguration.getArmDownForMaintenance()).thenReturn(true); + + ExternalObjectDirectoryEntity armEntity = createEodEntity(armLocationEntity); + MediaEntity mediaEntity = new MediaEntity(); + mediaEntity.setId(1L); + + when(externalObjectDirectoryRepository.findByEntityAndStatus(eq(mediaEntity), any(ObjectRecordStatusEntity.class))) + .thenReturn(List.of(armEntity)); + + DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(List.of(), externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, dataManagementConfiguration, + armApiService, objectRetrievalQueueRepository); + + assertThrows(ArmDownForMaintenanceException.class, () -> dataManagementFacade.retrieveFileFromStorage(mediaEntity)); + verify(armApiService, times(0)).downloadArmData(any(), any()); + } + + @Test + void retrieveFileFromStorageTranscription_whenArmDownForMaintenance_shouldThrow() throws Exception { + List datastoreOrder = List.of(DatastoreContainerType.ARM); + when(storageOrderHelper.getStorageOrder()).thenReturn(datastoreOrder); + when(dataManagementConfiguration.getArmDownForMaintenance()).thenReturn(true); + + ExternalObjectDirectoryEntity armEntity = createEodEntity(armLocationEntity); + TranscriptionEntity transcriptionEntity = new TranscriptionEntity(); + transcriptionEntity.setId(11L); + TranscriptionDocumentEntity transcriptionDocumentEntity = new TranscriptionDocumentEntity(); + transcriptionDocumentEntity.setId(21L); + transcriptionDocumentEntity.setTranscription(transcriptionEntity); + + when(externalObjectDirectoryRepository.findByEntityAndStatus(eq(transcriptionDocumentEntity), any(ObjectRecordStatusEntity.class))) + .thenReturn(List.of(armEntity)); + + DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(List.of(), externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, dataManagementConfiguration, + armApiService, objectRetrievalQueueRepository); + + assertThrows(ArmDownForMaintenanceException.class, + () -> dataManagementFacade.retrieveFileFromStorage(transcriptionDocumentEntity)); + verify(armApiService, times(0)).downloadArmData(any(), any()); + } + + @Test + void retrieveFileFromStorageAnnotation_whenArmDownForMaintenance_shouldThrow() throws Exception { + List datastoreOrder = List.of(DatastoreContainerType.ARM); + when(storageOrderHelper.getStorageOrder()).thenReturn(datastoreOrder); + when(dataManagementConfiguration.getArmDownForMaintenance()).thenReturn(true); + + ExternalObjectDirectoryEntity armEntity = createEodEntity(armLocationEntity); + AnnotationDocumentEntity annotationDocumentEntity = new AnnotationDocumentEntity(); + annotationDocumentEntity.setId(31L); + + when(externalObjectDirectoryRepository.findByEntityAndStatus(eq(annotationDocumentEntity), any(ObjectRecordStatusEntity.class))) + .thenReturn(List.of(armEntity)); + + DataManagementFacadeImpl dataManagementFacade = new DataManagementFacadeImpl(List.of(), externalObjectDirectoryRepository, + objectRecordStatusRepository, storageOrderHelper, + unstructuredDataHelper, dataManagementConfiguration, + armApiService, objectRetrievalQueueRepository); + + assertThrows(ArmDownForMaintenanceException.class, + () -> dataManagementFacade.retrieveFileFromStorage(annotationDocumentEntity)); + verify(armApiService, times(0)).downloadArmData(any(), any()); + } + + @NotNull + private UnstructuredDataHelper getUnstructuredDataHelper() { + return new UnstructuredDataHelper( + externalObjectDirectoryRepository, + objectRecordStatusRepository, + externalLocationTypeRepository, + userAccountRepository, + dataManagementService, + dataManagementConfiguration + ); + } + + private BlobContainerDownloadable setupDownloadableContainer(DatastoreContainerType containerType, + boolean processSuccess) throws IOException, FileNotDownloadedException { + BlobContainerDownloadable downloadable = mock(BlobContainerDownloadable.class); + + BinaryData data = BinaryData.fromString("Test String"); + + fileBasedDownloadResponseMetaData.setInputStream(data.toStream(), dataManagementConfiguration); + + lenient().when(downloadable.getContainerName(containerType)).thenReturn(Optional.of("test")); + if (processSuccess) { + lenient().when(downloadable + .downloadBlobFromContainer(eq(containerType), + Mockito.notNull())).thenReturn(fileBasedDownloadResponseMetaData); + } else { + lenient().when(downloadable + .downloadBlobFromContainer(eq(containerType), + Mockito.notNull())).thenThrow(new FileNotDownloadedException()); + } + return downloadable; + } + + private ExternalObjectDirectoryEntity createEodEntity(ExternalLocationTypeEntity locationTypeEntity) { + ExternalObjectDirectoryEntity entity = new ExternalObjectDirectoryEntity(); + + entity.setExternalLocationType(locationTypeEntity); + + ObjectRecordStatusEntity storedStatus = new ObjectRecordStatusEntity(); + storedStatus.setId(2); + entity.setStatus(storedStatus); + + return entity; + } + + private static @NotNull ObjectRetrievalQueueEntity createObjectRetrievalQueueEntity(MediaEntity mediaEntity, UserAccountEntity userAccount) { + ObjectRetrievalQueueEntity objectRetrievalQueueEntity = new ObjectRetrievalQueueEntity(); + objectRetrievalQueueEntity.setMedia(mediaEntity); + objectRetrievalQueueEntity.setCreatedBy(userAccount); + objectRetrievalQueueEntity.setLastModifiedBy(userAccount); + objectRetrievalQueueEntity.setParentObjectId(String.valueOf(mediaEntity.getId())); + objectRetrievalQueueEntity.setContentObjectId(mediaEntity.getContentObjectId()); + objectRetrievalQueueEntity.setClipId(mediaEntity.getClipId()); + return objectRetrievalQueueEntity; + } + + } From 054acf2ad31aaa486e59099cc9847345fb0cafc5 Mon Sep 17 00:00:00 2001 From: karen-hedges <133129444+karen-hedges@users.noreply.github.com> Date: Thu, 14 May 2026 09:21:08 +0100 Subject: [PATCH 10/14] DMP-5486 Disable ARM connections Added tests --- .../impl/AnnotationDataManagementTest.java | 3 ++- .../service/impl/AudioServiceImplTest.java | 22 ++++++++++++++++++- .../api/DataManagementFacadeImplTest.java | 2 +- .../impl/TranscriptionDownloaderTest.java | 6 +++-- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/test/java/uk/gov/hmcts/darts/annotation/service/impl/AnnotationDataManagementTest.java b/src/test/java/uk/gov/hmcts/darts/annotation/service/impl/AnnotationDataManagementTest.java index f18244f5b83..a2e700ca79c 100644 --- a/src/test/java/uk/gov/hmcts/darts/annotation/service/impl/AnnotationDataManagementTest.java +++ b/src/test/java/uk/gov/hmcts/darts/annotation/service/impl/AnnotationDataManagementTest.java @@ -128,7 +128,8 @@ void retrieveFileFromStorage_throwsIfDownloadAnnotationDocumentResponseFails() t @Test @SuppressWarnings("PMD.CloseResource") - void retrieveFileFromStorage_throwsIfDownloadAnnotationDocumentInputStreamFails() throws FileNotDownloadedException, IOException, ArmDownForMaintenanceException { + void retrieveFileFromStorage_throwsIfDownloadAnnotationDocumentInputStreamFails() + throws FileNotDownloadedException, IOException, ArmDownForMaintenanceException { var mockFileBasedDownloadResponseMetaData = mock(FileBasedDownloadResponseMetaData.class); when(dataManagementFacade.retrieveFileFromStorage(anyList())).thenReturn(mockFileBasedDownloadResponseMetaData); diff --git a/src/test/java/uk/gov/hmcts/darts/audio/service/impl/AudioServiceImplTest.java b/src/test/java/uk/gov/hmcts/darts/audio/service/impl/AudioServiceImplTest.java index f49222e188c..ced7e63cfe8 100644 --- a/src/test/java/uk/gov/hmcts/darts/audio/service/impl/AudioServiceImplTest.java +++ b/src/test/java/uk/gov/hmcts/darts/audio/service/impl/AudioServiceImplTest.java @@ -12,8 +12,11 @@ import uk.gov.hmcts.darts.audio.model.AudioMetadata; import uk.gov.hmcts.darts.audio.service.AudioOperationService; import uk.gov.hmcts.darts.audio.service.AudioService; +import uk.gov.hmcts.darts.arm.enums.ArmApiError; +import uk.gov.hmcts.darts.arm.exception.ArmDownForMaintenanceException; import uk.gov.hmcts.darts.audio.service.AudioTransformationService; import uk.gov.hmcts.darts.common.entity.MediaEntity; +import uk.gov.hmcts.darts.common.exception.DartsApiException; import uk.gov.hmcts.darts.common.repository.ExternalObjectDirectoryRepository; import uk.gov.hmcts.darts.common.repository.MediaRepository; import uk.gov.hmcts.darts.common.service.FileOperationService; @@ -21,8 +24,10 @@ import java.util.Collections; import java.util.List; +import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyList; @@ -192,4 +197,19 @@ void getMediaEntitiesByHearingAndLowestChannel_singleChannelGroupReturn_shouldRe .containsExactlyInAnyOrder(media1, media2); verify(mediaRepository).findAllByHearingIdAndMinimumChannelAndIsCurrentTrue(HEARING_ID); } -} \ No newline at end of file + + @Test + void encode_whenArmDownForMaintenance_shouldThrowDartsApiException() throws Exception { + MediaEntity mediaEntity = new MediaEntity(); + mediaEntity.setId(11L); + when(mediaRepository.findById(mediaEntity.getId())).thenReturn(Optional.of(mediaEntity)); + + when(audioTransformationService.retrieveFromStorageAndSaveToTempWorkspace(mediaEntity)) + .thenThrow(new ArmDownForMaintenanceException("ARM down")); + + assertThatThrownBy(() -> audioService.encode(mediaEntity.getId())) + .isExactlyInstanceOf(DartsApiException.class) + .hasFieldOrPropertyWithValue("error", ArmApiError.ARM_DOWN_FOR_MAINTENANCE); + } +} + diff --git a/src/test/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImplTest.java b/src/test/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImplTest.java index 9d0e423c220..4e12208e457 100644 --- a/src/test/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImplTest.java +++ b/src/test/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImplTest.java @@ -111,7 +111,7 @@ class DataManagementFacadeImplTest { private ExternalLocationTypeEntity unstructuredLocationEntity; private ExternalLocationTypeEntity detsLocationEntity; private ExternalLocationTypeEntity armLocationEntity; - private FileBasedDownloadResponseMetaData fileBasedDownloadResponseMetaData = new FileBasedDownloadResponseMetaData(); + private final FileBasedDownloadResponseMetaData fileBasedDownloadResponseMetaData = new FileBasedDownloadResponseMetaData(); private DownloadResponseMetaData downloadResponseMetaData = new FileBasedDownloadResponseMetaData(); @TempDir diff --git a/src/test/java/uk/gov/hmcts/darts/transcriptions/service/impl/TranscriptionDownloaderTest.java b/src/test/java/uk/gov/hmcts/darts/transcriptions/service/impl/TranscriptionDownloaderTest.java index 75d7f46aa69..1b9f4dff0bc 100644 --- a/src/test/java/uk/gov/hmcts/darts/transcriptions/service/impl/TranscriptionDownloaderTest.java +++ b/src/test/java/uk/gov/hmcts/darts/transcriptions/service/impl/TranscriptionDownloaderTest.java @@ -108,7 +108,8 @@ void downloadTranscript_throwsExceptionIfTranscriptionHasNoTranscriptionDocument } @Test - void downloadTranscript_throwsExceptionIfTranscriptionDocumentHasNoExternalObjectDirectories() throws FileNotDownloadedException, ArmDownForMaintenanceException { + void downloadTranscript_throwsExceptionIfTranscriptionDocumentHasNoExternalObjectDirectories() + throws FileNotDownloadedException, ArmDownForMaintenanceException { var transcriptionDocument = someTranscriptionDocumentWithUploadDate(now()); transcriptionDocument.setExternalObjectDirectoryEntities(emptyList()); @@ -127,7 +128,8 @@ void downloadTranscript_throwsExceptionIfTranscriptionDocumentHasNoExternalObjec @Test - void downloadTranscript_throwsExceptionIfFailsToGetDownloadResponseInputStream() throws IOException, FileNotDownloadedException, ArmDownForMaintenanceException { + void downloadTranscript_throwsExceptionIfFailsToGetDownloadResponseInputStream() + throws IOException, FileNotDownloadedException, ArmDownForMaintenanceException { var transcriptionDocument = someTranscriptionDocumentWithUploadDate(now()); transcriptionDocument.setExternalObjectDirectoryEntities(List.of(someExternalObjectDirectoryWithCreationDate(now()))); From a96b2931dfb4d981f17a1046c145d394cb746f19 Mon Sep 17 00:00:00 2001 From: karen-hedges <133129444+karen-hedges@users.noreply.github.com> Date: Thu, 14 May 2026 09:25:47 +0100 Subject: [PATCH 11/14] DMP-5486 Disable ARM connections Added tests --- .../hmcts/darts/audio/service/impl/AudioServiceImplTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/uk/gov/hmcts/darts/audio/service/impl/AudioServiceImplTest.java b/src/test/java/uk/gov/hmcts/darts/audio/service/impl/AudioServiceImplTest.java index ced7e63cfe8..ba8cbf270d7 100644 --- a/src/test/java/uk/gov/hmcts/darts/audio/service/impl/AudioServiceImplTest.java +++ b/src/test/java/uk/gov/hmcts/darts/audio/service/impl/AudioServiceImplTest.java @@ -7,13 +7,13 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import uk.gov.hmcts.darts.arm.enums.ArmApiError; +import uk.gov.hmcts.darts.arm.exception.ArmDownForMaintenanceException; import uk.gov.hmcts.darts.audio.component.AudioBeingProcessedFromArchiveQuery; import uk.gov.hmcts.darts.audio.model.AudioBeingProcessedFromArchiveQueryResult; import uk.gov.hmcts.darts.audio.model.AudioMetadata; import uk.gov.hmcts.darts.audio.service.AudioOperationService; import uk.gov.hmcts.darts.audio.service.AudioService; -import uk.gov.hmcts.darts.arm.enums.ArmApiError; -import uk.gov.hmcts.darts.arm.exception.ArmDownForMaintenanceException; import uk.gov.hmcts.darts.audio.service.AudioTransformationService; import uk.gov.hmcts.darts.common.entity.MediaEntity; import uk.gov.hmcts.darts.common.exception.DartsApiException; From 70b3d7c46da943c16ea42d6c075bdd9585670b66 Mon Sep 17 00:00:00 2001 From: karen-hedges <133129444+karen-hedges@users.noreply.github.com> Date: Thu, 14 May 2026 10:08:16 +0100 Subject: [PATCH 12/14] DMP-5486 Disable ARM connections Added tests --- .../common/datamanagement/api/DataManagementFacadeImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImpl.java b/src/main/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImpl.java index 954f3f607ab..5e1150d3be8 100644 --- a/src/main/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImpl.java +++ b/src/main/java/uk/gov/hmcts/darts/common/datamanagement/api/DataManagementFacadeImpl.java @@ -36,6 +36,7 @@ import java.util.Optional; import java.util.UUID; +import static java.lang.Boolean.TRUE; import static java.util.Objects.nonNull; import static uk.gov.hmcts.darts.common.datamanagement.enums.DatastoreContainerType.ARM; import static uk.gov.hmcts.darts.common.datamanagement.enums.DatastoreContainerType.UNSTRUCTURED; @@ -190,7 +191,7 @@ private DownloadResponseMetaData getDataFromStorage( .append('\n'); continue; } - if (dataManagementConfiguration.getArmDownForMaintenance() + if (TRUE.equals(dataManagementConfiguration.getArmDownForMaintenance()) && datastoreContainerType.equals(ARM)) { throw new ArmDownForMaintenanceException("ARM is currently down for maintenance, cannot download files from ARM at this time"); } From 7b0c4bce50243eb80c9573dc1540a5d64452b0d7 Mon Sep 17 00:00:00 2001 From: karen-hedges <133129444+karen-hedges@users.noreply.github.com> Date: Tue, 9 Jun 2026 15:56:46 +0100 Subject: [PATCH 13/14] DMP-5486 Disable ARM connections Fix to build --- .../darts/arm/exception/ArmDownForMaintenanceException.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/uk/gov/hmcts/darts/arm/exception/ArmDownForMaintenanceException.java b/src/main/java/uk/gov/hmcts/darts/arm/exception/ArmDownForMaintenanceException.java index c49c80b5ff4..6b4c5d64339 100644 --- a/src/main/java/uk/gov/hmcts/darts/arm/exception/ArmDownForMaintenanceException.java +++ b/src/main/java/uk/gov/hmcts/darts/arm/exception/ArmDownForMaintenanceException.java @@ -1,7 +1,9 @@ package uk.gov.hmcts.darts.arm.exception; public class ArmDownForMaintenanceException extends Exception { + public ArmDownForMaintenanceException(String message) { super(message); } + } \ No newline at end of file From 1717517985ce356c8cddfec18ecb0312efeb4aa2 Mon Sep 17 00:00:00 2001 From: hmcts-jenkins-cnp <60659747+hmcts-jenkins-cnp[bot]@users.noreply.github.com> Date: Wed, 10 Jun 2026 15:07:26 +0000 Subject: [PATCH 14/14] Bumping chart version/ fixing aliases --- charts/darts-api/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/darts-api/Chart.yaml b/charts/darts-api/Chart.yaml index fd4ea7b9c1b..77a08148e2b 100644 --- a/charts/darts-api/Chart.yaml +++ b/charts/darts-api/Chart.yaml @@ -4,7 +4,7 @@ appVersion: "1.0" description: A Helm chart for darts-api App name: darts-api home: https://github.com/hmcts/darts-api -version: 0.0.114 +version: 0.0.115 maintainers: - name: HMCTS darts team dependencies: