mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
Fix: make AutoRelog retries single-owner (#3186)
Login rejections could schedule and execute multiple restarts for one failure while leaving no usable console route during reconnect delays. Changes: - Bind failure and restart work to immutable connection attempts - Coalesce automatic retries while allowing explicit settings replacement until commit - Preserve held bots and offline command routing across failed logins - Add deterministic retry, ownership, and routing regression tests Fixes #3186
This commit is contained in:
parent
92212d2b95
commit
456a548cbc
11 changed files with 645 additions and 114 deletions
107
MinecraftClient/ConnectionAttemptLifecycle.cs
Normal file
107
MinecraftClient/ConnectionAttemptLifecycle.cs
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using MinecraftClient.Scripting;
|
||||
|
||||
namespace MinecraftClient
|
||||
{
|
||||
internal sealed class ConnectionAttemptLifecycle
|
||||
{
|
||||
private int disconnectState;
|
||||
|
||||
internal bool IsFailureClaimed => Volatile.Read(ref disconnectState) != 0;
|
||||
|
||||
internal bool TryBeginDisconnect()
|
||||
{
|
||||
return Interlocked.CompareExchange(ref disconnectState, 1, 0) == 0;
|
||||
}
|
||||
|
||||
internal void CompleteDisconnect()
|
||||
{
|
||||
Volatile.Write(ref disconnectState, 2);
|
||||
}
|
||||
|
||||
internal static void RestoreHeldBots(ICollection<ChatBot> heldBots, Action<ChatBot> loadBot)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(heldBots);
|
||||
ArgumentNullException.ThrowIfNull(loadBot);
|
||||
|
||||
foreach (ChatBot bot in heldBots)
|
||||
loadBot(bot);
|
||||
heldBots.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class AttemptOwnedRoute
|
||||
{
|
||||
private const long NoOwner = -1;
|
||||
private readonly Lock stateLock = new();
|
||||
private long ownerAttempt = NoOwner;
|
||||
|
||||
internal long OwnerAttempt
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (stateLock)
|
||||
return ownerAttempt;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool TryActivate(long connectionAttempt, Action activate)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(activate);
|
||||
|
||||
lock (stateLock)
|
||||
{
|
||||
if (ownerAttempt >= connectionAttempt)
|
||||
return false;
|
||||
|
||||
ownerAttempt = connectionAttempt;
|
||||
activate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool TryDeactivate(long connectionAttempt, Action deactivate)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(deactivate);
|
||||
|
||||
lock (stateLock)
|
||||
{
|
||||
if (ownerAttempt != connectionAttempt)
|
||||
return false;
|
||||
|
||||
ownerAttempt = NoOwner;
|
||||
deactivate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool TryTransfer(long sourceConnectionAttempt, long targetConnectionAttempt)
|
||||
{
|
||||
lock (stateLock)
|
||||
{
|
||||
if (ownerAttempt != sourceConnectionAttempt)
|
||||
return false;
|
||||
|
||||
ownerAttempt = targetConnectionAttempt;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool TryDeactivate(Action deactivate)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(deactivate);
|
||||
|
||||
lock (stateLock)
|
||||
{
|
||||
if (ownerAttempt == NoOwner)
|
||||
return false;
|
||||
|
||||
ownerAttempt = NoOwner;
|
||||
deactivate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue