Fix server update restarts when server paused. (#8509)
This commit is contained in:
committed by
GitHub
parent
e649dcea14
commit
5f9f319d5a
109
Content.Server/ServerUpdates/ServerUpdateManager.cs
Normal file
109
Content.Server/ServerUpdates/ServerUpdateManager.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Shared.CCVar;
|
||||
using Robust.Server;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Server.ServerStatus;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.ServerUpdates;
|
||||
|
||||
/// <summary>
|
||||
/// Responsible for restarting the server for update, when not disruptive.
|
||||
/// </summary>
|
||||
public sealed class ServerUpdateManager
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IWatchdogApi _watchdog = default!;
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IChatManager _chatManager = default!;
|
||||
[Dependency] private readonly IBaseServer _server = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
|
||||
[ViewVariables]
|
||||
private bool _updateOnRoundEnd;
|
||||
|
||||
private TimeSpan? _restartTime;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_watchdog.UpdateReceived += WatchdogOnUpdateReceived;
|
||||
_playerManager.PlayerStatusChanged += PlayerManagerOnPlayerStatusChanged;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (_restartTime != null && _restartTime < _gameTiming.RealTime)
|
||||
{
|
||||
DoShutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Notify that the round just ended, which is a great time to restart if necessary!
|
||||
/// </summary>
|
||||
/// <returns>True if the server is going to restart.</returns>
|
||||
public bool RoundEnded()
|
||||
{
|
||||
if (_updateOnRoundEnd)
|
||||
{
|
||||
DoShutdown();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void PlayerManagerOnPlayerStatusChanged(object? sender, SessionStatusEventArgs e)
|
||||
{
|
||||
switch (e.NewStatus)
|
||||
{
|
||||
case SessionStatus.Connecting:
|
||||
_restartTime = null;
|
||||
break;
|
||||
case SessionStatus.Disconnected:
|
||||
ServerEmptyUpdateRestartCheck();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void WatchdogOnUpdateReceived()
|
||||
{
|
||||
_chatManager.DispatchServerAnnouncement(Loc.GetString("server-updates-received"));
|
||||
_updateOnRoundEnd = true;
|
||||
ServerEmptyUpdateRestartCheck();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether there are still players on the server,
|
||||
/// and if not starts a timer to automatically reboot the server if an update is available.
|
||||
/// </summary>
|
||||
private void ServerEmptyUpdateRestartCheck()
|
||||
{
|
||||
// Can't simple check the current connected player count since that doesn't update
|
||||
// before PlayerStatusChanged gets fired.
|
||||
// So in the disconnect handler we'd still see a single player otherwise.
|
||||
var playersOnline = _playerManager.Sessions.Any(p => p.Status != SessionStatus.Disconnected);
|
||||
if (playersOnline || !_updateOnRoundEnd)
|
||||
{
|
||||
// Still somebody online.
|
||||
return;
|
||||
}
|
||||
|
||||
if (_restartTime != null)
|
||||
{
|
||||
// Do nothing because I guess we already have a timer running..?
|
||||
return;
|
||||
}
|
||||
|
||||
var restartDelay = TimeSpan.FromSeconds(_cfg.GetCVar(CCVars.UpdateRestartDelay));
|
||||
_restartTime = restartDelay + _gameTiming.RealTime;
|
||||
}
|
||||
|
||||
private void DoShutdown()
|
||||
{
|
||||
_server.Shutdown(Loc.GetString("server-updates-shutdown"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user