From 33d7bc1f8e42d8b29c07a207ff56c2f7f2258354 Mon Sep 17 00:00:00 2001 From: George Barnes Date: Wed, 17 Dec 2025 15:45:20 +0000 Subject: [PATCH 1/5] Basic gc_state fix without testing --- .../uk/gov/hmcts/reform/preapi/media/MediaKind.java | 7 +++---- .../media/storage/AzureIngestStorageService.java | 10 ++++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/preapi/media/MediaKind.java b/src/main/java/uk/gov/hmcts/reform/preapi/media/MediaKind.java index 9ce8d40b11..6df9957fe9 100644 --- a/src/main/java/uk/gov/hmcts/reform/preapi/media/MediaKind.java +++ b/src/main/java/uk/gov/hmcts/reform/preapi/media/MediaKind.java @@ -384,10 +384,9 @@ private void startLiveEvent(String liveEventName) { @Override public String triggerProcessingStep1(CaptureSessionDTO captureSession, String captureSessionNoHyphen, UUID recordingId) { - if (!azureIngestStorageService.doesValidAssetExist(captureSession.getBookingId().toString())) { - log.info("No valid asset files found for capture session [{}] in container named [{}]", - captureSession.getId(), - captureSession.getBookingId().toString() + if (!checkLiveFeedAvailable(captureSession.getId())) { + log.info("No valid recording content found for capture session [{}] in Mediakind", + captureSession.getId() ); azureIngestStorageService.markContainerAsSafeToDelete(captureSession.getBookingId().toString()); return null; diff --git a/src/main/java/uk/gov/hmcts/reform/preapi/media/storage/AzureIngestStorageService.java b/src/main/java/uk/gov/hmcts/reform/preapi/media/storage/AzureIngestStorageService.java index bec50ee71e..f0e4f0418b 100644 --- a/src/main/java/uk/gov/hmcts/reform/preapi/media/storage/AzureIngestStorageService.java +++ b/src/main/java/uk/gov/hmcts/reform/preapi/media/storage/AzureIngestStorageService.java @@ -17,10 +17,6 @@ public AzureIngestStorageService(BlobServiceClient ingestStorageClient, AzureCon super(ingestStorageClient, azureConfiguration); } - public boolean doesValidAssetExist(String containerName) { - return doesIsmFileExist(containerName) || doesBlobExist(containerName, BLOB_GC_STATE); - } - public void markContainerAsProcessing(String containerName) { tagAllBlobsInContainer(containerName, TAG_KEY_STATUS, TAG_VALUE_PROCESSING); } @@ -37,4 +33,10 @@ public boolean sectionFileExist(String containerName) { .stream() .anyMatch(blobItem -> blobItem.getName().equalsIgnoreCase("0/section")); } + + // Deprecated, do not rely on MK internal state to determine recording status + @Deprecated + public boolean doesValidAssetExist(String containerName) { + return doesIsmFileExist(containerName) || doesBlobExist(containerName, BLOB_GC_STATE); + } } From 09576f978f74b11d85515bd81ae6cce73793c09c Mon Sep 17 00:00:00 2001 From: George Barnes Date: Tue, 6 Jan 2026 16:58:02 +0000 Subject: [PATCH 2/5] Refactor some MK tests and add gc_state processing tests --- ...ernative_Email_Report-2026-01-06-16:54.csv | 2 + .../reform/preapi/media/MediaKindTest.java | 304 ++++++++++-------- 2 files changed, 174 insertions(+), 132 deletions(-) create mode 100644 Migration Reports/Alternative_Email_Report-2026-01-06-16:54.csv diff --git a/Migration Reports/Alternative_Email_Report-2026-01-06-16:54.csv b/Migration Reports/Alternative_Email_Report-2026-01-06-16:54.csv new file mode 100644 index 0000000000..4934a8b9a8 --- /dev/null +++ b/Migration Reports/Alternative_Email_Report-2026-01-06-16:54.csv @@ -0,0 +1,2 @@ +email,alternativeEmail,status,message +test@example.com,existing@example.com.cjsm.net,SUCCESS,Alternative email updated successfully diff --git a/src/test/java/uk/gov/hmcts/reform/preapi/media/MediaKindTest.java b/src/test/java/uk/gov/hmcts/reform/preapi/media/MediaKindTest.java index a7f8b06fc1..bd8d4570ce 100644 --- a/src/test/java/uk/gov/hmcts/reform/preapi/media/MediaKindTest.java +++ b/src/test/java/uk/gov/hmcts/reform/preapi/media/MediaKindTest.java @@ -208,7 +208,7 @@ void getAllPaginatedMkListMultiPage() { @DisplayName("Should get asset by asset name") @Test void getAssetByAssetNameSuccess() { - var assetName = UUID.randomUUID().toString(); + final String assetName = UUID.randomUUID().toString(); var asset = createMkAsset(assetName); when(mockClient.getAsset(eq(assetName))).thenReturn(asset); @@ -245,7 +245,7 @@ void getAssetByAssetNameNotFound() { @DisplayName("Should get live event by name") @Test void getLiveEventByNameSuccess() { - var liveEventName = UUID.randomUUID().toString(); + final String liveEventName = UUID.randomUUID().toString(); var liveEvent = createLiveEvent(liveEventName); when(mockClient.getLiveEvent(liveEventName)).thenReturn(liveEvent); @@ -277,8 +277,8 @@ void getLiveEventNotFound() { @DisplayName("Should return a list of all live events") @Test void getLiveEventListSuccess() { - var liveEventName1 = UUID.randomUUID().toString(); - var liveEventName2 = UUID.randomUUID().toString(); + final String liveEventName1 = UUID.randomUUID().toString(); + final String liveEventName2 = UUID.randomUUID().toString(); var liveEvents = List.of( createLiveEvent(liveEventName1), createLiveEvent(liveEventName2) @@ -328,10 +328,45 @@ private MkLiveEvent createLiveEvent(String name) { .build(); } + private MkAssetStorage createAssetStorage() { + var examplePeriods = JsonNodeFactory.instance.objectNode(); + examplePeriods.set("0/index/edge", JsonNodeFactory.instance.objectNode()); + + return MkAssetStorage.builder() + .spec(MkAssetStorage.MkAssetStorageSpec.builder() + .periods(examplePeriods) + .build()) + .build(); + } + + private void mockFinishedRecording(String liveEventName) { + var mockLiveEvent = mock(MkLiveEvent.class); + var mockAssetStorage = createAssetStorage(); + + when(mockClient.getLiveEvent(liveEventName)).thenReturn(mockLiveEvent); + when(mockLiveEvent.getProperties()) + .thenReturn( + MkLiveEventProperties.builder() + .resourceState(LiveEventResourceState.RUNNING.toString()) + .build() + ); + + when(mockClient.getAssetTracks(liveEventName)).thenReturn(mockAssetStorage); + } + + private void mockProcessingJob(String processingJobName, String jobName) { + var mockJob1 = mock(MkJob.class); + var mockProperties1 = mock(MkJob.MkJobProperties.class); + when(mockJob1.getProperties()).thenReturn(mockProperties1); + when(mockProperties1.getState()).thenReturn(JobState.PROCESSING, JobState.PROCESSING, JobState.FINISHED); + when(mockClient.getJob(eq(processingJobName), startsWith(jobName))).thenReturn(mockJob1); + } + + @DisplayName("Should return the capture session when successfully started the live event") @Test void startLiveEventSuccess() { - var liveEventName = captureSession.getId().toString().replace("-", ""); + final String liveEventName = captureSession.getId().toString().replace("-", ""); var mockLiveEvent = mock(MkLiveEvent.class); when(mockClient.getLiveEvent(liveEventName)).thenReturn(mockLiveEvent); @@ -352,7 +387,7 @@ void startLiveEventSuccess() { @Test @DisplayName("Should return the capture session when successfully started the live event") void startLiveEventLiveEventConflictSuccess() { - var liveEventName = captureSession.getId().toString().replace("-", ""); + final String liveEventName = captureSession.getId().toString().replace("-", ""); var mockLiveEvent = mock(MkLiveEvent.class); when(mockClient.putLiveEvent(any(), any())) @@ -375,7 +410,7 @@ void startLiveEventLiveEventConflictSuccess() { @DisplayName("Should throw not found error when live event cannot be found after creation") @Test void startLiveEventNotFoundAfterCreate() { - var liveEventName = captureSession.getId().toString().replace("-", ""); + final String liveEventName = captureSession.getId().toString().replace("-", ""); when(mockClient.getLiveEvent(liveEventName)).thenThrow(mock(NotFoundException.class)); @@ -394,7 +429,7 @@ void startLiveEventNotFoundAfterCreate() { @DisplayName("Should throw 409 error when asset already exists") @Test void startLiveEventAssetConflict() { - var liveEventName = captureSession.getId().toString().replace("-", ""); + final String liveEventName = captureSession.getId().toString().replace("-", ""); var mockLiveEvent = mock(MkLiveEvent.class); when(mockClient.getLiveEvent(liveEventName)).thenReturn(mockLiveEvent); @@ -417,10 +452,23 @@ void startLiveEventAssetConflict() { @DisplayName("Should throw 409 error when live output already exists") @Test void startLiveEventLiveOutputConflict() { - var liveEventName = captureSession.getId().toString().replace("-", ""); + final String liveEventName = captureSession.getId().toString().replace("-", ""); var mockLiveEvent = mock(MkLiveEvent.class); + when(mockClient.getStreamingEndpointByName("default-live")) + .thenReturn(MkStreamingEndpoint.builder() + .properties(MkStreamingEndpointProperties.builder() + .resourceState(MkStreamingEndpointProperties.ResourceState.Running) + .build()) + .build()); when(mockClient.getLiveEvent(liveEventName)).thenReturn(mockLiveEvent); + when(mockLiveEvent.getProperties()) + .thenReturn( + MkLiveEventProperties.builder() + .resourceState(LiveEventResourceState.RUNNING.toString()) + .build() + ); + when(mockClient.putLiveOutput(eq(liveEventName), eq(liveEventName), any())) .thenThrow(mock(ConflictException.class)); @@ -440,7 +488,7 @@ void startLiveEventLiveOutputConflict() { @DisplayName("Should throw 404 error when creating a live output but cannot find live event") @Test void startLiveEventLiveOutputLiveEventNotFound() { - var liveEventName = captureSession.getId().toString().replace("-", ""); + final String liveEventName = captureSession.getId().toString().replace("-", ""); var mockLiveEvent = mock(MkLiveEvent.class); when(mockClient.getLiveEvent(liveEventName)).thenReturn(mockLiveEvent); @@ -463,7 +511,7 @@ void startLiveEventLiveOutputLiveEventNotFound() { @DisplayName("Should throw 404 error when attempting to start live event that cannot be found (after setup)") @Test void startLiveEventStartNotFound() { - var liveEventName = captureSession.getId().toString().replace("-", ""); + final String liveEventName = captureSession.getId().toString().replace("-", ""); var mockLiveEvent = mock(MkLiveEvent.class); when(mockClient.getLiveEvent(liveEventName)).thenReturn(mockLiveEvent); @@ -486,11 +534,34 @@ void startLiveEventStartNotFound() { @Test @DisplayName("Should successfully stop live event when there is not a recording found") void stopLiveEventAndProcessNoRecording() throws InterruptedException { - var liveEventName = captureSession.getId().toString().replace("-", ""); - var recordingId = UUID.randomUUID(); + final String liveEventName = captureSession.getId().toString().replace("-", ""); + final UUID recordingId = UUID.randomUUID(); + var mockLiveEvent = mock(MkLiveEvent.class); + var mockAssetStorage = mock(MkAssetStorage.class); + + when(mockClient.getLiveEvent(liveEventName)).thenReturn(mockLiveEvent); + when(mockLiveEvent.getProperties()) + .thenReturn( + MkLiveEventProperties.builder() + .resourceState(LiveEventResourceState.RUNNING.toString()) + .build() + ); + + when(mockClient.getLiveEvent(liveEventName)).thenReturn(mockLiveEvent); + when(mockLiveEvent.getProperties()) + .thenReturn( + MkLiveEventProperties.builder() + .resourceState(LiveEventResourceState.RUNNING.toString()) + .build() + ); - when(azureIngestStorageService.doesValidAssetExist(captureSession.getBookingId().toString())) - .thenReturn(false); + when(mockClient.getAssetTracks(liveEventName)).thenReturn(mockAssetStorage); + when(mockAssetStorage.getSpec()) + .thenReturn( + MkAssetStorage.MkAssetStorageSpec.builder() + .periods(null) + .build() + ); var res = mediaKind.stopLiveEventAndProcess(captureSession, recordingId); assertThat(res).isEqualTo(RecordingStatus.NO_RECORDING); @@ -499,7 +570,6 @@ void stopLiveEventAndProcessNoRecording() throws InterruptedException { verify(mockClient, times(1)).deleteLiveEvent(liveEventName); verify(mockClient, times(1)).deleteStreamingLocator(any()); verify(mockClient, times(1)).deleteLiveOutput(liveEventName, liveEventName); - verify(azureIngestStorageService, times(1)).doesValidAssetExist(captureSession.getBookingId().toString()); verify(azureIngestStorageService, times(1)) .markContainerAsSafeToDelete(captureSession.getBookingId().toString()); verify(mockClient, never()).putAsset(any(), any()); @@ -508,23 +578,14 @@ void stopLiveEventAndProcessNoRecording() throws InterruptedException { @Test @DisplayName("Should successfully stop live event when there is a recording found") void stopLiveEventAndProcessRecordingAvailable() throws InterruptedException { - var liveEventName = captureSession.getId().toString().replace("-", ""); - var recordingId = UUID.randomUUID(); - var tempName = recordingId.toString().replace("-", ""); - var mockJob1 = mock(MkJob.class); - var mockProperties1 = mock(MkJob.MkJobProperties.class); - var mockJob2 = mock(MkJob.class); - var mockProperties2 = mock(MkJob.MkJobProperties.class); + final String liveEventName = captureSession.getId().toString().replace("-", ""); + final UUID recordingId = UUID.randomUUID(); + final String tempName = recordingId.toString().replace("-", ""); - when(mockClient.getJob(eq(ENCODE_FROM_INGEST_TRANSFORM), startsWith(liveEventName))).thenReturn(mockJob1); - when(mockClient.getJob(eq(ENCODE_FROM_MP4_TRANSFORM), startsWith(tempName))).thenReturn(mockJob2); - when(mockJob1.getProperties()).thenReturn(mockProperties1); - when(mockJob2.getProperties()).thenReturn(mockProperties2); - when(mockProperties1.getState()).thenReturn(JobState.PROCESSING, JobState.PROCESSING, JobState.FINISHED); - when(mockProperties2.getState()).thenReturn(JobState.PROCESSING, JobState.PROCESSING, JobState.FINISHED); + mockProcessingJob(ENCODE_FROM_INGEST_TRANSFORM, liveEventName); + mockProcessingJob(ENCODE_FROM_MP4_TRANSFORM, tempName); + mockFinishedRecording(liveEventName); - when(azureIngestStorageService.doesValidAssetExist(captureSession.getBookingId().toString())) - .thenReturn(true); when(azureIngestStorageService.tryGetMp4FileName(recordingId.toString())).thenReturn("index.mp4"); when(azureFinalStorageService.doesIsmFileExist(recordingId.toString())).thenReturn(true); @@ -535,7 +596,6 @@ void stopLiveEventAndProcessRecordingAvailable() throws InterruptedException { verify(mockClient, times(1)).deleteLiveEvent(liveEventName); verify(mockClient, times(1)).deleteStreamingLocator(any()); verify(mockClient, times(1)).deleteLiveOutput(liveEventName, liveEventName); - verify(azureIngestStorageService, times(1)).doesValidAssetExist(captureSession.getBookingId().toString()); verify(mockClient, times(2)).putAsset(any(), any()); verify(mockClient, times(1)).getTransform(ENCODE_FROM_INGEST_TRANSFORM); verify(mockClient, times(1)).getTransform(ENCODE_FROM_MP4_TRANSFORM); @@ -562,29 +622,22 @@ void stopLiveEventAndProcessRecordingAvailable() throws InterruptedException { @Test @DisplayName("Should throw error for stop live event when file cannot be found after first encode job") void stopLiveEventAndProcessRecordingEncodingJobNoFileNameFound() throws InterruptedException { - var liveEventName = captureSession.getId().toString().replace("-", ""); - var recordingId = UUID.randomUUID(); - var mockJob1 = mock(MkJob.class); - var mockProperties1 = mock(MkJob.MkJobProperties.class); - - when(mockClient.getJob(eq(ENCODE_FROM_INGEST_TRANSFORM), startsWith(liveEventName))).thenReturn(mockJob1); + final String liveEventName = captureSession.getId().toString().replace("-", ""); + final UUID recordingId = UUID.randomUUID(); - when(mockJob1.getProperties()).thenReturn(mockProperties1); - when(mockProperties1.getState()).thenReturn(JobState.PROCESSING, JobState.PROCESSING, JobState.FINISHED); + mockFinishedRecording(liveEventName); + mockProcessingJob(ENCODE_FROM_INGEST_TRANSFORM, liveEventName); - when(azureIngestStorageService.doesValidAssetExist(captureSession.getBookingId().toString())) - .thenReturn(true); when(azureIngestStorageService.tryGetMp4FileName(recordingId.toString())).thenReturn(null); - assertThat(mediaKind.stopLiveEventAndProcess(captureSession, recordingId)).isEqualTo(RecordingStatus.FAILURE); verify(mockClient, times(1)).stopLiveEvent(liveEventName); verify(mockClient, times(1)).deleteLiveEvent(liveEventName); verify(mockClient, times(1)).deleteStreamingLocator(any()); verify(mockClient, times(1)).deleteLiveOutput(liveEventName, liveEventName); - verify(azureIngestStorageService, times(1)).doesValidAssetExist(captureSession.getBookingId().toString()); verify(mockClient, times(2)).putAsset(any(), any()); verify(mockClient, times(1)).getTransform(ENCODE_FROM_INGEST_TRANSFORM); + verify(mockClient, times(1)).getAssetTracks(liveEventName); verify(mockClient, never()).putTransform(any(), any()); verify(azureIngestStorageService, never()).doesIsmFileExist(recordingId.toString()); } @@ -592,10 +645,10 @@ void stopLiveEventAndProcessRecordingEncodingJobNoFileNameFound() throws Interru @Test @DisplayName("Should throw error when error occurs creating asset") void stopLiveEventAndProcessAssetCreateError() { - var recordingId = UUID.randomUUID(); + final UUID recordingId = UUID.randomUUID(); + final String liveEventName = captureSession.getId().toString().replace("-", ""); - when(azureIngestStorageService.doesValidAssetExist(captureSession.getBookingId().toString())) - .thenReturn(true); + mockFinishedRecording(liveEventName); when(mockClient.putAsset(any(), any())).thenThrow(FeignException.class); assertThrows( @@ -610,25 +663,16 @@ void stopLiveEventAndProcessAssetCreateError() { @Test @DisplayName("Should create the EncodeFromIngest transform if it doesn't exist") void stopLiveEventAndProcessRecordingFoundRunEncodeTransform() throws InterruptedException { - var liveEventName = captureSession.getId().toString().replace("-", ""); - var recordingId = UUID.randomUUID(); - var tempName = recordingId.toString().replace("-", ""); - var mockJob1 = mock(MkJob.class); - var mockProperties1 = mock(MkJob.MkJobProperties.class); - var mockJob2 = mock(MkJob.class); - var mockProperties2 = mock(MkJob.MkJobProperties.class); + final String liveEventName = captureSession.getId().toString().replace("-", ""); + final UUID recordingId = UUID.randomUUID(); + final String tempName = recordingId.toString().replace("-", ""); - when(mockClient.getTransform(ENCODE_FROM_INGEST_TRANSFORM)).thenThrow(NotFoundException.class); + mockProcessingJob(ENCODE_FROM_INGEST_TRANSFORM, liveEventName); + mockProcessingJob(ENCODE_FROM_MP4_TRANSFORM, tempName); + mockFinishedRecording(liveEventName); - when(mockClient.getJob(eq(ENCODE_FROM_INGEST_TRANSFORM), startsWith(liveEventName))).thenReturn(mockJob1); - when(mockClient.getJob(eq(ENCODE_FROM_MP4_TRANSFORM), startsWith(tempName))).thenReturn(mockJob2); - when(mockJob1.getProperties()).thenReturn(mockProperties1); - when(mockJob2.getProperties()).thenReturn(mockProperties2); - when(mockProperties1.getState()).thenReturn(JobState.PROCESSING, JobState.PROCESSING, JobState.FINISHED); - when(mockProperties2.getState()).thenReturn(JobState.PROCESSING, JobState.PROCESSING, JobState.FINISHED); + when(mockClient.getTransform(ENCODE_FROM_INGEST_TRANSFORM)).thenThrow(NotFoundException.class); - when(azureIngestStorageService.doesValidAssetExist(captureSession.getBookingId().toString())) - .thenReturn(true); when(azureIngestStorageService.tryGetMp4FileName(any())).thenReturn("index.mp4"); when(azureFinalStorageService.doesIsmFileExist(recordingId.toString())).thenReturn(true); @@ -648,31 +692,23 @@ void stopLiveEventAndProcessRecordingFoundRunEncodeTransform() throws Interrupte verify(mockClient, times(1)).deleteLiveEvent(liveEventName); verify(mockClient, times(1)).deleteStreamingLocator(any()); verify(mockClient, times(1)).deleteLiveOutput(liveEventName, liveEventName); + verify(mockClient, times(1)).getAssetTracks(liveEventName); } @Test @DisplayName("Should create the EncodeFromMp4 transform if it doesn't exist") void stopLiveEventAndProcessRecordingFoundRunEncodeTransform2() throws InterruptedException { - var liveEventName = captureSession.getId().toString().replace("-", ""); - var recordingId = UUID.randomUUID(); - var tempName = recordingId.toString().replace("-", ""); - var mockJob1 = mock(MkJob.class); - var mockProperties1 = mock(MkJob.MkJobProperties.class); - var mockJob2 = mock(MkJob.class); - var mockProperties2 = mock(MkJob.MkJobProperties.class); + final String liveEventName = captureSession.getId().toString().replace("-", ""); + final UUID recordingId = UUID.randomUUID(); + final String tempName = recordingId.toString().replace("-", ""); + + mockFinishedRecording(liveEventName); + mockProcessingJob(ENCODE_FROM_INGEST_TRANSFORM, liveEventName); + mockProcessingJob(ENCODE_FROM_MP4_TRANSFORM, tempName); when(mockClient.getTransform(ENCODE_FROM_INGEST_TRANSFORM)).thenThrow(NotFoundException.class); when(mockClient.getTransform(ENCODE_FROM_MP4_TRANSFORM)).thenThrow(NotFoundException.class); - when(mockClient.getJob(eq(ENCODE_FROM_INGEST_TRANSFORM), startsWith(liveEventName))).thenReturn(mockJob1); - when(mockClient.getJob(eq(ENCODE_FROM_MP4_TRANSFORM), startsWith(tempName))).thenReturn(mockJob2); - when(mockJob1.getProperties()).thenReturn(mockProperties1); - when(mockJob2.getProperties()).thenReturn(mockProperties2); - when(mockProperties1.getState()).thenReturn(JobState.PROCESSING, JobState.PROCESSING, JobState.FINISHED); - when(mockProperties2.getState()).thenReturn(JobState.PROCESSING, JobState.PROCESSING, JobState.FINISHED); - - when(azureIngestStorageService.doesValidAssetExist(captureSession.getBookingId().toString())) - .thenReturn(true); when(azureIngestStorageService.tryGetMp4FileName(any())).thenReturn("index.mp4"); when(azureFinalStorageService.doesIsmFileExist(recordingId.toString())).thenReturn(true); @@ -694,13 +730,14 @@ void stopLiveEventAndProcessRecordingFoundRunEncodeTransform2() throws Interrupt verify(mockClient, times(1)).deleteLiveEvent(liveEventName); verify(mockClient, times(1)).deleteStreamingLocator(any()); verify(mockClient, times(1)).deleteLiveOutput(liveEventName, liveEventName); + verify(mockClient, times(1)).getAssetTracks(liveEventName); } @Test @DisplayName("Should throw not found when live event cannot be found to stop") void stopLiveEventAndProcessLiveEventNotFound() { - var liveEventName = captureSession.getId().toString().replace("-", ""); - var recordingId = UUID.randomUUID(); + final String liveEventName = captureSession.getId().toString().replace("-", ""); + final UUID recordingId = UUID.randomUUID(); doThrow(NotFoundException.class).when(mockClient).stopLiveEvent(any()); @@ -718,11 +755,33 @@ void stopLiveEventAndProcessLiveEventNotFound() { @Test @DisplayName("Should successfully stop live event when there is not a streaming endpoint to stop/delete") void stopLiveEventAndProcessEndpointNotFound() throws InterruptedException { - var liveEventName = captureSession.getId().toString().replace("-", ""); - var recordingId = UUID.randomUUID(); + final String liveEventName = captureSession.getId().toString().replace("-", ""); + final UUID recordingId = UUID.randomUUID(); + var mockLiveEvent = mock(MkLiveEvent.class); + var mockAssetStorage = mock(MkAssetStorage.class); + + when(mockClient.getStreamingEndpointByName("default-live")) + .thenReturn(MkStreamingEndpoint.builder() + .properties(MkStreamingEndpointProperties.builder() + .resourceState(MkStreamingEndpointProperties.ResourceState.Running) + .build()) + .build()); + when(mockClient.getLiveEvent(liveEventName)).thenReturn(mockLiveEvent); + when(mockLiveEvent.getProperties()) + .thenReturn( + MkLiveEventProperties.builder() + .resourceState(LiveEventResourceState.RUNNING.toString()) + .build() + ); + + when(mockClient.getAssetTracks(liveEventName)).thenReturn(mockAssetStorage); + when(mockAssetStorage.getSpec()) + .thenReturn( + MkAssetStorage.MkAssetStorageSpec.builder() + .periods(null) + .build() + ); - when(azureIngestStorageService.doesValidAssetExist(captureSession.getBookingId().toString())) - .thenReturn(false); doThrow(NotFoundException.class).when(mockClient).stopStreamingEndpoint(any()); var res = mediaKind.stopLiveEventAndProcess(captureSession, recordingId); @@ -732,15 +791,14 @@ void stopLiveEventAndProcessEndpointNotFound() throws InterruptedException { verify(mockClient, times(1)).deleteLiveEvent(liveEventName); verify(mockClient, times(1)).deleteStreamingLocator(any()); verify(mockClient, times(1)).deleteLiveOutput(liveEventName, liveEventName); - verify(azureIngestStorageService, times(1)).doesValidAssetExist(captureSession.getBookingId().toString()); + verify(mockClient, times(1)).getAssetTracks(liveEventName); verify(mockClient, never()).putAsset(any(), any()); } @DisplayName("Should accept a request to import an asset and return a job response for encoding to mp4") @Test void importAssetSuccess() throws InterruptedException { - - var newRecordingId = UUID.randomUUID(); + final UUID newRecordingId = UUID.randomUUID(); var generateAssetDTO = new GenerateAssetDTO(newRecordingId + "-input", newRecordingId, @@ -752,11 +810,12 @@ void importAssetSuccess() throws InterruptedException { var mockJob = mock(MkJob.class); var mockProperties = mock(MkJob.MkJobProperties.class); when(mockClient.getJob(eq(ENCODE_FROM_MP4_TRANSFORM), any())).thenReturn(mockJob); - when(azureFinalStorageService.getMp4FileName(generateAssetDTO.getSourceContainer())).thenReturn("video.mp4"); when(mockJob.getProperties()).thenReturn(mockProperties); when(mockProperties.getState()).thenReturn(JobState.FINISHED); when(mockClient.getTransform(ENCODE_FROM_MP4_TRANSFORM)).thenThrow(NotFoundException.class); + when(azureFinalStorageService.getMp4FileName(generateAssetDTO.getSourceContainer())).thenReturn("video.mp4"); + var result = mediaKind.importAsset(generateAssetDTO, true); assertThat(result.getJobStatus()).isEqualTo("Finished"); @@ -860,7 +919,7 @@ void importAssetJobFailed() throws InterruptedException { @DisplayName("Should fail to play a live event because the live event is not running") @Test void playLiveEventFailureLiveEventNotRunning() { - var liveEventName = captureSession.getId().toString().replace("-", ""); + final String liveEventName = captureSession.getId().toString().replace("-", ""); var mockLiveEvent = mock(MkLiveEvent.class); when(mockClient.getLiveEvent(liveEventName)).thenReturn(mockLiveEvent); @@ -881,7 +940,7 @@ void playLiveEventFailureLiveEventNotRunning() { @DisplayName("Should fail to play a live event because the streaming endpoint won't start") @Test void playLiveEventFailureToStartStreamingEndpoint() { - var liveEventName = captureSession.getId().toString().replace("-", ""); + final String liveEventName = captureSession.getId().toString().replace("-", ""); var mockLiveEvent = mock(MkLiveEvent.class); when(mockClient.getStreamingEndpointByName("default-live")) @@ -905,7 +964,7 @@ void playLiveEventFailureToStartStreamingEndpoint() { @DisplayName("Should play a live event successfully") @Test void playLiveEventSuccess() throws JsonProcessingException, InterruptedException { - var liveEventName = captureSession.getId().toString().replace("-", ""); + final String liveEventName = captureSession.getId().toString().replace("-", ""); var mockLiveEvent = mock(MkLiveEvent.class); when(mockClient.getStreamingEndpointByName("default-live")) @@ -938,7 +997,7 @@ void playLiveEventSuccess() throws JsonProcessingException, InterruptedException @Test @DisplayName("Should play a live event successfully when streaming locator already exists") void playLiveEventStreamingLocatorAlreadyExistsSuccess() throws JsonProcessingException, InterruptedException { - var liveEventName = captureSession.getId().toString().replace("-", ""); + final String liveEventName = captureSession.getId().toString().replace("-", ""); var mockLiveEvent = mock(MkLiveEvent.class); when(mockClient.getStreamingEndpointByName("default-live")) @@ -973,7 +1032,7 @@ void playLiveEventStreamingLocatorAlreadyExistsSuccess() throws JsonProcessingEx @Test @DisplayName("Should throw error when failing to get streaming locator (not 404)") void playLiveEventStreamingLocatorFailed() throws JsonProcessingException, InterruptedException { - var liveEventName = captureSession.getId().toString().replace("-", ""); + final String liveEventName = captureSession.getId().toString().replace("-", ""); var mockLiveEvent = mock(MkLiveEvent.class); when(mockClient.getStreamingEndpointByName("default-live")) @@ -1033,8 +1092,8 @@ private MkStreamingLocatorUrlPaths getGoodStreamingLocatorPaths(String liveEvent @DisplayName("Should return the playback urls for the asset") @Test void playAssetSuccess() throws InterruptedException { - var assetName = UUID.randomUUID().toString(); - var userId = UUID.randomUUID().toString(); + final String assetName = UUID.randomUUID().toString(); + final String userId = UUID.randomUUID().toString(); var asset = createMkAsset(assetName); var streamingEndpoint = MkStreamingEndpoint.builder() .properties( @@ -1096,8 +1155,8 @@ void playAssetSuccess() throws InterruptedException { @DisplayName("Should return the playback urls for the asset when content key policy didn't exist") @Test void playAssetContentKeyNotFoundSuccess() throws InterruptedException, JsonProcessingException { - var assetName = UUID.randomUUID().toString(); - var userId = UUID.randomUUID().toString(); + final String assetName = UUID.randomUUID().toString(); + final String userId = UUID.randomUUID().toString(); var asset = createMkAsset(assetName); var streamingEndpoint = MkStreamingEndpoint.builder() .properties( @@ -1164,8 +1223,8 @@ void playAssetContentKeyNotFoundSuccess() throws InterruptedException, JsonProce @DisplayName("Should return the playback urls for the asset when streaming policy not found") @Test void playAssetStreamingPolicyNotFoundSuccess() throws InterruptedException { - var assetName = UUID.randomUUID().toString(); - var userId = UUID.randomUUID().toString(); + final String assetName = UUID.randomUUID().toString(); + final String userId = UUID.randomUUID().toString(); var asset = createMkAsset(assetName); var streamingEndpoint = MkStreamingEndpoint.builder() .properties( @@ -1229,8 +1288,8 @@ void playAssetStreamingPolicyNotFoundSuccess() throws InterruptedException { @DisplayName("Should return the playback urls for the asset when default endpoint not running") @Test void playAssetStreamingEndpointNotRunningSuccess() throws InterruptedException { - var assetName = UUID.randomUUID().toString(); - var userId = UUID.randomUUID().toString(); + final String assetName = UUID.randomUUID().toString(); + final String userId = UUID.randomUUID().toString(); var asset = createMkAsset(assetName); var mockProperties = mock(MkStreamingEndpointProperties.class); @@ -1298,8 +1357,8 @@ void playAssetStreamingEndpointNotRunningSuccess() throws InterruptedException { @DisplayName("Should return the playback urls for the asset when default endpoint not created") @Test void playAssetStreamingEndpointNotFoundSuccess() throws InterruptedException { - var assetName = UUID.randomUUID().toString(); - var userId = UUID.randomUUID().toString(); + final String assetName = UUID.randomUUID().toString(); + final String userId = UUID.randomUUID().toString(); var asset = createMkAsset(assetName); var streamingEndpoint = MkStreamingEndpoint.builder() .name("default") @@ -1367,8 +1426,8 @@ void playAssetStreamingEndpointNotFoundSuccess() throws InterruptedException { @DisplayName("Should throw not found error when both dash and hls are null") @Test void playAssetNotFound() throws InterruptedException { - var assetName = UUID.randomUUID().toString(); - var userId = UUID.randomUUID().toString(); + final String assetName = UUID.randomUUID().toString(); + final String userId = UUID.randomUUID().toString(); var asset = createMkAsset(assetName); var streamingEndpoint = MkStreamingEndpoint.builder() .properties( @@ -1412,7 +1471,6 @@ void playAssetNotFound() throws InterruptedException { @DisplayName("Should Delete all streaming locators and Content Key Policies") @Test void testDeleteAllStreamingLocatorsAndContentKeyPolicies() { - var locators = List.of( MkStreamingLocator.builder().name("locator1").build(), MkStreamingLocator.builder().name("locator2").build(), @@ -1454,7 +1512,7 @@ void testDeleteAllStreamingLocatorsAndContentKeyPolicies() { @Test @DisplayName("Should not error when stopping live event when live output has not been deleted") void cleanupStoppedLiveEventLiveOutputNotDeletedSuccess() { - var liveEventId = UUID.randomUUID().toString().replace("-", ""); + final String liveEventId = UUID.randomUUID().toString().replace("-", ""); doThrow(FeignException.BadRequest.class).when(mockClient).stopLiveEvent(liveEventId); @@ -1468,7 +1526,7 @@ void cleanupStoppedLiveEventLiveOutputNotDeletedSuccess() { @Test @DisplayName("Should stop live event by id") void stopLiveEvent() { - var liveEventName = "liveEventName"; + final String liveEventName = "liveEventName"; mediaKind.stopLiveEvent(liveEventName); @@ -1479,7 +1537,7 @@ void stopLiveEvent() { @Test @DisplayName("Should stop live event by id, or do nothing if id doesn't exist") void stopLiveEventOnError() { - var liveEventName = "liveEventName"; + final String liveEventName = "liveEventName"; doThrow(NotFoundException.class).when(mockClient).stopLiveEvent(liveEventName); mediaKind.stopLiveEvent(liveEventName); @@ -1614,8 +1672,9 @@ void importAssetFinalAssetFailure() { @Test @DisplayName("Should not detect live feed when no subperiods are present in the asset tracks") void playLiveEventNoPeriodsSuccess() throws JsonProcessingException, InterruptedException { - var liveEventName = captureSession.getId().toString().replace("-", ""); + final String liveEventName = captureSession.getId().toString().replace("-", ""); var mockLiveEvent = mock(MkLiveEvent.class); + var mockAssetStorage = mock(MkAssetStorage.class); when(mockClient.getStreamingEndpointByName("default-live")) .thenReturn(MkStreamingEndpoint.builder() @@ -1631,7 +1690,6 @@ void playLiveEventNoPeriodsSuccess() throws JsonProcessingException, Interrupted .build() ); - var mockAssetStorage = mock(MkAssetStorage.class); when(mockClient.getAssetTracks(liveEventName)).thenReturn(mockAssetStorage); when(mockAssetStorage.getSpec()) .thenReturn( @@ -1651,8 +1709,8 @@ void playLiveEventNoPeriodsSuccess() throws JsonProcessingException, Interrupted @Test @DisplayName("Should detect live feed when subperiods are present in the asset tracks") void playLiveEventWithPeriodsSuccess() throws JsonProcessingException, InterruptedException { - var liveEventName = captureSession.getId().toString().replace("-", ""); - var mockLiveEvent = mock(MkLiveEvent.class); + final String liveEventName = captureSession.getId().toString().replace("-", ""); + mockFinishedRecording(liveEventName); when(mockClient.getStreamingEndpointByName("default-live")) .thenReturn(MkStreamingEndpoint.builder() @@ -1660,25 +1718,7 @@ void playLiveEventWithPeriodsSuccess() throws JsonProcessingException, Interrupt .resourceState(MkStreamingEndpointProperties.ResourceState.Running) .build()) .build()); - when(mockClient.getLiveEvent(liveEventName)).thenReturn(mockLiveEvent); - when(mockLiveEvent.getProperties()) - .thenReturn( - MkLiveEventProperties.builder() - .resourceState(LiveEventResourceState.RUNNING.toString()) - .build() - ); - var mockAssetStorage = mock(MkAssetStorage.class); - when(mockClient.getAssetTracks(liveEventName)).thenReturn(mockAssetStorage); - - var examplePeriods = JsonNodeFactory.instance.objectNode(); - examplePeriods.set("0/index/edge", JsonNodeFactory.instance.objectNode()); - when(mockAssetStorage.getSpec()) - .thenReturn( - MkAssetStorage.MkAssetStorageSpec.builder() - .periods(examplePeriods) - .build() - ); when(mockClient.getStreamingLocator(any())) .thenReturn(MkStreamingLocator.builder().build()); From 7d35be035829f537344090b01a3d707731133751 Mon Sep 17 00:00:00 2001 From: George Barnes Date: Tue, 6 Jan 2026 17:01:22 +0000 Subject: [PATCH 3/5] Cleanup mig file --- Migration Reports/Alternative_Email_Report-2026-01-06-16:54.csv | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 Migration Reports/Alternative_Email_Report-2026-01-06-16:54.csv diff --git a/Migration Reports/Alternative_Email_Report-2026-01-06-16:54.csv b/Migration Reports/Alternative_Email_Report-2026-01-06-16:54.csv deleted file mode 100644 index 4934a8b9a8..0000000000 --- a/Migration Reports/Alternative_Email_Report-2026-01-06-16:54.csv +++ /dev/null @@ -1,2 +0,0 @@ -email,alternativeEmail,status,message -test@example.com,existing@example.com.cjsm.net,SUCCESS,Alternative email updated successfully From cbf012b48603dec6ea65996f31297553995f07b9 Mon Sep 17 00:00:00 2001 From: George Barnes Date: Tue, 6 Jan 2026 17:24:37 +0000 Subject: [PATCH 4/5] Remove gc_state detection method instead of deprecation --- .../storage/AzureIngestStorageService.java | 6 ---- .../AzureIngestStorageServiceTest.java | 30 ------------------- 2 files changed, 36 deletions(-) diff --git a/src/main/java/uk/gov/hmcts/reform/preapi/media/storage/AzureIngestStorageService.java b/src/main/java/uk/gov/hmcts/reform/preapi/media/storage/AzureIngestStorageService.java index f0e4f0418b..15a3347023 100644 --- a/src/main/java/uk/gov/hmcts/reform/preapi/media/storage/AzureIngestStorageService.java +++ b/src/main/java/uk/gov/hmcts/reform/preapi/media/storage/AzureIngestStorageService.java @@ -33,10 +33,4 @@ public boolean sectionFileExist(String containerName) { .stream() .anyMatch(blobItem -> blobItem.getName().equalsIgnoreCase("0/section")); } - - // Deprecated, do not rely on MK internal state to determine recording status - @Deprecated - public boolean doesValidAssetExist(String containerName) { - return doesIsmFileExist(containerName) || doesBlobExist(containerName, BLOB_GC_STATE); - } } diff --git a/src/test/java/uk/gov/hmcts/reform/preapi/media/storage/AzureIngestStorageServiceTest.java b/src/test/java/uk/gov/hmcts/reform/preapi/media/storage/AzureIngestStorageServiceTest.java index 4e76f52b43..e435b6ee81 100644 --- a/src/test/java/uk/gov/hmcts/reform/preapi/media/storage/AzureIngestStorageServiceTest.java +++ b/src/test/java/uk/gov/hmcts/reform/preapi/media/storage/AzureIngestStorageServiceTest.java @@ -67,36 +67,6 @@ void setUp() { when(blobContainerClient.listBlobs()).thenReturn(pagedIterable); } - @Test - void doesValidAssetExistTrueIsmFound() { - var blobItem = mock(BlobItem.class); - when(blobContainerClient.exists()).thenReturn(true); - when(blobItem.getName()).thenReturn("video.ism"); - when(pagedIterable.stream()).thenReturn(Stream.of(blobItem)); - - assertTrue(azureIngestStorageService.doesValidAssetExist("test-container")); - } - - @Test - void doesValidAssetExistTrueGcStateFound() { - var blobItem = mock(BlobItem.class); - when(blobContainerClient.exists()).thenReturn(true); - when(blobItem.getName()).thenReturn("gc_state"); - when(pagedIterable.stream()).thenAnswer(inv -> Stream.of(blobItem)); - - assertTrue(azureIngestStorageService.doesValidAssetExist("test-container")); - } - - @Test - void doesValidAssetExistFalse() { - var blobItem = mock(BlobItem.class); - when(blobContainerClient.exists()).thenReturn(true); - when(blobItem.getName()).thenReturn("something-else.mp4"); - when(pagedIterable.stream()).thenAnswer(inv -> Stream.of(blobItem)); - - assertFalse(azureIngestStorageService.doesValidAssetExist("test-container")); - } - @Test void uploadBlobSuccess() throws IOException { var tempFile = Files.createTempFile("test", ".mp4"); From fa287104914d211fb560e81228cc47151931679c Mon Sep 17 00:00:00 2001 From: George Barnes Date: Wed, 7 Jan 2026 08:50:47 +0000 Subject: [PATCH 5/5] Remove test refs to gc_state --- .../CaptureSessionStatusCorrectionTaskIT.java | 14 -------------- .../media/storage/AzureIngestStorageService.java | 1 - .../controller/MediaServiceControllerTest.java | 2 +- 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/src/integrationTest/java/uk/gov/hmcts/reform/preapi/tasks/CaptureSessionStatusCorrectionTaskIT.java b/src/integrationTest/java/uk/gov/hmcts/reform/preapi/tasks/CaptureSessionStatusCorrectionTaskIT.java index 9d79b68a3e..e09ca57185 100644 --- a/src/integrationTest/java/uk/gov/hmcts/reform/preapi/tasks/CaptureSessionStatusCorrectionTaskIT.java +++ b/src/integrationTest/java/uk/gov/hmcts/reform/preapi/tasks/CaptureSessionStatusCorrectionTaskIT.java @@ -211,20 +211,6 @@ public void shouldCorrectTheStatusOfUnusedCaptureSessions() { entityManager.flush(); - var testContainer1 = createContainer(String.valueOf(captureSession1.getBooking().getId())); - - var testContainer2 = createContainer(String.valueOf(captureSession2.getBooking().getId())); - - testContainer1.getBlobClient("gc_state").upload( - new ByteArrayInputStream("section file content".getBytes()), - "section file content".length() - ); - - testContainer2.getBlobClient("gc_state").upload( - new ByteArrayInputStream("gc stuff".getBytes()), - "gc stuff".length() - ); - //Run correction task captureSessionStatusCorrectionTask.run(); diff --git a/src/main/java/uk/gov/hmcts/reform/preapi/media/storage/AzureIngestStorageService.java b/src/main/java/uk/gov/hmcts/reform/preapi/media/storage/AzureIngestStorageService.java index 15a3347023..de3fb41f13 100644 --- a/src/main/java/uk/gov/hmcts/reform/preapi/media/storage/AzureIngestStorageService.java +++ b/src/main/java/uk/gov/hmcts/reform/preapi/media/storage/AzureIngestStorageService.java @@ -7,7 +7,6 @@ @Service public class AzureIngestStorageService extends AzureStorageService { - private static final String BLOB_GC_STATE = "gc_state"; private static final String TAG_KEY_STATUS = "status"; private static final String TAG_VALUE_PROCESSING = "processing"; private static final String TAG_VALUE_SAFE_TO_DELETE = "safe_to_delete"; diff --git a/src/test/java/uk/gov/hmcts/reform/preapi/controller/MediaServiceControllerTest.java b/src/test/java/uk/gov/hmcts/reform/preapi/controller/MediaServiceControllerTest.java index 55fb9080ea..e64dbcba78 100644 --- a/src/test/java/uk/gov/hmcts/reform/preapi/controller/MediaServiceControllerTest.java +++ b/src/test/java/uk/gov/hmcts/reform/preapi/controller/MediaServiceControllerTest.java @@ -889,7 +889,7 @@ void checkStreamCaptureSessionIsmFileExists() throws Exception { @Test @DisplayName("Should return 200 with updated capture session when streaming path exists") - void checkStreamCaptureSessionGcStateExists() throws Exception { + void checkStreamCaptureSessionStreamingPathExists() throws Exception { var dto = new CaptureSessionDTO(); dto.setId(UUID.randomUUID()); dto.setStatus(RecordingStatus.STANDBY);