import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.producer.Producer;
+import org.apache.kafka.clients.producer.ProducerRecord;
+import org.apache.kafka.clients.producer.RecordMetadata;
import org.apache.kafka.common.TopicPartition;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.time.LocalDateTime;
+import java.time.ZoneOffset;
import java.util.LinkedHashMap;
+import java.util.UUID;
+import java.util.concurrent.Future;
@Slf4j
{
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<>();
@Override
- public Message persistMessage(
+ 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 Mono.create(sink ->
+ {
+ ProducerRecord<String, MessageTo> record =
+ new ProducerRecord<>(
+ tp.topic(),
+ tp.partition(),
+ timestamp.toEpochSecond(zoneOffset),
+ chatRoomId.toString(),
+ MessageTo.of(key.getUsername(), key.getMessageId(), text));
+
+ producer.send(record, ((metadata, exception) ->
+ {
+ if (metadata != null)
+ {
+ Message message = messages.get(key);
+ if (message != null)
+ {
+ if (message.getMessageText().equals(text))
+ {
+ // Warn and emit existing message
+ log.warn(
+ "Keeping existing message with {}@{} for {}",
+ message.getSerialNumber(),
+ message.getTimestamp(), key);
+ }
+ else
+ {
+ // Emit error and abort
+ sink.error(new MessageMutationException(message, text));
+ return;
+ }
+ }
+ else
+ {
+ // Emit new message
+ message = new Message(key, metadata.offset(), timestamp, text);
+ messages.put(message.getKey(), message);
+ }
+
+ sink.success();
+ }
+ }));
+ });
}
@Override