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