forked from admin/VolcanicAgenticCore
28 lines
1.3 KiB
C#
28 lines
1.3 KiB
C#
namespace Volcanic.AgenticCore.Telegram.Polling;
|
|
|
|
/// <summary>
|
|
/// Exponential backoff with jitter for consecutive polling failures. Thread-safe: failures are counted by the polling
|
|
/// loop, the reset comes from the HTTP response callback.
|
|
/// </summary>
|
|
public sealed class ReconnectPolicy(TimeSpan initialDelay, TimeSpan maxDelay, double jitter = 0.2, Random? random = null)
|
|
{
|
|
private readonly Random _random = random ?? Random.Shared;
|
|
private int _failures;
|
|
|
|
/// <summary>Consecutive failures since the last success.</summary>
|
|
public int Failures => Volatile.Read(ref _failures);
|
|
|
|
/// <summary>Record a failure and return how long to wait before the next attempt.</summary>
|
|
public TimeSpan NextDelay()
|
|
{
|
|
var failures = Interlocked.Increment(ref _failures);
|
|
var exponent = Math.Min(failures - 1, 30);
|
|
var ms = Math.Min(maxDelay.TotalMilliseconds, initialDelay.TotalMilliseconds * Math.Pow(2, exponent));
|
|
var factor = 1 + ((_random.NextDouble() * 2) - 1) * jitter;
|
|
return TimeSpan.FromMilliseconds(Math.Max(0, ms * factor));
|
|
}
|
|
|
|
/// <summary>Record a success. Returns the number of failures it ends (0 when the connection was healthy).</summary>
|
|
public int Reset() => Interlocked.Exchange(ref _failures, 0);
|
|
}
|