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:
Anon 2026-07-27 16:12:10 +02:00
parent 92212d2b95
commit 456a548cbc
11 changed files with 645 additions and 114 deletions

View file

@ -62,6 +62,37 @@ public sealed class AutoRelogRetryPolicyTests
Assert.Equal(0, retriesLeft);
}
[Fact]
public void CoalescedDuplicateRollsBackOnlyItsOwnReservation()
{
var policy = new AutoRelogRetryPolicy(new ManualTimeProvider());
Assert.True(policy.TryReserveAttempt(2, out int firstRetriesLeft));
Assert.True(policy.TryReserveAttempt(2, out int duplicateRetriesLeft));
policy.RollBackReservedAttempt();
Assert.Equal(1, firstRetriesLeft);
Assert.Equal(0, duplicateRetriesLeft);
Assert.Equal(1, policy.Attempts);
Assert.True(policy.TryReserveAttempt(2, out int secondFailureRetriesLeft));
Assert.Equal(0, secondFailureRetriesLeft);
Assert.False(policy.TryReserveAttempt(2, out _));
}
[Fact]
public void UnlimitedDuplicateRollbackKeepsUnlimitedBudget()
{
var policy = new AutoRelogRetryPolicy(new ManualTimeProvider());
Assert.True(policy.TryReserveAttempt(-1, out _));
Assert.True(policy.TryReserveAttempt(-1, out _));
policy.RollBackReservedAttempt();
Assert.Equal(1, policy.Attempts);
Assert.True(policy.TryReserveAttempt(-1, out int retriesLeft));
Assert.Equal(-1, retriesLeft);
}
[Fact]
public void StableConnectionResetsRetryBudget()
{