websocket de diferentes canales implementado y testeado
Some checks failed
Deploy Spring Boot App / build-and-deploy (push) Has been cancelled
Some checks failed
Deploy Spring Boot App / build-and-deploy (push) Has been cancelled
This commit is contained in:
@@ -1,34 +1,119 @@
|
||||
package com.example.fercoganbackend.component;
|
||||
|
||||
// ContadorWebSocketHandler.java
|
||||
import com.example.fercoganbackend.service.ContadorService;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.socket.*;
|
||||
import org.springframework.web.socket.handler.TextWebSocketHandler;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
@Component
|
||||
public class ContadorWebSocketHandler extends TextWebSocketHandler {
|
||||
private final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();
|
||||
|
||||
private final Map<String, Set<WebSocketSession>> sesionesPorLote = new ConcurrentHashMap<>();
|
||||
private final ContadorService contadorService;
|
||||
|
||||
public ContadorWebSocketHandler(ContadorService contadorService) {
|
||||
this.contadorService = contadorService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConnectionEstablished(WebSocketSession session) {
|
||||
sessions.add(session);
|
||||
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
|
||||
String roomKey = extraerRoomKey(session);
|
||||
|
||||
System.out.println("=== NUEVA CONEXIÓN WEBSOCKET ===");
|
||||
System.out.println("Session ID: " + session.getId());
|
||||
System.out.println("URI: " + session.getUri());
|
||||
System.out.println("Room Key: " + roomKey);
|
||||
System.out.println("Sesiones activas en " + roomKey + ": " +
|
||||
(sesionesPorLote.get(roomKey) != null ? sesionesPorLote.get(roomKey).size() : 0));
|
||||
|
||||
// Agregar sesión a la sala correspondiente
|
||||
sesionesPorLote.computeIfAbsent(roomKey, k -> new CopyOnWriteArraySet<>()).add(session);
|
||||
|
||||
// Enviar valor actual del contador para este lote
|
||||
int valorActual = contadorService.getContador(roomKey);
|
||||
session.sendMessage(new TextMessage(String.valueOf(valorActual)));
|
||||
|
||||
System.out.println("Valor inicial enviado: " + valorActual);
|
||||
System.out.println("=== CONEXIÓN ESTABLECIDA ===");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
|
||||
sessions.remove(session);
|
||||
}
|
||||
|
||||
public void broadcast(String message) {
|
||||
for (WebSocketSession session : sessions) {
|
||||
try {
|
||||
session.sendMessage(new TextMessage(message));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
String roomKey = extraerRoomKey(session);
|
||||
Set<WebSocketSession> sesiones = sesionesPorLote.get(roomKey);
|
||||
if (sesiones != null) {
|
||||
sesiones.remove(session);
|
||||
if (sesiones.isEmpty()) {
|
||||
sesionesPorLote.remove(roomKey);
|
||||
}
|
||||
}
|
||||
System.out.println("Conexión cerrada para: " + roomKey + " - " + status);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
|
||||
String roomKey = extraerRoomKey(session);
|
||||
String payload = message.getPayload();
|
||||
|
||||
System.out.println("Mensaje recibido de " + roomKey + ": " + payload);
|
||||
|
||||
if ("incrementar".equals(payload)) {
|
||||
int nuevoValor = contadorService.incrementar(roomKey);
|
||||
System.out.println("Incrementando " + roomKey + " a: " + nuevoValor);
|
||||
broadcastToRoom(roomKey, String.valueOf(nuevoValor));
|
||||
}
|
||||
}
|
||||
|
||||
// Broadcast a una sala específica
|
||||
public void broadcastToRoom(String remate, String lote, String message) {
|
||||
String roomKey = generarRoomKey(remate, lote);
|
||||
System.out.println("Broadcast a room: " + roomKey + " - Mensaje: " + message);
|
||||
broadcastToRoom(roomKey, message);
|
||||
}
|
||||
|
||||
private void broadcastToRoom(String roomKey, String message) {
|
||||
Set<WebSocketSession> sesiones = sesionesPorLote.get(roomKey);
|
||||
System.out.println("Buscando sesiones para: " + roomKey);
|
||||
System.out.println("Sesiones encontradas: " + (sesiones != null ? sesiones.size() : 0));
|
||||
|
||||
if (sesiones != null) {
|
||||
for (WebSocketSession session : sesiones) {
|
||||
try {
|
||||
if (session.isOpen()) {
|
||||
System.out.println("Enviando a session: " + session.getId());
|
||||
session.sendMessage(new TextMessage(message));
|
||||
} else {
|
||||
System.out.println("Session cerrada: " + session.getId());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error enviando mensaje a " + session.getId() + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
System.out.println("No hay sesiones activas para: " + roomKey);
|
||||
}
|
||||
}
|
||||
|
||||
private String extraerRoomKey(WebSocketSession session) {
|
||||
String path = session.getUri().getPath();
|
||||
String[] segments = path.split("/");
|
||||
|
||||
// Para /ws/remate1/lote1 los segmentos son: ["", "ws", "remate1", "lote1"]
|
||||
if (segments.length >= 4) {
|
||||
String remate = segments[2]; // índice 2 = remate1
|
||||
String lote = segments[3]; // índice 3 = lote1
|
||||
return generarRoomKey(remate, lote);
|
||||
}
|
||||
|
||||
return "default-default";
|
||||
}
|
||||
|
||||
private String generarRoomKey(String remate, String lote) {
|
||||
return remate + "-" + lote;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,24 @@
|
||||
package com.example.fercoganbackend.configuration;
|
||||
|
||||
// WebSocketConfig.java
|
||||
import com.example.fercoganbackend.component.ContadorWebSocketHandler;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.socket.config.annotation.*;
|
||||
import org.springframework.web.socket.config.annotation.EnableWebSocket;
|
||||
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
|
||||
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSocket
|
||||
public class WebSocketConfig implements WebSocketConfigurer {
|
||||
private final ContadorWebSocketHandler handler;
|
||||
|
||||
public WebSocketConfig(ContadorWebSocketHandler handler) {
|
||||
this.handler = handler;
|
||||
private final ContadorWebSocketHandler webSocketHandler;
|
||||
|
||||
public WebSocketConfig(ContadorWebSocketHandler webSocketHandler) {
|
||||
this.webSocketHandler = webSocketHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
|
||||
registry.addHandler(handler, "/ws/contador").setAllowedOrigins("*");
|
||||
registry.addHandler(webSocketHandler, "/ws/{remate}/{lote}")
|
||||
.setAllowedOrigins("*");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.example.fercoganbackend.controller;
|
||||
|
||||
// ContadorController.java (REST API)
|
||||
import com.example.fercoganbackend.component.ContadorWebSocketHandler;
|
||||
import com.example.fercoganbackend.service.ContadorService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -11,20 +10,38 @@ public class ContadorController {
|
||||
private final ContadorService contadorService;
|
||||
private final ContadorWebSocketHandler webSocketHandler;
|
||||
|
||||
public ContadorController(ContadorService contadorService, ContadorWebSocketHandler webSocketHandler) {
|
||||
public ContadorController(ContadorService contadorService,
|
||||
ContadorWebSocketHandler webSocketHandler) {
|
||||
this.contadorService = contadorService;
|
||||
this.webSocketHandler = webSocketHandler;
|
||||
}
|
||||
|
||||
@PostMapping("/incrementar")
|
||||
public int incrementar() {
|
||||
int nuevoValor = contadorService.incrementar();
|
||||
webSocketHandler.broadcast(String.valueOf(nuevoValor));
|
||||
@PostMapping("/incrementar/{remate}/{lote}")
|
||||
public int incrementar(@PathVariable String remate, @PathVariable String lote) {
|
||||
String roomKey = remate + "-" + lote;
|
||||
int nuevoValor = contadorService.incrementar(roomKey);
|
||||
|
||||
System.out.println("=== INCREMENTAR VIA REST ===");
|
||||
System.out.println("Remate: " + remate + ", Lote: " + lote);
|
||||
System.out.println("Room Key: " + roomKey);
|
||||
System.out.println("Nuevo valor: " + nuevoValor);
|
||||
|
||||
webSocketHandler.broadcastToRoom(remate, lote, String.valueOf(nuevoValor));
|
||||
return nuevoValor;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public int getContador() {
|
||||
return contadorService.getContador();
|
||||
@GetMapping("/{remate}/{lote}")
|
||||
public int getContador(@PathVariable String remate, @PathVariable String lote) {
|
||||
return contadorService.getContador(remate + "-" + lote);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/reset/{remate}/{lote}")
|
||||
public int resetContador(@PathVariable String remate, @PathVariable String lote,
|
||||
@RequestParam(defaultValue = "200") int valorInicial) {
|
||||
String roomKey = remate + "-" + lote;
|
||||
contadorService.setContador(roomKey, valorInicial);
|
||||
int valor = contadorService.getContador(roomKey);
|
||||
webSocketHandler.broadcastToRoom(remate, lote, String.valueOf(valor));
|
||||
return valor;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,49 @@
|
||||
package com.example.fercoganbackend.service;
|
||||
|
||||
// ContadorService.java
|
||||
import org.springframework.stereotype.Service;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Service
|
||||
public class ContadorService {
|
||||
private final AtomicInteger contador = new AtomicInteger(200);
|
||||
private boolean sw = true;
|
||||
private final Map<String, AtomicInteger> contadoresPorLote = new ConcurrentHashMap<>();
|
||||
private final Map<String, Boolean> switchesPorLote = new ConcurrentHashMap<>();
|
||||
|
||||
public int incrementar(String roomKey) {
|
||||
AtomicInteger contador = contadoresPorLote.computeIfAbsent(roomKey,
|
||||
k -> new AtomicInteger(200));
|
||||
boolean sw = switchesPorLote.computeIfAbsent(roomKey, k -> true);
|
||||
|
||||
public int incrementar() {
|
||||
int valorActual = contador.get();
|
||||
int incremento;
|
||||
if (valorActual < 300) {
|
||||
incremento = sw ? 20 : 30;
|
||||
sw = !sw; // alterna el booleano
|
||||
} else if (valorActual < 1000) {
|
||||
incremento = 50;
|
||||
} else if (valorActual < 2000) {
|
||||
incremento = 100;
|
||||
} else {
|
||||
incremento = 500;
|
||||
}
|
||||
int incremento = calcularIncremento(valorActual, sw);
|
||||
|
||||
// Alternar el switch para este lote
|
||||
switchesPorLote.put(roomKey, !sw);
|
||||
|
||||
return contador.addAndGet(incremento);
|
||||
}
|
||||
|
||||
|
||||
public int getContador() {
|
||||
return contador.get();
|
||||
public int getContador(String roomKey) {
|
||||
AtomicInteger contador = contadoresPorLote.get(roomKey);
|
||||
return contador != null ? contador.get() : 200; // Valor por defecto
|
||||
}
|
||||
}
|
||||
|
||||
public void setContador(String roomKey, int valor) {
|
||||
AtomicInteger contador = contadoresPorLote.computeIfAbsent(roomKey,
|
||||
k -> new AtomicInteger(valor));
|
||||
contador.set(valor);
|
||||
}
|
||||
|
||||
private int calcularIncremento(int valorActual, boolean sw) {
|
||||
if (valorActual < 300) {
|
||||
return sw ? 20 : 30;
|
||||
} else if (valorActual < 1000) {
|
||||
return 50;
|
||||
} else if (valorActual < 2000) {
|
||||
return 100;
|
||||
} else {
|
||||
return 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user