feat: `UnknownChatroomException` records shard and owned shards
authorKai Moritz <kai@juplo.de>
Mon, 21 Aug 2023 16:26:53 +0000 (18:26 +0200)
committerKai Moritz <kai@juplo.de>
Sat, 27 Jan 2024 14:16:22 +0000 (15:16 +0100)
src/main/java/de/juplo/kafka/chat/backend/api/ChatBackendControllerAdvice.java
src/main/java/de/juplo/kafka/chat/backend/domain/UnknownChatroomException.java
src/main/java/de/juplo/kafka/chat/backend/persistence/inmemory/InMemoryChatHomeService.java
src/main/java/de/juplo/kafka/chat/backend/persistence/inmemory/SimpleChatHome.java
src/main/java/de/juplo/kafka/chat/backend/persistence/kafka/KafkaChatHome.java
src/test/java/de/juplo/kafka/chat/backend/api/ChatBackendControllerTest.java

index ad90c4b..47b46bc 100644 (file)
@@ -47,6 +47,8 @@ public class ChatBackendControllerAdvice
     problem.setDetail(stringBuilder.toString());
 
     problem.setProperty("chatroomId", e.getChatroomId());
+    problem.setProperty("shard", e.getShard());
+    problem.setProperty("ownedShards", e.getOwnedShards());
 
     return problem;
   }
index 1f70f11..714c220 100644 (file)
@@ -2,17 +2,43 @@ package de.juplo.kafka.chat.backend.domain;
 
 import lombok.Getter;
 
+import java.util.Arrays;
+import java.util.Optional;
 import java.util.UUID;
+import java.util.stream.Collectors;
 
 
-public class UnknownChatroomException extends RuntimeException
+public class UnknownChatroomException extends IllegalStateException
 {
   @Getter
   private final UUID chatroomId;
+  @Getter
+  private final Optional<Integer> shard;
+  @Getter
+  private final Optional<int[]> ownedShards;
 
   public UnknownChatroomException(UUID chatroomId)
   {
     super("Chatroom does not exist: " + chatroomId);
     this.chatroomId = chatroomId;
+    this.shard = Optional.empty();
+    this.ownedShards = Optional.empty();
+  }
+
+  public UnknownChatroomException(UUID chatroomId, int shard, int[] ownedShards)
+  {
+    super(
+        "Chatroom does not exist (here): " +
+        chatroomId +
+        " shard=" +
+        shard +
+        ", owned=" +
+        Arrays
+            .stream(ownedShards)
+            .mapToObj(ownedShard -> Integer.toString(ownedShard))
+            .collect(Collectors.joining(",")));
+    this.chatroomId = chatroomId;
+    this.shard = Optional.of(shard);
+    this.ownedShards = Optional.of(ownedShards);
   }
 }
index 1334124..29f1312 100644 (file)
@@ -6,6 +6,7 @@ import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
 import java.util.*;
+import java.util.stream.IntStream;
 
 
 @Slf4j
@@ -60,6 +61,14 @@ public class InMemoryChatHomeService
     return Mono.justOrEmpty(chatrooms[shard].get(id));
   }
 
+  public int[] getOwnedShards()
+  {
+    return IntStream
+        .range(0, chatrooms.length)
+        .filter(i -> chatrooms[i] != null)
+        .toArray();
+  }
+
   public Flux<ChatRoom> getChatRooms(int shard)
   {
     return Flux.fromStream(chatrooms[shard].values().stream());
index e35a661..f99bc9d 100644 (file)
@@ -35,7 +35,10 @@ public class SimpleChatHome implements ChatHome
   {
     return service
         .getChatRoom(shard, id)
-        .switchIfEmpty(Mono.error(() -> new UnknownChatroomException(id)));
+        .switchIfEmpty(Mono.error(() -> new UnknownChatroomException(
+            id,
+            shard,
+            service.getOwnedShards())));
   }
 
   @Override
index ab72269..07fb885 100644 (file)
@@ -26,7 +26,10 @@ public class KafkaChatHome implements ChatHome
     int shard = selectShard(id);
     return chatRoomChannel
         .getChatRoom(shard, id)
-        .switchIfEmpty(Mono.error(() -> new UnknownChatroomException(id)));
+        .switchIfEmpty(Mono.error(() -> new UnknownChatroomException(
+            id,
+            shard,
+            chatRoomChannel.getOwnedShards())));
   }
 
   int selectShard(UUID chatRoomId)
index 5df4314..32b1e35 100644 (file)
@@ -53,6 +53,7 @@ public class ChatBackendControllerTest
     // Given
     UUID chatroomId = getRandomIdForOwnedShard();
     when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
+    when(chatHomeService.getOwnedShards()).thenReturn(new int[] { 6 });
 
     // When
     WebTestClient.ResponseSpec responseSpec = client
@@ -73,6 +74,7 @@ public class ChatBackendControllerTest
     // Given
     UUID chatroomId = getRandomIdForOwnedShard();
     when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
+    when(chatHomeService.getOwnedShards()).thenReturn(new int[] { 6 });
 
     // When
     WebTestClient.ResponseSpec responseSpec = client
@@ -94,6 +96,7 @@ public class ChatBackendControllerTest
     String username = "foo";
     Long messageId = 66l;
     when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
+    when(chatHomeService.getOwnedShards()).thenReturn(new int[] { 6 });
 
     // When
     WebTestClient.ResponseSpec responseSpec = client
@@ -120,6 +123,7 @@ public class ChatBackendControllerTest
     String username = "foo";
     Long messageId = 66l;
     when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
+    when(chatHomeService.getOwnedShards()).thenReturn(new int[] { 6 });
 
     // When
     WebTestClient.ResponseSpec responseSpec = client
@@ -143,6 +147,7 @@ public class ChatBackendControllerTest
     // Given
     UUID chatroomId = getRandomIdForOwnedShard();
     when(chatHomeService.getChatRoom(anyInt(), any(UUID.class))).thenReturn(Mono.empty());
+    when(chatHomeService.getOwnedShards()).thenReturn(new int[] { 6 });
 
     // When
     WebTestClient.ResponseSpec responseSpec = client