refactor: Refined channel-states, introduced `ChannelState` -- MOVE
[demos/kafka/chat] / src / main / java / de / juplo / kafka / chat / backend / implementation / kafka / DataChannel.java
index fdb16fb..e1754a1 100644 (file)
@@ -35,7 +35,7 @@ public class DataChannel implements Runnable, ConsumerRebalanceListener
   private final long[] currentOffset;
   private final long[] nextOffset;
   private final Map<UUID, ChatRoomData>[] chatRoomData;
-  private final InfoChannel infoChannel;
+  private final ChannelMediator channelMediator;
   private final ShardingPublisherStrategy shardingPublisherStrategy;
 
   private boolean running;
@@ -53,7 +53,7 @@ public class DataChannel implements Runnable, ConsumerRebalanceListener
     Duration pollingInterval,
     int bufferSize,
     Clock clock,
-    InfoChannel infoChannel,
+    ChannelMediator channelMediator,
     ShardingPublisherStrategy shardingPublisherStrategy)
   {
     log.debug(
@@ -77,7 +77,7 @@ public class DataChannel implements Runnable, ConsumerRebalanceListener
     IntStream
         .range(0, numShards)
         .forEach(shard -> this.chatRoomData[shard] = new HashMap<>());
-    this.infoChannel = infoChannel;
+    this.channelMediator = channelMediator;
     this.shardingPublisherStrategy = shardingPublisherStrategy;
   }
 
@@ -144,7 +144,7 @@ public class DataChannel implements Runnable, ConsumerRebalanceListener
           currentOffset);
 
       consumer.seek(topicPartition, nextOffset[partition]);
-      infoChannel.sendShardAssignedEvent(partition);
+      channelMediator.shardAssigned(partition);
       shardingPublisherStrategy
           .publishOwnership(partition)
           .doOnSuccess(instanceId -> log.info(
@@ -155,7 +155,8 @@ public class DataChannel implements Runnable, ConsumerRebalanceListener
               "Could not publish instance {} as owner of shard {}: {}",
               instanceId,
               partition,
-              throwable))
+              throwable.toString()))
+          .onErrorComplete()
           .block();
     });
 
@@ -171,7 +172,7 @@ public class DataChannel implements Runnable, ConsumerRebalanceListener
       isShardOwned[partition] = false;
       nextOffset[partition] = consumer.position(topicPartition);
       log.info("Partition revoked: {} - next={}", partition, nextOffset[partition]);
-      infoChannel.sendShardRevokedEvent(partition);
+      channelMediator.shardRevoked(partition);
     });
   }
 
@@ -266,9 +267,7 @@ public class DataChannel implements Runnable, ConsumerRebalanceListener
     Message.MessageKey key = Message.MessageKey.of(chatMessageTo.getUser(), chatMessageTo.getId());
     Message message = new Message(key, offset, timestamp, chatMessageTo.getText());
 
-    ChatRoomData chatRoomData = this
-        .chatRoomData[partition]
-        .computeIfAbsent(chatRoomId, this::computeChatRoomData);
+    ChatRoomData chatRoomData = computeChatRoomData(chatRoomId, partition);
     KafkaChatMessageService kafkaChatRoomService =
         (KafkaChatMessageService) chatRoomData.getChatRoomService();
 
@@ -311,6 +310,11 @@ public class DataChannel implements Runnable, ConsumerRebalanceListener
         .toArray();
   }
 
+  void createChatRoomData(ChatRoomInfo chatRoomInfo)
+  {
+    computeChatRoomData(chatRoomInfo.getId(), chatRoomInfo.getShard());
+  }
+
   Mono<ChatRoomData> getChatRoomData(int shard, UUID id)
   {
     if (loadInProgress)
@@ -323,17 +327,28 @@ public class DataChannel implements Runnable, ConsumerRebalanceListener
       return Mono.error(new ShardNotOwnedException(instanceId, shard));
     }
 
-    return infoChannel
-        .getChatRoomInfo(id)
-        .map(chatRoomInfo ->
-            chatRoomData[shard].computeIfAbsent(id, this::computeChatRoomData));
+    return Mono.justOrEmpty(chatRoomData[shard].get(id));
   }
 
-  private ChatRoomData computeChatRoomData(UUID chatRoomId)
+  private ChatRoomData computeChatRoomData(UUID chatRoomId, int shard)
   {
-    log.info("Creating ChatRoom {} with buffer-size {}", chatRoomId, bufferSize);
-    KafkaChatMessageService service = new KafkaChatMessageService(this, chatRoomId);
-    return new ChatRoomData(clock, service, bufferSize);
+    ChatRoomData chatRoomData = this.chatRoomData[shard].get(chatRoomId);
+
+    if (chatRoomData != null)
+    {
+      log.info(
+          "Ignoring request to create already existing ChatRoomData for {}",
+          chatRoomId);
+    }
+    else
+    {
+      log.info("Creating ChatRoomData {} with buffer-size {}", chatRoomId, bufferSize);
+      KafkaChatMessageService service = new KafkaChatMessageService(this, chatRoomId);
+      chatRoomData = new ChatRoomData(clock, service, bufferSize);
+      this.chatRoomData[shard].put(chatRoomId, chatRoomData);
+    }
+
+    return chatRoomData;
   }
 
   ConsumerGroupMetadata getConsumerGroupMetadata()