mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
Improved server's reconnection and drafts stability:
* draft: fixed miss or empty draft panels on reconnect; * draft: fixed tourney freezes for richman drafts on disconnects; * draft: fixed tourney freezes on rare use cases with bad connection;
This commit is contained in:
parent
5e27be4dfa
commit
30d44ce869
17 changed files with 201 additions and 133 deletions
|
|
@ -73,6 +73,7 @@ public class Session {
|
|||
|
||||
private final ReentrantLock lock;
|
||||
private final ReentrantLock callBackLock;
|
||||
private String lastCallbackInfo = "";
|
||||
|
||||
public Session(ManagerFactory managerFactory, String sessionId, InvokerCallbackHandler callbackHandler) {
|
||||
this.managerFactory = managerFactory;
|
||||
|
|
@ -429,8 +430,10 @@ public class Session {
|
|||
*/
|
||||
public void fireCallback(final ClientCallback call) {
|
||||
boolean lockSet = false; // TODO: research about locks, why it here? 2023-12-06
|
||||
|
||||
try {
|
||||
if (valid && callBackLock.tryLock(50, TimeUnit.MILLISECONDS)) {
|
||||
lastCallbackInfo = call.getInfo();
|
||||
call.setMessageId(messageId.incrementAndGet());
|
||||
lockSet = true;
|
||||
Callback callback = new Callback(call);
|
||||
|
|
@ -440,11 +443,14 @@ public class Session {
|
|||
}
|
||||
} catch (InterruptedException ex) {
|
||||
// already sending another command (connection problem?)
|
||||
// TODO: un-support multiple games/drafts at the same time?!?!?!?!
|
||||
if (call.getMethod().equals(ClientCallbackMethod.GAME_INIT)
|
||||
|| call.getMethod().equals(ClientCallbackMethod.START_GAME)) {
|
||||
// it's ok use case, user has connection problem so can't send game init (see sendInfoAboutPlayersNotJoinedYetAndTryToFixIt)
|
||||
// it's ok, possible use cases:
|
||||
// - user has connection problem so can't send game init (see sendInfoAboutPlayersNotJoinedYetAndTryToFixIt)
|
||||
} else {
|
||||
logger.warn("SESSION LOCK, possible connection problem - fireCallback - userId: " + userId + " messageId: " + call.getMessageId(), ex);
|
||||
logger.warn("SESSION LOCK, possible connection problem - fireCallback - userId: "
|
||||
+ userId + ", prev call: " + lastCallbackInfo + ", current call: " + call.getInfo(), ex);
|
||||
}
|
||||
} catch (HandleCallbackException ex) {
|
||||
// general error
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import mage.cards.decks.Deck;
|
|||
import mage.constants.ManaType;
|
||||
import mage.constants.TableState;
|
||||
import mage.game.Table;
|
||||
import mage.game.draft.DraftPlayer;
|
||||
import mage.game.result.ResultProtos;
|
||||
import mage.game.tournament.TournamentPlayer;
|
||||
import mage.interfaces.callback.ClientCallback;
|
||||
|
|
@ -441,6 +442,15 @@ public class User {
|
|||
ccDraftStarted(entry.getValue().getDraft().getTableId(), entry.getValue().getDraft().getId(), entry.getKey());
|
||||
entry.getValue().init();
|
||||
entry.getValue().update();
|
||||
|
||||
// on reconnect must resend booster data to new player
|
||||
// TODO: there are possible rare race conditions and user can get draft panel without game info, miss tourney panel, etc
|
||||
// TODO: client side - it must show active panel like current game or draft instead tourney panel
|
||||
DraftPlayer draftPlayer = entry.getValue().getDraftPlayer();
|
||||
if (draftPlayer != null) {
|
||||
draftPlayer.setBoosterNotLoaded();
|
||||
entry.getValue().getDraft().boosterSendingStart();
|
||||
}
|
||||
}
|
||||
|
||||
// active constructing
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package mage.server.draft;
|
||||
|
||||
import mage.game.draft.Draft;
|
||||
import mage.game.draft.DraftPlayer;
|
||||
import mage.interfaces.callback.ClientCallback;
|
||||
import mage.interfaces.callback.ClientCallbackMethod;
|
||||
import mage.server.User;
|
||||
|
|
@ -156,6 +157,10 @@ public class DraftSession {
|
|||
return new DraftPickView(draft.getPlayer(playerId), timeout);
|
||||
}
|
||||
|
||||
public DraftPlayer getDraftPlayer() {
|
||||
return draft.getPlayer(playerId);
|
||||
}
|
||||
|
||||
public Draft getDraft() {
|
||||
return draft;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,20 +38,17 @@ public class ThreadExecutorImpl implements ThreadExecutor {
|
|||
*/
|
||||
|
||||
public ThreadExecutorImpl(ConfigSettings config) {
|
||||
//callExecutor = Executors.newCachedThreadPool();
|
||||
callExecutor = new CachedThreadPoolWithException();
|
||||
((ThreadPoolExecutor) callExecutor).setKeepAliveTime(60, TimeUnit.SECONDS);
|
||||
((ThreadPoolExecutor) callExecutor).allowCoreThreadTimeOut(true);
|
||||
((ThreadPoolExecutor) callExecutor).setThreadFactory(new XmageThreadFactory(ThreadUtils.THREAD_PREFIX_CALL_REQUEST));
|
||||
|
||||
//gameExecutor = Executors.newFixedThreadPool(config.getMaxGameThreads());
|
||||
gameExecutor = new FixedThreadPoolWithException(config.getMaxGameThreads());
|
||||
((ThreadPoolExecutor) gameExecutor).setKeepAliveTime(60, TimeUnit.SECONDS);
|
||||
((ThreadPoolExecutor) gameExecutor).allowCoreThreadTimeOut(true);
|
||||
((ThreadPoolExecutor) gameExecutor).setThreadFactory(new XmageThreadFactory(ThreadUtils.THREAD_PREFIX_GAME));
|
||||
|
||||
//tourney = Executors.newFixedThreadPool(config.getMaxGameThreads() / GAMES_PER_TOURNEY_RATIO);
|
||||
tourneyExecutor = new FixedThreadPoolWithException(config.getMaxGameThreads() / GAMES_PER_TOURNEY_RATIO);
|
||||
tourneyExecutor = new FixedThreadPoolWithException(Math.min(2, config.getMaxGameThreads() / GAMES_PER_TOURNEY_RATIO));
|
||||
((ThreadPoolExecutor) tourneyExecutor).setKeepAliveTime(60, TimeUnit.SECONDS);
|
||||
((ThreadPoolExecutor) tourneyExecutor).allowCoreThreadTimeOut(true);
|
||||
((ThreadPoolExecutor) tourneyExecutor).setThreadFactory(new XmageThreadFactory(ThreadUtils.THREAD_PREFIX_TOURNEY));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue