From f28d5ec2910bf12d547c3be4fe8debd4707c514a Mon Sep 17 00:00:00 2001 From: Lou Andria Date: Wed, 22 Jul 2026 13:56:39 +0200 Subject: [PATCH 1/3] fix: use presign instead of download as existence test of cache --- src/main/java/fr/birdia/cacher/service/CacheService.java | 5 ++--- .../cacher/endpoint/rest/controller/CacherControllerIT.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/fr/birdia/cacher/service/CacheService.java b/src/main/java/fr/birdia/cacher/service/CacheService.java index 6aa05a2..c06b80a 100644 --- a/src/main/java/fr/birdia/cacher/service/CacheService.java +++ b/src/main/java/fr/birdia/cacher/service/CacheService.java @@ -29,13 +29,12 @@ public class CacheService { public URL getWithCache(URL url) { var bucketKey = SHA256.apply(url.toString()); try { - var cachedFile = bucketComponent.download(bucketKey); - log.info("isCachedFile null: " + (cachedFile == null)); // TODO: clean + return bucketComponent.presign(bucketKey, DOWNLOAD_DURATION); } catch (Exception e) { var downloadedFromSource = downloadWithGet(url); bucketComponent.upload(downloadedFromSource, bucketKey); + return bucketComponent.presign(bucketKey, DOWNLOAD_DURATION); } - return bucketComponent.presign(bucketKey, DOWNLOAD_DURATION); } @SneakyThrows diff --git a/src/test/java/fr/birdia/cacher/endpoint/rest/controller/CacherControllerIT.java b/src/test/java/fr/birdia/cacher/endpoint/rest/controller/CacherControllerIT.java index 79595c6..314afe6 100644 --- a/src/test/java/fr/birdia/cacher/endpoint/rest/controller/CacherControllerIT.java +++ b/src/test/java/fr/birdia/cacher/endpoint/rest/controller/CacherControllerIT.java @@ -43,8 +43,8 @@ void miss() throws MalformedURLException { var bucketKey = SHA256.apply(decodedUrl); assertEquals("8547b3662d07fb7867a11c2c89672a664fd6e4ffb370dee9f60e0e65eeebde09", bucketKey); - when(bucketComponent.download(bucketKey)).thenThrow(new RuntimeException("cache miss")); when(bucketComponent.presign(eq(bucketKey), any(Duration.class))) + .thenThrow(new RuntimeException("cache miss")) .thenReturn( URI.create("https://example.com/presigned?param1=3¶m2=4%20param3=5").toURL()); From 69be3a031f095324d9a060ee37be0365d3399c11 Mon Sep 17 00:00:00 2001 From: Lou Andria Date: Wed, 22 Jul 2026 14:36:10 +0200 Subject: [PATCH 2/3] fix: even BucketComponent::presign is not enough, create ExtendedBucketComponent::exists --- .../file/bucket/ExtendedBucketComponent.java | 26 +++++++++++++++++++ .../birdia/cacher/service/CacheService.java | 11 ++++---- .../rest/controller/CacherControllerIT.java | 6 ++--- 3 files changed, 34 insertions(+), 9 deletions(-) create mode 100644 src/main/java/fr/birdia/cacher/file/bucket/ExtendedBucketComponent.java diff --git a/src/main/java/fr/birdia/cacher/file/bucket/ExtendedBucketComponent.java b/src/main/java/fr/birdia/cacher/file/bucket/ExtendedBucketComponent.java new file mode 100644 index 0000000..6ddfaaa --- /dev/null +++ b/src/main/java/fr/birdia/cacher/file/bucket/ExtendedBucketComponent.java @@ -0,0 +1,26 @@ +package fr.birdia.cacher.file.bucket; + +import org.springframework.stereotype.Component; +import software.amazon.awssdk.services.s3.model.HeadObjectRequest; +import software.amazon.awssdk.services.s3.model.NoSuchKeyException; + +@Component +public class ExtendedBucketComponent extends BucketComponent { + private final BucketConf bucketConf; + + public ExtendedBucketComponent(BucketConf bucketConf) { + super(bucketConf); + this.bucketConf = bucketConf; + } + + public boolean exists(String objectKey) { + var s3client = bucketConf.getS3Client(); + try { + s3client.headObject( + HeadObjectRequest.builder().bucket(bucketConf.getBucketName()).key(objectKey).build()); + return true; + } catch (NoSuchKeyException e) { + return false; + } + } +} diff --git a/src/main/java/fr/birdia/cacher/service/CacheService.java b/src/main/java/fr/birdia/cacher/service/CacheService.java index c06b80a..f58339f 100644 --- a/src/main/java/fr/birdia/cacher/service/CacheService.java +++ b/src/main/java/fr/birdia/cacher/service/CacheService.java @@ -2,7 +2,7 @@ import static java.net.http.HttpClient.newHttpClient; -import fr.birdia.cacher.file.bucket.BucketComponent; +import fr.birdia.cacher.file.bucket.ExtendedBucketComponent; import fr.birdia.cacher.hash.SHA256; import java.io.File; import java.io.FileOutputStream; @@ -20,7 +20,8 @@ @AllArgsConstructor @Service public class CacheService { - private final BucketComponent bucketComponent; + private final ExtendedBucketComponent bucketComponent; + private final SHA256 SHA256; private final Duration DOWNLOAD_DURATION = Duration.ofMinutes(5); @@ -28,13 +29,11 @@ public class CacheService { public URL getWithCache(URL url) { var bucketKey = SHA256.apply(url.toString()); - try { - return bucketComponent.presign(bucketKey, DOWNLOAD_DURATION); - } catch (Exception e) { + if (!bucketComponent.exists(bucketKey)) { var downloadedFromSource = downloadWithGet(url); bucketComponent.upload(downloadedFromSource, bucketKey); - return bucketComponent.presign(bucketKey, DOWNLOAD_DURATION); } + return bucketComponent.presign(bucketKey, DOWNLOAD_DURATION); } @SneakyThrows diff --git a/src/test/java/fr/birdia/cacher/endpoint/rest/controller/CacherControllerIT.java b/src/test/java/fr/birdia/cacher/endpoint/rest/controller/CacherControllerIT.java index 314afe6..85bc55e 100644 --- a/src/test/java/fr/birdia/cacher/endpoint/rest/controller/CacherControllerIT.java +++ b/src/test/java/fr/birdia/cacher/endpoint/rest/controller/CacherControllerIT.java @@ -9,7 +9,7 @@ import static org.mockito.Mockito.when; import fr.birdia.cacher.conf.FacadeIT; -import fr.birdia.cacher.file.bucket.BucketComponent; +import fr.birdia.cacher.file.bucket.ExtendedBucketComponent; import fr.birdia.cacher.hash.SHA256; import java.io.File; import java.net.MalformedURLException; @@ -26,7 +26,7 @@ class CacherControllerIT extends FacadeIT { @Autowired SHA256 SHA256; - @MockBean BucketComponent bucketComponent; + @MockBean ExtendedBucketComponent bucketComponent; @Test void unauthorized() { @@ -43,8 +43,8 @@ void miss() throws MalformedURLException { var bucketKey = SHA256.apply(decodedUrl); assertEquals("8547b3662d07fb7867a11c2c89672a664fd6e4ffb370dee9f60e0e65eeebde09", bucketKey); + when(bucketComponent.exists(bucketKey)).thenReturn(false); when(bucketComponent.presign(eq(bucketKey), any(Duration.class))) - .thenThrow(new RuntimeException("cache miss")) .thenReturn( URI.create("https://example.com/presigned?param1=3¶m2=4%20param3=5").toURL()); From a10f0f65d5538343237817c990e1d9ced640b6f8 Mon Sep 17 00:00:00 2001 From: "poja[bot]" Date: Wed, 22 Jul 2026 12:40:11 +0000 Subject: [PATCH 3/3] poja: deployment ID: 61ce62eb-8c74-44ba-9d06-ffe5fabd8627 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e193d04..fc5a171 100644 --- a/build.gradle +++ b/build.gradle @@ -58,7 +58,7 @@ jacocoTestCoverageVerification { rule { limit { counter = "LINE" - minimum = 0.8 + minimum = 0.7 } } }