From 2501aa857c7d42daf571392c2c5e5cf98d1519bc Mon Sep 17 00:00:00 2001 From: Stefan <> Date: Sat, 16 Mar 2024 22:18:49 +0100 Subject: [PATCH] test onetime reads under load --- .../paste/application/PasteService.java | 3 +- .../binpastes/paste/api/OneTimePastesIT.java | 28 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/github/binpastes/paste/application/PasteService.java b/backend/src/main/java/com/github/binpastes/paste/application/PasteService.java index 7f6244c..894cad2 100644 --- a/backend/src/main/java/com/github/binpastes/paste/application/PasteService.java +++ b/backend/src/main/java/com/github/binpastes/paste/application/PasteService.java @@ -58,7 +58,8 @@ private Mono trackAccess(Paste paste) { return result .map(p -> p.trackView(LocalDateTime.now())) .flatMap(pasteRepository::save) - .doOnSuccess(burntPaste -> log.info("OneTime paste {} viewed and burnt", burntPaste.getId())); + .doOnSuccess(burntPaste -> log.info("OneTime paste {} viewed and burnt", burntPaste.getId())) + .onErrorResume(OptimisticLockingFailureException.class, throwable -> Mono.empty()); } trackingService.trackView(paste.getId()); diff --git a/backend/src/test/java/com/github/binpastes/paste/api/OneTimePastesIT.java b/backend/src/test/java/com/github/binpastes/paste/api/OneTimePastesIT.java index 8fa7361..0eaeb6b 100644 --- a/backend/src/test/java/com/github/binpastes/paste/api/OneTimePastesIT.java +++ b/backend/src/test/java/com/github/binpastes/paste/api/OneTimePastesIT.java @@ -15,6 +15,9 @@ import org.springframework.test.web.reactive.server.WebTestClient; import reactor.core.publisher.Mono; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Stream; + import static java.time.Duration.ofMillis; import static java.time.LocalDateTime.now; import static java.time.LocalDateTime.parse; @@ -66,6 +69,31 @@ void getOneTimePasteTwice() { .expectStatus().isNotFound(); } + @Test + @DisplayName("GET /{pasteId} - one-time paste is read-once even under load") + void getOneTimePasteConcurrently() { + var oneTimePaste = givenOneTimePaste(); + var okCount = new AtomicInteger(); + + Runnable call = () -> { + try { + webClient.get() + .uri("/api/v1/paste/" + oneTimePaste.getId()) + .exchange() + .expectStatus().isNotFound(); + } catch (AssertionError e) { + okCount.incrementAndGet(); + } + }; + + Stream.generate(() -> call) + .parallel() + .limit(100) + .forEach(Runnable::run); + + assertThat(okCount.get()).isOne(); + } + @Test @DisplayName("GET / - one-time paste is never listed") void findAllPastes() {