Added inactive watchdog hint in frontend.

This commit is contained in:
genxium
2022-12-20 16:01:44 +08:00
parent 9eb6ad26ef
commit 727e66787f
8 changed files with 130 additions and 136 deletions

View File

@@ -1,28 +1,28 @@
{
"RET_CODE": {
"__comment__":"基础",
"OK": 9000,
"UNKNOWN_ERROR": 9001,
"INVALID_REQUEST_PARAM": 9002,
"IS_TEST_ACC": 9003,
"MYSQL_ERROR": 9004,
"NONEXISTENT_ACT": 9005,
"LACK_OF_DIAMOND": 9006,
"LACK_OF_GOLD": 9007,
"LACK_OF_ENERGY": 9008,
"NONEXISTENT_ACT_HANDLER": 9009,
"LOCALLY_NO_AVAILABLE_ROOM": 9010,
"LOCALLY_NO_SPECIFIED_ROOM": 9011,
"PLAYER_NOT_ADDABLE_TO_ROOM": 9012,
"PLAYER_NOT_READDABLE_TO_ROOM": 9013,
"PLAYER_NOT_FOUND": 9014,
"PLAYER_CHEATING": 9015,
"WECHAT_SERVER_ERROR": 9016,
"IS_BOT_ACC": 9017,
"__comment__": "Websocket",
"OK": 3000,
"UNKNOWN_ERROR": 3001,
"INVALID_REQUEST_PARAM": 3002,
"IS_TEST_ACC": 3003,
"MYSQL_ERROR": 3004,
"NONEXISTENT_ACT": 3005,
"LACK_OF_DIAMOND": 3006,
"LACK_OF_GOLD": 3007,
"LACK_OF_ENERGY": 3008,
"NONEXISTENT_ACT_HANDLER": 3009,
"LOCALLY_NO_AVAILABLE_ROOM": 3010,
"LOCALLY_NO_SPECIFIED_ROOM": 3011,
"PLAYER_NOT_ADDABLE_TO_ROOM": 3012,
"PLAYER_NOT_READDABLE_TO_ROOM": 3013,
"PLAYER_NOT_FOUND": 3014,
"PLAYER_CHEATING": 3015,
"WECHAT_SERVER_ERROR": 3016,
"IS_BOT_ACC": 3017,
"ACTIVE_WATCHDOG": 3018,
"BATTLE_STOPPED": 3019,
"__comment__":"SMS",
"SMS_CAPTCHA_REQUESTED_TOO_FREQUENTLY": 5001,
"SMS_CAPTCHA_NOT_MATCH": 5002,
"__comment__": "OTHERS",
"INVALID_TOKEN": 2001,
"DUPLICATED": 2002,
@@ -39,12 +39,15 @@
"FAILED_TO_DELETE": 2015,
"FAILED_TO_CREATE": 2016,
"INCORRECT_PHONE_NUMBER": 2018,
"INSUFFICIENT_MEM_TO_ALLOCATE_CONNECTION": 3001,
"PASSWORD_RESET_CODE_GENERATION_PER_EMAIL_TOO_FREQUENTLY": 4000,
"TRADE_CREATION_TOO_FREQUENTLY": 4002,
"MAP_NOT_UNLOCKED": 4003,
"INSUFFICIENT_MEM_TO_ALLOCATE_CONNECTION": 2019,
"PASSWORD_RESET_CODE_GENERATION_PER_EMAIL_TOO_FREQUENTLY": 2020,
"TRADE_CREATION_TOO_FREQUENTLY": 2021,
"MAP_NOT_UNLOCKED": 2022,
"GET_SMS_CAPTCHA_RESP_ERROR_CODE": 2023,
"SMS_CAPTCHA_REQUESTED_TOO_FREQUENTLY": 2024,
"SMS_CAPTCHA_NOT_MATCH": 2025,
"GET_SMS_CAPTCHA_RESP_ERROR_CODE": 5003,
"NOT_IMPLEMENTED_YET": 65535
},
"AUTH_CHANNEL": {
@@ -62,6 +65,6 @@
},
"WS": {
"INTERVAL_TO_PING": 2000,
"WILL_KICK_IF_INACTIVE_FOR": 6000
"WILL_KICK_IF_INACTIVE_FOR": 4000
}
}

View File

@@ -15,10 +15,13 @@ type constants struct {
SmsValidResendPeriodSeconds int `json:"SMS_VALID_RESEND_PERIOD_SECONDS"`
} `json:"PLAYER"`
RetCode struct {
ActiveWatchdog int `json:"ACTIVE_WATCHDOG"`
BattleStopped int `json:"BATTLE_STOPPED"`
Duplicated int `json:"DUPLICATED"`
FailedToCreate int `json:"FAILED_TO_CREATE"`
FailedToDelete int `json:"FAILED_TO_DELETE"`
FailedToUpdate int `json:"FAILED_TO_UPDATE"`
GetSmsCaptchaRespErrorCode int `json:"GET_SMS_CAPTCHA_RESP_ERROR_CODE"`
IncorrectCaptcha int `json:"INCORRECT_CAPTCHA"`
IncorrectHandle int `json:"INCORRECT_HANDLE"`
IncorrectPassword int `json:"INCORRECT_PASSWORD"`
@@ -28,27 +31,26 @@ type constants struct {
InvalidEmailLiteral int `json:"INVALID_EMAIL_LITERAL"`
InvalidRequestParam int `json:"INVALID_REQUEST_PARAM"`
InvalidToken int `json:"INVALID_TOKEN"`
IsTestAcc int `json:"IS_TEST_ACC"`
IsBotAcc int `json:"IS_BOT_ACC"`
IsTestAcc int `json:"IS_TEST_ACC"`
LackOfDiamond int `json:"LACK_OF_DIAMOND"`
LackOfEnergy int `json:"LACK_OF_ENERGY"`
LackOfGold int `json:"LACK_OF_GOLD"`
LocallyNoAvailableRoom int `json:"LOCALLY_NO_AVAILABLE_ROOM"`
LocallyNoSpecifiedRoom int `json:"LOCALLY_NO_SPECIFIED_ROOM"`
MapNotUnlocked int `json:"MAP_NOT_UNLOCKED"`
MysqlError int `json:"MYSQL_ERROR"`
GetSmsCaptchaRespErrorCode int `json:"GET_SMS_CAPTCHA_RESP_ERROR_CODE"`
NewHandleConflict int `json:"NEW_HANDLE_CONFLICT"`
NonexistentAct int `json:"NONEXISTENT_ACT"`
NonexistentActHandler int `json:"NONEXISTENT_ACT_HANDLER"`
LocallyNoAvailableRoom int `json:"LOCALLY_NO_AVAILABLE_ROOM"`
LocallyNoSpecifiedRoom int `json:"LOCALLY_NO_SPECIFIED_ROOM"`
PlayerNotAddableToRoom int `json:"PLAYER_NOT_ADDABLE_TO_ROOM"`
PlayerNotReAddableToRoom int `json:"PLAYER_NOT_READDABLE_TO_ROOM"`
PlayerNotFound int `json:"PLAYER_NOT_FOUND"`
PlayerCheating int `json:"PLAYER_CHEATING"`
NotImplementedYet int `json:"NOT_IMPLEMENTED_YET"`
NoAssociatedEmail int `json:"NO_ASSOCIATED_EMAIL"`
Ok int `json:"OK"`
PasswordResetCodeGenerationPerEmailTooFrequently int `json:"PASSWORD_RESET_CODE_GENERATION_PER_EMAIL_TOO_FREQUENTLY"`
PlayerCheating int `json:"PLAYER_CHEATING"`
PlayerNotAddableToRoom int `json:"PLAYER_NOT_ADDABLE_TO_ROOM"`
PlayerNotFound int `json:"PLAYER_NOT_FOUND"`
PlayerNotReaddableToRoom int `json:"PLAYER_NOT_READDABLE_TO_ROOM"`
SendEmailTimeout int `json:"SEND_EMAIL_TIMEOUT"`
SmsCaptchaNotMatch int `json:"SMS_CAPTCHA_NOT_MATCH"`
SmsCaptchaRequestedTooFrequently int `json:"SMS_CAPTCHA_REQUESTED_TOO_FREQUENTLY"`

View File

@@ -170,9 +170,10 @@ type Room struct {
LastAllConfirmedInputList []uint64
JoinIndexBooleanArr []bool
BackendDynamicsEnabled bool
LastRenderFrameIdTriggeredAt int64
PlayerDefaultSpeed int32
BackendDynamicsEnabled bool
ForceAllResyncOnAnyActiveSlowTicker bool
LastRenderFrameIdTriggeredAt int64
PlayerDefaultSpeed int32
BulletBattleLocalIdCounter int32
dilutedRollbackEstimatedDtNanos int64
@@ -210,7 +211,7 @@ func (pR *Room) AddPlayerIfPossible(pPlayerFromDbInit *Player, session *websocke
pR.PlayerSignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer
newWatchdog := NewWatchdog(ConstVals.Ws.WillKickIfInactiveFor, func() {
Logger.Warn("Conn inactive watchdog triggered#1:", zap.Any("playerId", playerId), zap.Any("roomId", pR.Id), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount))
signalToCloseConnOfThisPlayer(Constants.RetCode.UnknownError, "")
signalToCloseConnOfThisPlayer(Constants.RetCode.ActiveWatchdog, "")
})
newWatchdog.Stop()
pR.PlayerActiveWatchdogDict[playerId] = newWatchdog
@@ -247,7 +248,7 @@ func (pR *Room) ReAddPlayerIfPossible(pTmpPlayerInstance *Player, session *webso
pR.PlayerSignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer
pR.PlayerActiveWatchdogDict[playerId] = NewWatchdog(ConstVals.Ws.WillKickIfInactiveFor, func() {
Logger.Warn("Conn inactive watchdog triggered#2:", zap.Any("playerId", playerId), zap.Any("roomId", pR.Id), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount))
signalToCloseConnOfThisPlayer(Constants.RetCode.UnknownError, "")
signalToCloseConnOfThisPlayer(Constants.RetCode.ActiveWatchdog, "")
}) // For ReAdded player the new watchdog starts immediately
Logger.Warn("ReAddPlayerIfPossible finished.", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("joinIndex", pEffectiveInRoomPlayerInstance.JoinIndex), zap.Any("playerBattleState", pEffectiveInRoomPlayerInstance.BattleState), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount), zap.Any("AckingFrameId", pEffectiveInRoomPlayerInstance.AckingFrameId), zap.Any("AckingInputFrameId", pEffectiveInRoomPlayerInstance.AckingInputFrameId), zap.Any("LastSentInputFrameId", pEffectiveInRoomPlayerInstance.LastSentInputFrameId))
@@ -776,7 +777,8 @@ func (pR *Room) OnDismissed() {
pR.InputFrameUpsyncDelayTolerance = (pR.NstDelayFrames >> pR.InputScaleFrames) - 1 // this value should be strictly smaller than (NstDelayFrames >> InputScaleFrames), otherwise "type#1 forceConfirmation" might become a lag avalanche
pR.MaxChasingRenderFramesPerUpdate = 12 // Don't set this value too high to avoid exhausting frontend CPU within a single frame
pR.BackendDynamicsEnabled = true // [WARNING] When "false", recovery upon reconnection wouldn't work!
pR.BackendDynamicsEnabled = true // [WARNING] When "false", recovery upon reconnection wouldn't work!
pR.ForceAllResyncOnAnyActiveSlowTicker = false // See tradeoff discussion in "downsyncToAllPlayers"
punchSkillId := int32(1)
pR.MeleeSkillConfig = make(map[int32]*MeleeBullet, 0)
pR.MeleeSkillConfig[punchSkillId] = &MeleeBullet{
@@ -1769,7 +1771,7 @@ func (pR *Room) downsyncToAllPlayers(inputsBufferSnapshot *InputsBufferSnapshot)
break
}
/*
[WARNING] There's a tradeoff here, if the `ACTIVE SLOW TICKER` doesn't resume for a long period of time, the current approach is to kick it out by "connWatchdog" instead of forcing resync of all players in the same battle all the way along.
[WARNING] There's a tradeoff for setting/unsetting "ForceAllResyncOnAnyActiveSlowTicker" here, if the `ACTIVE SLOW TICKER` doesn't resume for a long period of time, the current approach is to kick it out by "connWatchdog" instead of forcing resync of all players in the same battle all the way along.
[FIXME]
In practice, I tested in internet environment by toggling player#1 "CPU throttling: 1x -> 4x -> 1x -> 6x -> 1x" and checked the logs of all players which showed that "all received inputFrameIds are consecutive for all players", yet not forcing resync of all players here still result in occasional inconsistent graphics for the `ACTIVE NORMAL TICKER`s.
@@ -1778,7 +1780,7 @@ func (pR *Room) downsyncToAllPlayers(inputsBufferSnapshot *InputsBufferSnapshot)
*/
thatPlayerJoinMask := uint64(1 << uint32(player.JoinIndex-1))
isActiveSlowTicker := (0 < (thatPlayerJoinMask & inputsBufferSnapshot.UnconfirmedMask)) && (PlayerBattleStateIns.ACTIVE == playerBattleState)
if isActiveSlowTicker {
if pR.ForceAllResyncOnAnyActiveSlowTicker && isActiveSlowTicker {
inputsBufferSnapshot.ShouldForceResync = true
break
}

View File

@@ -373,7 +373,7 @@ func Serve(c *gin.Context) {
// TODO: Is there any potential edge-trigger improvement like the epoll approach mentioned above for the following statement? See discussion in https://github.com/gorilla/websocket/issues/122
_, bytes, err := conn.ReadMessage()
if nil != err {
Logger.Error("About to `signalToCloseConnOfThisPlayer`", zap.Any("roomId", pRoom.Id), zap.Any("playerId", playerId), zap.Error(err))
Logger.Error("About to `signalToCloseConnOfThisPlayer` due to conn.ReadMessage err", zap.Any("roomId", pRoom.Id), zap.Any("playerId", playerId), zap.Error(err))
signalToCloseConnOfThisPlayer(Constants.RetCode.UnknownError, "")
return nil
}