26 12 25
Исправил баг что пир повторном подключении по одной сессии всё будет норм работать
This commit is contained in:
parent
eeb8ee9069
commit
809d897da6
@ -1,26 +1,19 @@
|
||||
package server.logic.ws_protocol.JSON;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
* Реестр активных подключений (только авторизованные).
|
||||
*
|
||||
* Позволяет:
|
||||
* - получить ConnectionContext по sessionId;
|
||||
* - получить все активные подключения пользователя по login;
|
||||
* - удалить подключение при закрытии WebSocket.
|
||||
*
|
||||
* найти все подключения пользователя:
|
||||
* var set = ActiveConnectionsRegistry.getInstance().getByLoginId(loginId);
|
||||
*
|
||||
* найти конкретное подключение по sessionId:
|
||||
* ConnectionContext ctx = ActiveConnectionsRegistry.getInstance().getBySessionId(sessionId);
|
||||
* Session ws = ctx != null ? ctx.getWsSession() : null;
|
||||
*/
|
||||
public final class ActiveConnectionsRegistry {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ActiveConnectionsRegistry.class);
|
||||
|
||||
private static final ActiveConnectionsRegistry INSTANCE = new ActiveConnectionsRegistry();
|
||||
|
||||
public static ActiveConnectionsRegistry getInstance() {
|
||||
@ -47,15 +40,33 @@ public final class ActiveConnectionsRegistry {
|
||||
String sessionId = ctx.getSessionId();
|
||||
String login = ctx.getLogin();
|
||||
|
||||
if (sessionId == null || login == null || login.isBlank()) {
|
||||
if (sessionId == null || sessionId.isBlank() || login == null || login.isBlank()) {
|
||||
log.debug("register skipped: bad ctx fields (login='{}', sessionId='{}')", login, sessionId);
|
||||
return;
|
||||
}
|
||||
|
||||
bySessionId.put(sessionId, ctx);
|
||||
// ✅ Если кто-то перерегистрировал тот же sessionId — вычищаем старый ctx из byLogin
|
||||
ConnectionContext prev = bySessionId.put(sessionId, ctx);
|
||||
if (prev != null && prev != ctx) {
|
||||
String prevLogin = prev.getLogin();
|
||||
if (prevLogin != null && !prevLogin.isBlank()) {
|
||||
Set<ConnectionContext> prevSet = byLogin.get(prevLogin);
|
||||
if (prevSet != null) {
|
||||
prevSet.remove(prev);
|
||||
if (prevSet.isEmpty()) {
|
||||
byLogin.remove(prevLogin);
|
||||
}
|
||||
}
|
||||
}
|
||||
log.warn("sessionId reused: replaced previous ctx (sessionId={}, prevLogin={}, newLogin={})",
|
||||
sessionId, prevLogin, login);
|
||||
}
|
||||
|
||||
byLogin
|
||||
.computeIfAbsent(login, id -> new CopyOnWriteArraySet<>())
|
||||
.add(ctx);
|
||||
|
||||
log.debug("registered ctx (login={}, sessionId={})", login, sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,11 +78,17 @@ public final class ActiveConnectionsRegistry {
|
||||
String sessionId = ctx.getSessionId();
|
||||
String login = ctx.getLogin();
|
||||
|
||||
if (sessionId != null) {
|
||||
bySessionId.remove(sessionId);
|
||||
if (sessionId != null && !sessionId.isBlank()) {
|
||||
ConnectionContext removed = bySessionId.remove(sessionId);
|
||||
|
||||
// Если в мапе лежал другой ctx под тем же sessionId — не трогаем его byLogin
|
||||
if (removed != null && removed != ctx) {
|
||||
log.debug("remove(ctx): sessionId mapped to another ctx, skip byLogin cleanup (sessionId={})", sessionId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (login != null) {
|
||||
if (login != null && !login.isBlank()) {
|
||||
Set<ConnectionContext> set = byLogin.get(login);
|
||||
if (set != null) {
|
||||
set.remove(ctx);
|
||||
@ -80,18 +97,21 @@ public final class ActiveConnectionsRegistry {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("removed ctx (login={}, sessionId={})", login, sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Удалить подключение по sessionId.
|
||||
*/
|
||||
public void removeBySessionId(String sessionId) {
|
||||
if (sessionId == null) return;
|
||||
if (sessionId == null || sessionId.isBlank()) return;
|
||||
|
||||
ConnectionContext ctx = bySessionId.remove(sessionId);
|
||||
if (ctx != null) {
|
||||
if (ctx == null) return;
|
||||
|
||||
String login = ctx.getLogin();
|
||||
if (login != null) {
|
||||
if (login != null && !login.isBlank()) {
|
||||
Set<ConnectionContext> set = byLogin.get(login);
|
||||
if (set != null) {
|
||||
set.remove(ctx);
|
||||
@ -100,14 +120,15 @@ public final class ActiveConnectionsRegistry {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("removed by sessionId (login={}, sessionId={})", login, sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить контекст по sessionId.
|
||||
*/
|
||||
public ConnectionContext getBySessionId(String sessionId) {
|
||||
if (sessionId == null) return null;
|
||||
if (sessionId == null || sessionId.isBlank()) return null;
|
||||
return bySessionId.get(sessionId);
|
||||
}
|
||||
|
||||
@ -115,12 +136,8 @@ public final class ActiveConnectionsRegistry {
|
||||
* Получить все активные подключения пользователя по login.
|
||||
*/
|
||||
public Set<ConnectionContext> getByLogin(String login) {
|
||||
if (login == null) return Set.of();
|
||||
if (login == null || login.isBlank()) return Set.of();
|
||||
Set<ConnectionContext> set = byLogin.get(login);
|
||||
if (set == null) {
|
||||
return Set.of();
|
||||
}
|
||||
// CopyOnWriteArraySet безопасно отдавать как есть
|
||||
return set;
|
||||
return (set == null) ? Set.of() : set; // CopyOnWriteArraySet можно отдавать как есть
|
||||
}
|
||||
}
|
||||
@ -19,8 +19,16 @@ public final class NetExceptionResponseFactory {
|
||||
String message) {
|
||||
|
||||
Net_Exception_Response resp = new Net_Exception_Response();
|
||||
|
||||
// ✅ НЕ падаем, даже если req == null
|
||||
if (req != null) {
|
||||
resp.setOp(req.getOp());
|
||||
resp.setRequestId(req.getRequestId());
|
||||
} else {
|
||||
resp.setOp(null);
|
||||
resp.setRequestId(null);
|
||||
}
|
||||
|
||||
resp.setStatus(status);
|
||||
resp.setCode(code);
|
||||
resp.setMessage(message);
|
||||
|
||||
@ -1,3 +1 @@
|
||||
Работу с линиями
|
||||
|
||||
Восстановление при подвисании сервера
|
||||
Loading…
Reference in New Issue
Block a user