From 8b36f121f0937f2fa1e991fe616312ab2d5c6bb4 Mon Sep 17 00:00:00 2001 From: Kai Moritz Date: Sat, 7 Jan 2023 02:16:57 +0100 Subject: [PATCH] fix: The sink is recreated, if it gets canceled - The sink is automatically cancelled, if the last consumer leaves. - Turning auto-cancel of, is not an option, because this buffers new messages, until the buffer overflows, after which new messages are droped. Hence, if a new subscriber arrives, it would see some old messages and then, after a gap, current messages. - Because of that, the sink is now automatically recreated, if the last subscriber leaves and triggers the automatically cancelation of the sink. - The sink can be recreated without conflicts, because all methods, that may access the sink are synchronized. --- .../kafka/chat/backend/domain/Chatroom.java | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/main/java/de/juplo/kafka/chat/backend/domain/Chatroom.java b/src/main/java/de/juplo/kafka/chat/backend/domain/Chatroom.java index 966a28ee..60f7274e 100644 --- a/src/main/java/de/juplo/kafka/chat/backend/domain/Chatroom.java +++ b/src/main/java/de/juplo/kafka/chat/backend/domain/Chatroom.java @@ -18,7 +18,8 @@ public class Chatroom @Getter private final String name; private final PersistenceStrategy persistence; - private final Sinks.Many sink; + private final int bufferSize; + private Sinks.Many sink; public Chatroom( UUID id, @@ -29,7 +30,8 @@ public class Chatroom this.id = id; this.name = name; this.persistence = persistence; - this.sink = Sinks.many().multicast().onBackpressureBuffer(bufferSize); + this.bufferSize = bufferSize; + this.sink = createSink(); } @@ -41,7 +43,14 @@ public class Chatroom { return persistence .persistMessage(Message.MessageKey.of(user, id), timestamp, text) - .doOnNext(message -> sink.tryEmitNext(message).orThrow()); + .doOnNext(message -> + { + Sinks.EmitResult result = sink.tryEmitNext(message); + if (result.isFailure()) + { + log.warn("Emitting of message failed with {} for {}", result.name(), message); + } + }); } @@ -50,9 +59,11 @@ public class Chatroom return persistence.getMessage(Message.MessageKey.of(username, messageId)); } - public Flux listen() + synchronized public Flux listen() { - return sink.asFlux(); + return sink + .asFlux() + .doOnCancel(() -> sink = createSink()); // Sink hast to be recreated on auto-cancel! } public Flux getMessages() @@ -64,4 +75,12 @@ public class Chatroom { return persistence.getMessages(first, last); } + + private Sinks.Many createSink() + { + return Sinks + .many() + .multicast() + .onBackpressureBuffer(bufferSize); + } } -- 2.20.1