server: fixed server app freeze on another instance already running, improved threads usage (related to #11285);

This commit is contained in:
Oleg Agafonov 2024-06-23 15:58:25 +04:00
parent f0c38cdb87
commit 7d675de876
21 changed files with 203 additions and 106 deletions

View file

@ -25,6 +25,8 @@ import mage.server.Main;
import mage.server.User;
import mage.server.managers.ManagerFactory;
import mage.util.MultiAmountMessage;
import mage.util.ThreadUtils;
import mage.util.XMageThreadFactory;
import mage.utils.StreamUtils;
import mage.utils.timer.PriorityTimer;
import mage.view.*;
@ -53,7 +55,7 @@ public class GameController implements GameCallback {
private final ExecutorService gameExecutor;
private static final Logger logger = Logger.getLogger(GameController.class);
protected final ScheduledExecutorService joinWaitingExecutor = Executors.newSingleThreadScheduledExecutor();
private ScheduledExecutorService JOIN_WAITING_EXECUTOR = null;
private ScheduledFuture<?> futureTimeout;
private final ManagerFactory managerFactory;
@ -238,13 +240,21 @@ public class GameController implements GameCallback {
}
}
);
joinWaitingExecutor.scheduleAtFixedRate(() -> {
// wait all players
if (JOIN_WAITING_EXECUTOR == null) {
JOIN_WAITING_EXECUTOR = Executors.newSingleThreadScheduledExecutor(
new XMageThreadFactory(ThreadUtils.THREAD_PREFIX_GAME_JOIN_WAITING + " " + game.getId())
);
}
JOIN_WAITING_EXECUTOR.scheduleAtFixedRate(() -> {
try {
sendInfoAboutPlayersNotJoinedYetAndTryToFixIt();
} catch (Exception ex) {
logger.fatal("Send info about player not joined yet:", ex);
}
}, GAME_TIMEOUTS_CHECK_JOINING_STATUS_EVERY_SECS, GAME_TIMEOUTS_CHECK_JOINING_STATUS_EVERY_SECS, TimeUnit.SECONDS);
checkJoinAndStart();
}
@ -347,7 +357,9 @@ public class GameController implements GameCallback {
}
private void sendInfoAboutPlayersNotJoinedYetAndTryToFixIt() {
// runs every 10 secs untill all players join
// TODO: need code and feature review - is it useful? 2024-06-23
// runs every 10 secs until all players join
// runs BEFORE game start, so it's safe to call player.leave here
for (Player player : game.getPlayers().values()) {
if (player.canRespond() && player.isHuman()) {
Optional<User> requestedUser = getUserByPlayerId(player.getId());
@ -412,7 +424,7 @@ public class GameController implements GameCallback {
private void checkJoinAndStart() {
if (isAllJoined()) {
joinWaitingExecutor.shutdownNow();
JOIN_WAITING_EXECUTOR.shutdownNow();
managerFactory.threadExecutor().getCallExecutor().execute(this::startGame);
}
}