From 613c290cf9bba96ddbfa69062f01174e3662ddef Mon Sep 17 00:00:00 2001 From: Kai Moritz Date: Sun, 20 Aug 2023 12:20:55 +0200 Subject: [PATCH] TEST+FIX: Unknown ChatRoom --- .../persistence/kafka/ChatRoomChannel.java | 8 +++++ .../persistence/kafka/KafkaChatHome.java | 5 ++- .../chat/backend/AbstractConfigurationIT.java | 32 +++++++++++++++++++ .../AbstractConfigurationWithShardingIT.java | 8 ++++- 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/juplo/kafka/chat/backend/persistence/kafka/ChatRoomChannel.java b/src/main/java/de/juplo/kafka/chat/backend/persistence/kafka/ChatRoomChannel.java index 7f93ad8b..7659d1e1 100644 --- a/src/main/java/de/juplo/kafka/chat/backend/persistence/kafka/ChatRoomChannel.java +++ b/src/main/java/de/juplo/kafka/chat/backend/persistence/kafka/ChatRoomChannel.java @@ -360,6 +360,14 @@ public class ChatRoomChannel implements Runnable, ConsumerRebalanceListener } } + int[] getOwnedShards() + { + return IntStream + .range(0, numShards) + .filter(shard -> isShardOwned[shard]) + .toArray(); + } + Mono getChatRoom(int shard, UUID id) { if (loadInProgress) diff --git a/src/main/java/de/juplo/kafka/chat/backend/persistence/kafka/KafkaChatHome.java b/src/main/java/de/juplo/kafka/chat/backend/persistence/kafka/KafkaChatHome.java index 67990409..ab72269d 100644 --- a/src/main/java/de/juplo/kafka/chat/backend/persistence/kafka/KafkaChatHome.java +++ b/src/main/java/de/juplo/kafka/chat/backend/persistence/kafka/KafkaChatHome.java @@ -2,6 +2,7 @@ package de.juplo.kafka.chat.backend.persistence.kafka; import de.juplo.kafka.chat.backend.domain.ChatHome; import de.juplo.kafka.chat.backend.domain.ChatRoom; +import de.juplo.kafka.chat.backend.domain.UnknownChatroomException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.kafka.common.utils.Utils; @@ -23,7 +24,9 @@ public class KafkaChatHome implements ChatHome public Mono getChatRoom(UUID id) { int shard = selectShard(id); - return chatRoomChannel.getChatRoom(shard, id); + return chatRoomChannel + .getChatRoom(shard, id) + .switchIfEmpty(Mono.error(() -> new UnknownChatroomException(id))); } int selectShard(UUID chatRoomId) diff --git a/src/test/java/de/juplo/kafka/chat/backend/AbstractConfigurationIT.java b/src/test/java/de/juplo/kafka/chat/backend/AbstractConfigurationIT.java index 53ad04ea..6db38b29 100644 --- a/src/test/java/de/juplo/kafka/chat/backend/AbstractConfigurationIT.java +++ b/src/test/java/de/juplo/kafka/chat/backend/AbstractConfigurationIT.java @@ -1,5 +1,6 @@ package de.juplo.kafka.chat.backend; +import de.juplo.kafka.chat.backend.persistence.inmemory.ShardingStrategy; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -10,6 +11,8 @@ import org.testcontainers.shaded.org.awaitility.Awaitility; import java.time.Duration; +import static org.hamcrest.Matchers.endsWith; + public abstract class AbstractConfigurationIT { @@ -17,6 +20,9 @@ public abstract class AbstractConfigurationIT int port; @Autowired WebTestClient webTestClient; + @Autowired + ShardingStrategy shardingStrategy; + @Test @DisplayName("The app starts, the data is restored and accessible") @@ -79,4 +85,30 @@ public abstract class AbstractConfigurationIT .expectBody().jsonPath("$.text").isEqualTo("Hallo, ich heiße Peter!"); }); } + + @Test + @DisplayName("A PUT-message for a non-existent chat-room yields 404 NOT FOUND") + void testNotFoundForPutMessageToNonExistentChatRoom() + { + String otherChatRoomId = "7f59ec77-832e-4a17-8d22-55ef46242c17"; + + Awaitility + .await() + .atMost(Duration.ofSeconds(15)) + .untilAsserted(() -> + webTestClient + .put() + .uri( + "http://localhost:{port}/{chatRoomId}/otto/66", + port, + otherChatRoomId) + .contentType(MediaType.TEXT_PLAIN) + .accept(MediaType.APPLICATION_JSON) + .bodyValue("The devil rules route 66") + .exchange() + .expectStatus().isNotFound() + .expectBody() + .jsonPath("$.type").value(endsWith("/problem/unknown-chatroom")) + .jsonPath("$.chatroomId").isEqualTo(otherChatRoomId)); + } } diff --git a/src/test/java/de/juplo/kafka/chat/backend/AbstractConfigurationWithShardingIT.java b/src/test/java/de/juplo/kafka/chat/backend/AbstractConfigurationWithShardingIT.java index e6fd95a9..5c9ac13f 100644 --- a/src/test/java/de/juplo/kafka/chat/backend/AbstractConfigurationWithShardingIT.java +++ b/src/test/java/de/juplo/kafka/chat/backend/AbstractConfigurationWithShardingIT.java @@ -7,6 +7,8 @@ import org.testcontainers.shaded.org.awaitility.Awaitility; import java.time.Duration; +import static org.hamcrest.Matchers.endsWith; + public abstract class AbstractConfigurationWithShardingIT extends AbstractConfigurationIT { @@ -15,6 +17,7 @@ public abstract class AbstractConfigurationWithShardingIT extends AbstractConfig void testNotFoundForPutMessageToAChatRoomInNotOwnedShard() { String otherChatRoomId = "4e7246a6-29ae-43ea-b56f-669c3481ac19"; + int shard = 0; Awaitility .await() @@ -30,6 +33,9 @@ public abstract class AbstractConfigurationWithShardingIT extends AbstractConfig .accept(MediaType.APPLICATION_JSON) .bodyValue("The devil rules route 66") .exchange() - .expectStatus().isNotFound()); + .expectStatus().isNotFound() + .expectBody() + .jsonPath("$.type").value(endsWith("/problem/shard-not-owned")) + .jsonPath("$.shard").isEqualTo(shard)); } } -- 2.20.1