diff --git a/provider/storage-azure/src/main/java/org/opengroup/osdu/storage/provider/azure/CloudStorageImpl.java b/provider/storage-azure/src/main/java/org/opengroup/osdu/storage/provider/azure/CloudStorageImpl.java index bbc4124801816ad5fb9a8eeb094ca9aac8a9c0d2..5077db8fd1972a163f9fe264ed97c627eff95fa1 100644 --- a/provider/storage-azure/src/main/java/org/opengroup/osdu/storage/provider/azure/CloudStorageImpl.java +++ b/provider/storage-azure/src/main/java/org/opengroup/osdu/storage/provider/azure/CloudStorageImpl.java @@ -206,8 +206,21 @@ public class CloudStorageImpl implements ICloudStorage { @Override public void deleteVersions(List<String> versionPaths) { - versionPaths.stream().forEach(versionPath -> - blobStore.deleteFromStorageContainer(headers.getPartitionId(), versionPath, containerName)); + versionPaths.stream().forEach(versionPath -> { + try { + blobStore.deleteFromStorageContainer(headers.getPartitionId(), versionPath, containerName); + } catch (AppException ex) { + // It is possible that the record may have a version instance that is present in the metadata store and absent from the the blob store. + // This is a known inconsistency caused when we fail to successfully add the version instance to the blob store. + // To handle it we should ignore deletions from the blob store that result in a 404 (not found) error. + if (ex.getError().getCode() == 404) { + this.logger.warning(String.format("Deletion Failed. Tried to delete non-existent version in storage account: %s", versionPath)); + } + else { + throw ex; + } + } + }); } @Override diff --git a/provider/storage-azure/src/test/java/org/opengroup/osdu/storage/provider/azure/CloudStorageImplTest.java b/provider/storage-azure/src/test/java/org/opengroup/osdu/storage/provider/azure/CloudStorageImplTest.java index b75749c94d82b7263b17ae14e6ed5d673de60352..faf0591bde83f7290f8cab5408a31d60ce44253c 100644 --- a/provider/storage-azure/src/test/java/org/opengroup/osdu/storage/provider/azure/CloudStorageImplTest.java +++ b/provider/storage-azure/src/test/java/org/opengroup/osdu/storage/provider/azure/CloudStorageImplTest.java @@ -416,7 +416,6 @@ class CloudStorageImplTest { @Test void shouldDeleteVersionsSuccessfully() { - List<String> versionPaths = Arrays.asList("versionPath1", "versionPath2"); when(headers.getPartitionId()).thenReturn(DATA_PARTITION); @@ -424,7 +423,41 @@ class CloudStorageImplTest { versionPaths.forEach(versionPath -> verify(blobStore, times(1)).deleteFromStorageContainer(DATA_PARTITION, versionPath, CONTAINER)); + } + + @Test + void deleteAllVersionsSuccessfully_when_blobThrowsNotFound() { + List<String> versionPaths = Arrays.asList("versionPath1", "versionPath2", "versionPath3"); + when(headers.getPartitionId()).thenReturn(DATA_PARTITION); + when(blobStore.deleteFromStorageContainer(DATA_PARTITION, "versionPath1", CONTAINER)).thenThrow(new AppException(404, "BlobNotFound", "404")); + when(blobStore.deleteFromStorageContainer(DATA_PARTITION, "versionPath2", CONTAINER)).thenReturn(true); + when(blobStore.deleteFromStorageContainer(DATA_PARTITION, "versionPath3", CONTAINER)).thenReturn(true); + + cloudStorage.deleteVersions(versionPaths); + + // All versions should continue to be deleted after a 404 from blob store is eaten successfully. + versionPaths.forEach(versionPath -> + verify(blobStore, times(1)).deleteFromStorageContainer(DATA_PARTITION, versionPath, CONTAINER)); + } + + @Test + void deleteAllVersionsFails_when_blobThrowsRandomException() { + List<String> versionPaths = Arrays.asList("versionPath1", "versionPath2", "versionPath3"); + when(headers.getPartitionId()).thenReturn(DATA_PARTITION); + when(blobStore.deleteFromStorageContainer(DATA_PARTITION, "versionPath1", CONTAINER)).thenReturn(true); + when(blobStore.deleteFromStorageContainer(DATA_PARTITION, "versionPath2", CONTAINER)).thenThrow(new AppException(500, "Random error", "500")); + + assertThrows(AppException.class, () -> cloudStorage.deleteVersions(versionPaths)); + + // versionPath1 deletes successfully. + verify(blobStore, times(1)).deleteFromStorageContainer(DATA_PARTITION, "versionPath1", CONTAINER); + + // versionPath2 delete is called but fails. + verify(blobStore, times(1)).deleteFromStorageContainer(DATA_PARTITION, "versionPath2", CONTAINER); + // Other than 404 by blob store, no exception should be eaten. + // Delete for versionPath3 is never called, as it failed at versionPath2. + verify(blobStore, times(0)).deleteFromStorageContainer(DATA_PARTITION, "versionPath3", CONTAINER); } @Test