Implement login queue reconnects
This commit is contained in:
parent
c29d8634ad
commit
b93e433227
1 changed files with 53 additions and 9 deletions
|
|
@ -13,10 +13,12 @@ namespace MHServerEmu.PlayerManagement.Players
|
|||
public class LoginQueueManager
|
||||
{
|
||||
private const ushort MuxChannel = 1;
|
||||
private const float ReconnectPermissionPercentile = 0.1f;
|
||||
|
||||
private static readonly Logger Logger = LogManager.CreateLogger();
|
||||
private static readonly TimeSpan PendingClientTimeout = TimeSpan.FromSeconds(15);
|
||||
private static readonly TimeSpan StatusUpdateInterval = TimeSpan.FromSeconds(10);
|
||||
private static readonly TimeSpan ReconnectPermissionDuration = TimeSpan.FromMinutes(10);
|
||||
|
||||
private readonly DoubleBufferQueue<IFrontendClient> _newClientQueue = new();
|
||||
|
||||
|
|
@ -34,6 +36,9 @@ namespace MHServerEmu.PlayerManagement.Players
|
|||
private readonly LoginQueueStatus.Builder _statusBuilder = LoginQueueStatus.CreateBuilder();
|
||||
private readonly Dictionary<IFrontendClient, TimeSpan> _statusUpdateTimes;
|
||||
|
||||
private readonly Dictionary<ulong, TimeSpan> _reconnectPermissions = new();
|
||||
private CooldownTimer _reconnectPermissionPurgeTimer = new(TimeSpan.FromMinutes(1));
|
||||
|
||||
public int PlayersInLine { get => _defaultQueue.Count + _reconnectQueue.Count; }
|
||||
|
||||
public LoginQueueManager(PlayerManagerService playerManager)
|
||||
|
|
@ -55,6 +60,7 @@ namespace MHServerEmu.PlayerManagement.Players
|
|||
public void Update()
|
||||
{
|
||||
TimeOutPendingClients();
|
||||
PurgeReconnectPermissions();
|
||||
AcceptNewClients();
|
||||
ProcessLoginQueue();
|
||||
}
|
||||
|
|
@ -94,6 +100,24 @@ namespace MHServerEmu.PlayerManagement.Players
|
|||
}
|
||||
}
|
||||
|
||||
private void PurgeReconnectPermissions()
|
||||
{
|
||||
if (_reconnectPermissionPurgeTimer.Check() == false)
|
||||
return;
|
||||
|
||||
TimeSpan now = Clock.UnixTime;
|
||||
|
||||
foreach (var kvp in _reconnectPermissions)
|
||||
{
|
||||
TimeSpan duration = now - kvp.Value;
|
||||
if (duration >= ReconnectPermissionDuration)
|
||||
{
|
||||
Logger.Info($"Purged reconnect permission for account 0x{kvp.Key:X}");
|
||||
_reconnectPermissions.Remove(kvp.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Accepts asynchronously added clients to the login queue.
|
||||
/// </summary>
|
||||
|
|
@ -122,9 +146,6 @@ namespace MHServerEmu.PlayerManagement.Players
|
|||
}
|
||||
else
|
||||
{
|
||||
// TODO: check reconnect
|
||||
LinkedList<IFrontendClient> queueToUse = _defaultQueue;
|
||||
|
||||
if (_queueNodes.TryPop(out LinkedListNode<IFrontendClient> queueNode) == false)
|
||||
{
|
||||
Logger.Warn($"AcceptNewClients(): Unable to accept client [{client}], the queue already has {PlayersInLine} clients, which is the maximum number allowed by the current server configuration");
|
||||
|
|
@ -133,6 +154,14 @@ namespace MHServerEmu.PlayerManagement.Players
|
|||
continue;
|
||||
}
|
||||
|
||||
LinkedList<IFrontendClient> queueToUse = _defaultQueue;
|
||||
|
||||
if (_reconnectPermissions.Remove(client.DbId))
|
||||
{
|
||||
queueToUse = _reconnectQueue;
|
||||
Logger.Info($"Consumed reconnect permission for client [{client}]");
|
||||
}
|
||||
|
||||
queueNode.Value = client;
|
||||
queueToUse.AddLast(queueNode);
|
||||
}
|
||||
|
|
@ -208,6 +237,7 @@ namespace MHServerEmu.PlayerManagement.Players
|
|||
if (client.IsConnected == false)
|
||||
{
|
||||
Logger.Warn($"ProcessQueuedClient(): Client [{client}] disconnected while waiting in the login queue");
|
||||
TryAddReconnectPermission(client, 1, Clock.UnixTime);
|
||||
RemoveClientSession(client);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -228,12 +258,6 @@ namespace MHServerEmu.PlayerManagement.Players
|
|||
return true;
|
||||
}
|
||||
|
||||
private void RemoveClientSession(IFrontendClient client)
|
||||
{
|
||||
ulong sessionId = client.Session.Id;
|
||||
_playerManager.SessionManager.RemoveActiveSession(sessionId);
|
||||
}
|
||||
|
||||
private void UpdateQueueStatus(LinkedList<IFrontendClient> queue, ref ulong nextPlaceInLine, TimeSpan now)
|
||||
{
|
||||
LinkedListNode<IFrontendClient> current = queue.First;
|
||||
|
|
@ -249,6 +273,7 @@ namespace MHServerEmu.PlayerManagement.Players
|
|||
current = current.Next;
|
||||
RemoveQueueNode(prev);
|
||||
|
||||
TryAddReconnectPermission(client, nextPlaceInLine, now);
|
||||
RemoveClientSession(client);
|
||||
|
||||
continue;
|
||||
|
|
@ -274,5 +299,24 @@ namespace MHServerEmu.PlayerManagement.Players
|
|||
node.Remove();
|
||||
_queueNodes.Push(node);
|
||||
}
|
||||
|
||||
private void RemoveClientSession(IFrontendClient client)
|
||||
{
|
||||
ulong sessionId = client.Session.Id;
|
||||
_playerManager.SessionManager.RemoveActiveSession(sessionId);
|
||||
}
|
||||
|
||||
private void TryAddReconnectPermission(IFrontendClient client, ulong placeInLine, TimeSpan now)
|
||||
{
|
||||
if (PlayersInLine == 0)
|
||||
return;
|
||||
|
||||
float percentile = (float)placeInLine / PlayersInLine;
|
||||
if (placeInLine == 1 || percentile <= ReconnectPermissionPercentile)
|
||||
{
|
||||
_reconnectPermissions[client.DbId] = now;
|
||||
Logger.Info($"Added reconnect permission for client [{client}] (placeInLine={placeInLine})");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue