The control layer keeps doubling after the first minute up to ten minutes, and the QUIC redial doubles after twelve short attempts up to five minutes, instead of retrying every minute or every five seconds forever.
40 lines
1.3 KiB
C#
40 lines
1.3 KiB
C#
namespace MoShiro.Agent;
|
|
|
|
/// <summary>Reconnect cadence for the control connection of a single dialer-to-listener path: 1, 2, 4, 8, 16, then five 32-second waits, then once per minute.</summary>
|
|
public sealed class ControlBackoff
|
|
{
|
|
private static readonly TimeSpan[] s_delays =
|
|
[
|
|
TimeSpan.FromSeconds(1),
|
|
TimeSpan.FromSeconds(2),
|
|
TimeSpan.FromSeconds(4),
|
|
TimeSpan.FromSeconds(8),
|
|
TimeSpan.FromSeconds(16),
|
|
TimeSpan.FromSeconds(32),
|
|
TimeSpan.FromSeconds(32),
|
|
TimeSpan.FromSeconds(32),
|
|
TimeSpan.FromSeconds(32),
|
|
TimeSpan.FromSeconds(32),
|
|
];
|
|
|
|
private const int MaxMinutes = 10;
|
|
|
|
private int _attempt;
|
|
|
|
public int Attempts => Volatile.Read(ref _attempt);
|
|
|
|
public TimeSpan Next()
|
|
{
|
|
int attempt = Interlocked.Increment(ref _attempt) - 1;
|
|
if (attempt < s_delays.Length)
|
|
{
|
|
return s_delays[attempt];
|
|
}
|
|
|
|
// 表走完还连不上(对端关了、这台机器没有这条路由):一分钟起继续翻倍,最长十分钟,不再每分钟白白重试一次、写三条日志
|
|
return TimeSpan.FromMinutes(Math.Min(MaxMinutes, 1 << Math.Min(attempt - s_delays.Length, 4)));
|
|
}
|
|
|
|
public void Reset() => Interlocked.Exchange(ref _attempt, 0);
|
|
}
|