using System; using StellaOps.Scanner.Worker.Options; namespace StellaOps.Scanner.Worker.Processing; public sealed class PollDelayStrategy { private readonly ScannerWorkerOptions.PollingOptions _options; private TimeSpan _currentDelay; public PollDelayStrategy(ScannerWorkerOptions.PollingOptions options) { _options = options ?? throw new ArgumentNullException(nameof(options)); } public TimeSpan NextDelay() { if (_currentDelay == TimeSpan.Zero) { _currentDelay = _options.InitialDelay; return ApplyJitter(_currentDelay); } var doubled = _currentDelay + _currentDelay; _currentDelay = doubled < _options.MaxDelay ? doubled : _options.MaxDelay; return ApplyJitter(_currentDelay); } public void Reset() => _currentDelay = TimeSpan.Zero; private TimeSpan ApplyJitter(TimeSpan duration) { if (_options.JitterRatio <= 0) { return duration; } var maxOffset = duration.TotalMilliseconds * _options.JitterRatio; if (maxOffset <= 0) { return duration; } var offset = (Random.Shared.NextDouble() * 2.0 - 1.0) * maxOffset; var adjustedMs = Math.Max(0, duration.TotalMilliseconds + offset); return TimeSpan.FromMilliseconds(adjustedMs); } }