Improved stability and other related fixes:

* server: added limit to max chat message (related to #11285);
* gui: fixed possible error after auto-submit deck;
* gui: fixed possible error after end game dialog;
* refactor: other code improves;
This commit is contained in:
Oleg Agafonov 2023-11-25 12:29:54 +04:00
parent 81f97c3b0e
commit d1f9e9cc90
15 changed files with 86 additions and 48 deletions

View file

@ -7,6 +7,7 @@ import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
import mage.cards.repository.ExpansionInfo;
import mage.cards.repository.ExpansionRepository;
import mage.constants.Constants;
import mage.constants.ManaType;
import mage.constants.PlayerAction;
import mage.constants.TableState;
@ -488,7 +489,13 @@ public class MageServerImpl implements MageServer {
@Override
//FIXME: why no sessionId here???
public void chatSendMessage(final UUID chatId, final String userName, final String message) throws MageException {
if (message.length() > Constants.MAX_CHAT_MESSAGE_SIZE) {
logger.error("Chat message too big: " + message.length() + ", from user " + userName);
return;
}
try {
// TODO: check and replace all usage of callExecutor.execute() by execute("actionName")
callExecutor.execute(
() -> managerFactory.chatManager().broadcast(chatId, userName, HtmlEscape.escapeHtml4(message), MessageColor.BLUE, true, null, ChatMessage.MessageType.TALK, null)
);
@ -953,8 +960,14 @@ public class MageServerImpl implements MageServer {
}
@Override
//TODO: check how often it is used
public ServerState getServerState() throws MageException {
// called one time per login, must work without auth and with diff versions
try {
// some ddos protection
Thread.sleep(1000);
} catch (InterruptedException ignore) {
}
try {
return new ServerState(
GameFactory.instance.getGameTypes(),

View file

@ -36,7 +36,6 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
public class TableManagerImpl implements TableManager {
protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor();
// protected static ScheduledExecutorService expireExecutor = ThreadExecutorImpl.getInstance().getExpireExecutor();
private final ManagerFactory managerFactory;
private final Logger logger = Logger.getLogger(TableManagerImpl.class);
private final DateFormat formatter = new SimpleDateFormat("HH:mm:ss");

View file

@ -26,12 +26,15 @@ public class UserManagerImpl implements UserManager {
private static final int SERVER_TIMEOUTS_USER_DISCONNECT_FROM_SERVER_AFTER_SECS = 3 * 60; // removes from all games and chats too (can be seen in users list with disconnected status)
private static final int SERVER_TIMEOUTS_USER_REMOVE_FROM_SERVER_AFTER_SECS = 8 * 60; // removes from users list
private static final int SERVER_TIMEOUTS_USER_EXPIRE_CHECK_SECS = 60;
private static final int SERVER_TIMEOUTS_USERS_LIST_UPDATE_SECS = 4; // server side updates (client use own timeouts to request users list)
private static final Logger logger = Logger.getLogger(UserManagerImpl.class);
protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor();
protected final ScheduledExecutorService userListExecutor = Executors.newSingleThreadScheduledExecutor();
private List<UserView> userInfoList = new ArrayList<>();
private List<UserView> userInfoList = new ArrayList<>(); // all users list for main room/chat
private final ManagerFactory managerFactory;
@ -46,9 +49,8 @@ public class UserManagerImpl implements UserManager {
public void init() {
USER_EXECUTOR = managerFactory.threadExecutor().getCallExecutor();
expireExecutor.scheduleAtFixedRate(this::checkExpired, 60, 60, TimeUnit.SECONDS);
userListExecutor.scheduleAtFixedRate(this::updateUserInfoList, 4, 4, TimeUnit.SECONDS);
expireExecutor.scheduleAtFixedRate(this::checkExpired, SERVER_TIMEOUTS_USER_EXPIRE_CHECK_SECS, SERVER_TIMEOUTS_USER_EXPIRE_CHECK_SECS, TimeUnit.SECONDS);
userListExecutor.scheduleAtFixedRate(this::updateUserInfoList, SERVER_TIMEOUTS_USERS_LIST_UPDATE_SECS, SERVER_TIMEOUTS_USERS_LIST_UPDATE_SECS, TimeUnit.SECONDS);
}
@Override
@ -254,7 +256,7 @@ public class UserManagerImpl implements UserManager {
}
/**
* This method recreated the user list that will be send to all clients
* This method recreated the user list that will be sent to all clients
*/
private void updateUserInfoList() {
try {

View file

@ -335,7 +335,7 @@ public class GameController implements GameCallback {
gameFuture = gameExecutor.submit(worker);
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
} catch (InterruptedException ignore) {
}
if (game.getState().getChoosingPlayerId() != null) {
// start timer to force player to choose starting player otherwise loosing by being idle

View file

@ -37,7 +37,7 @@ public class GameSessionPlayer extends GameSessionWatcher {
public GameSessionPlayer(ManagerFactory managerFactory, Game game, UUID userId, UUID playerId) {
super(managerFactory.userManager(), userId, game, true);
this.userManager = managerFactory.userManager();
callExecutor = managerFactory.threadExecutor().getCallExecutor();
this.callExecutor = managerFactory.threadExecutor().getCallExecutor();
this.playerId = playerId;
}

View file

@ -45,11 +45,11 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
UPDATE_EXECUTOR.scheduleAtFixedRate(() -> {
try {
update();
} catch (Exception ex) {
LOGGER.fatal("Games room update exception! " + ex.toString(), ex);
} catch (Exception e) {
LOGGER.fatal("Games room update error: " + e.getMessage(), e);
}
}, 2, 2, TimeUnit.SECONDS);
}, 2, 2, TimeUnit.SECONDS); // TODO: is it ok for performance?
}
@Override