Feat/ms 4 integration #282

Merged
jona.walpert merged 23 commits from feat/ms-4-integration into main 2026-04-13 03:07:52 +02:00
2 changed files with 59 additions and 16 deletions
Showing only changes of commit d82297ac46 - Show all commits
@@ -9,6 +9,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.WeakHashMap;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
@@ -19,8 +20,14 @@ import org.jspecify.annotations.Nullable;
*/ */
public class ChatController { public class ChatController {
/** Ensures one active message poller per physical ClientService connection. */
private static final Map<ClientService, ChatController> ACTIVE_CONTROLLERS =
new WeakHashMap<>();
private final String username; private final String username;
private final ClientService clientService;
private final ChatClient chatClient; private final ChatClient chatClient;
public ChatBoxController getChatBoxController() { public ChatBoxController getChatBoxController() {
@@ -58,11 +65,15 @@ public class ChatController {
*/ */
public ChatController(String username, ClientService clientService) { public ChatController(String username, ClientService clientService) {
this.username = username; this.username = username;
this.clientService = clientService;
chatClient = new ChatClient(clientService); chatClient = new ChatClient(clientService);
chatModelMap = new LinkedHashMap<>(); chatModelMap = new LinkedHashMap<>();
localUserList = new ArrayList<>(); localUserList = new ArrayList<>();
this.chatBoxController = new ChatBoxController(username, this); this.chatBoxController = new ChatBoxController(username, this);
this.logger = LogManager.getLogger(ChatController.class); this.logger = LogManager.getLogger(ChatController.class);
registerAsActiveController(clientService);
this.timer = new Timer(true); this.timer = new Timer(true);
timer.schedule( timer.schedule(
new TimerTask() { new TimerTask() {
@@ -80,6 +91,17 @@ public class ChatController {
REFRESH_TIME); REFRESH_TIME);
} }
private void registerAsActiveController(ClientService clientService) {
synchronized (ACTIVE_CONTROLLERS) {
ChatController oldController = ACTIVE_CONTROLLERS.get(clientService);
if (oldController != null && oldController != this) {
oldController.shutdown();
logger.info("Replaced previous ChatController poller for shared ClientService");
}
ACTIVE_CONTROLLERS.put(clientService, this);
}
}
/** /**
* Method to be activated, if a lobby has been chosen. It will update the UI and add a new * Method to be activated, if a lobby has been chosen. It will update the UI and add a new
* ChatModel to hold the Data for the Lobby Chat * ChatModel to hold the Data for the Lobby Chat
@@ -158,8 +180,8 @@ public class ChatController {
} }
/** /**
* Method to get the lobbyId of the currently active lobby chat, to check if incoming lobby messages * Method to get the lobbyId of the currently active lobby chat, to check if incoming lobby
* belong to the same lobby. * messages belong to the same lobby.
* *
* @return the lobbyId of the currently active lobby chat. * @return the lobbyId of the currently active lobby chat.
*/ */
@@ -210,6 +232,11 @@ public class ChatController {
/** Stops polling background tasks for this chat controller instance. */ /** Stops polling background tasks for this chat controller instance. */
public void shutdown() { public void shutdown() {
timer.cancel(); timer.cancel();
synchronized (ACTIVE_CONTROLLERS) {
if (ACTIVE_CONTROLLERS.get(clientService) == this) {
ACTIVE_CONTROLLERS.remove(clientService);
}
}
} }
/** /**
@@ -1,7 +1,8 @@
package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.send_message; package ch.unibas.dmi.dbis.cs108.casono.server.app.commands.send_message;
import ch.unibas.dmi.dbis.cs108.casono.client.chat.Message;
import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatType; import ch.unibas.dmi.dbis.cs108.casono.client.chat.ChatType;
import ch.unibas.dmi.dbis.cs108.casono.client.chat.Message;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.Lobby;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.LobbyId; import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.LobbyId;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.LobbyManager; import ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby.LobbyManager;
import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserRegistry; import ch.unibas.dmi.dbis.cs108.casono.server.domain.user.UserRegistry;
@@ -38,7 +39,7 @@ public class SendMessageHandler extends CommandHandler<SendMessageRequest> {
@Override @Override
public void execute(SendMessageRequest request) { public void execute(SendMessageRequest request) {
Message message = request.getMessage(); Message message = request.getMessage();
broadcast(message); broadcast(request, message);
OkResponse response = new OkResponse(request.getContext()); OkResponse response = new OkResponse(request.getContext());
responseDispatcher.dispatch(response); responseDispatcher.dispatch(response);
} }
@@ -49,20 +50,35 @@ public class SendMessageHandler extends CommandHandler<SendMessageRequest> {
* *
* @param message The {@link Message} object to be broadcast. * @param message The {@link Message} object to be broadcast.
*/ */
public void broadcast(Message message) { public void broadcast(SendMessageRequest request, Message message) {
if (message != null if (message != null && message.getMessageType() == ChatType.LOBBY && lobbyManager != null) {
&& message.getMessageType() == ChatType.LOBBY LobbyId targetLobbyId = resolveLobbyIdForMessage(request, message);
&& message.lobbyId >= 0 if (targetLobbyId != null) {
&& lobbyManager != null) {
lobbyManager.broadcast( lobbyManager.broadcast(
LobbyId.of(message.lobbyId), targetLobbyId,
username -> username ->
userRegistry userRegistry
.getByUsername(username) .getByUsername(username)
.ifPresent(user -> user.enqueueMessage(message))); .ifPresent(user -> user.enqueueMessage(message)));
return; return;
} }
}
userRegistry.getAllUsers().forEach(user -> user.enqueueMessage(message)); userRegistry.getAllUsers().forEach(user -> user.enqueueMessage(message));
} }
private LobbyId resolveLobbyIdForMessage(SendMessageRequest request, Message message) {
if (message.lobbyId >= 0) {
LobbyId idFromMessage = LobbyId.of(message.lobbyId);
if (lobbyManager.getLobby(idFromMessage) != null) {
return idFromMessage;
}
}
return userRegistry
.getBySessionId(request.getContext().sessionId())
.map(user -> lobbyManager.getLobbyByUsername(user.getName()))
.map(Lobby::getId)
.orElse(null);
}
} }