import de.juplo.kafka.chat.backend.domain.ChatRoomService;
import de.juplo.kafka.chat.backend.domain.Message;
import de.juplo.kafka.chat.backend.domain.MessageMutationException;
-import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.common.TopicPartition;
import reactor.core.publisher.Mono;
import java.time.LocalDateTime;
+import java.time.ZoneOffset;
import java.util.LinkedHashMap;
+import java.util.UUID;
@Slf4j
-@RequiredArgsConstructor
public class KafkaChatRoomService implements ChatRoomService
{
private final Producer<String, MessageTo> producer;
private final TopicPartition tp;
+ private final UUID chatRoomId;
+ private final ZoneOffset zoneOffset;
private final LinkedHashMap<Message.MessageKey, Message> messages = new LinkedHashMap<>();
- private long offset = 0l;
+ private volatile MessageHandlingStrategy strategy;
+
+
+ public KafkaChatRoomService(
+ Producer<String, MessageTo> producer,
+ TopicPartition tp,
+ UUID chatRoomId,
+ ZoneOffset zoneOffset)
+ {
+ this.producer = producer;
+ this.tp = tp;
+ this.chatRoomId = chatRoomId;
+ this.zoneOffset = zoneOffset;
+ this.strategy = new ChatroomInactiveMessageHandlingStrategy(tp);
+ }
@Override
- public Message persistMessage(
+ synchronized public Mono<Message> persistMessage(
Message.MessageKey key,
LocalDateTime timestamp,
String text)
{
-
- Mono.error(() -> new MessageMutationException(existing, text)));
- Message message = new Message(key, (long)messages.size(), timestamp, text);
- messages.put(message.getKey(), message);
- return message;
+ return strategy.persistMessage(key, timestamp, text);
+ }
+
+ protected void addMessage(Message message) throws MessageMutationException
+ {
+ Message existingMessage = messages.get(message.getKey());
+
+ // TODO: Ist der Test nötig, oder wird das durch den Kontrollierten Wechsel
+ // der Strategie ggf. schon abgefangen? Weil: Wenn es nur um die Sorge geht,
+ // das eine Nachricht schon "durch den Nutzer" anders geschrieben wurde,
+ // fängt dies bereits der ChatRoom ab.
+ // Die Überprüfung hier war vor dem Hintergrund der Sorge hinzugefügt worden,
+ // dass die Nachricht wegen Verschluckern in Kafka / beim Strategiewechsel / ??
+ // doppelt aufschlägt...
+ if (existingMessage == null)
+ {
+ messages.put(message.getKey(), message);
+ }
+ else
+ {
+ if (!existingMessage.getMessageText().equals(message.getMessageText()))
+ {
+ throw new MessageMutationException(existingMessage, message.getMessageText());
+ }
+
+ // Warn and emit existing message
+ log.warn(
+ "Keeping existing message with {}@{} for {}",
+ existingMessage.getSerialNumber(),
+ existingMessage.getTimestamp(),
+ existingMessage.getKey());
+ }
}
@Override
- public Mono<Message> getMessage(Message.MessageKey key)
+ synchronized public Mono<Message> getMessage(Message.MessageKey key)
{
+ // TODO: Aufrufe, auf eine Nachricht (einge gewisse Zeit) warten lassen
+ // und dann bedienen, wenn der der Callback vom Producer aufgerufen wird?
return Mono.fromSupplier(() -> messages.get(key));
}
@Override
- public Flux<Message> getMessages(long first, long last)
+ synchronized public Flux<Message> getMessages(long first, long last)
{
return Flux.fromStream(messages
.values()