ChatRealtimeBroadcaster.java
package com.wavii.service;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@Component
@RequiredArgsConstructor
@Slf4j
public class ChatRealtimeBroadcaster {
private final ObjectMapper objectMapper;
private final Map<String, Map<String, WebSocketSession>> rooms = new ConcurrentHashMap<>();
private final Map<String, String> sessionRooms = new ConcurrentHashMap<>();
public void register(String roomId, WebSocketSession session) {
rooms.computeIfAbsent(roomId, key -> new ConcurrentHashMap<>())
.put(session.getId(), session);
sessionRooms.put(session.getId(), roomId);
}
public void unregister(WebSocketSession session) {
String roomId = sessionRooms.remove(session.getId());
if (roomId == null) {
return;
}
Map<String, WebSocketSession> room = rooms.get(roomId);
if (room == null) {
return;
}
room.remove(session.getId());
if (room.isEmpty()) {
rooms.remove(roomId);
}
}
public void broadcast(String roomId, Object payload) {
Map<String, WebSocketSession> room = rooms.get(roomId);
if (room == null || room.isEmpty()) {
return;
}
try {
String json = objectMapper.writeValueAsString(payload);
for (WebSocketSession session : room.values()) {
if (!session.isOpen()) {
continue;
}
session.sendMessage(new TextMessage(json));
}
} catch (Exception e) {
log.warn("Error emitiendo mensaje en {}: {}", roomId, e.getMessage());
}
}
public String directRoom(UUID left, UUID right) {
String a = left.toString();
String b = right.toString();
return "direct:" + (a.compareTo(b) <= 0 ? a + ":" + b : b + ":" + a);
}
public String classRoom(UUID enrollmentId) {
return "class:" + enrollmentId;
}
public String forumRoom(UUID forumId) {
return "forum:" + forumId;
}
}