diff --git a/src/NATS.Client.Core/NatsOpts.cs b/src/NATS.Client.Core/NatsOpts.cs index 5dc7b2083..e99530c80 100644 --- a/src/NATS.Client.Core/NatsOpts.cs +++ b/src/NATS.Client.Core/NatsOpts.cs @@ -4,6 +4,9 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using NATS.Client.Core.Internal; +#if NETSTANDARD +using Random = NATS.Client.Core.Internal.NetStandardExtensions.Random; +#endif namespace NATS.Client.Core; @@ -186,3 +189,21 @@ internal NatsOpts ReadUserInfoFromConnectionString() } } } + +public static class NatsOptsExtensions +{ + /// + /// Applies an exponential backoff delay with an added random jitter for attempts. + /// + /// The NatsOpts instance containing configuration settings for intervals and jitter. + /// The current attempt iteration, used to calculate the exponential delay. + /// A task that completes after the calculated delay time has elapsed. + public static Task BackoffWithJitterAsync(this NatsOpts opts, int iter) + { + var baseDelay = opts.ReconnectWaitMin.TotalMilliseconds * Math.Pow(2, iter - 1); + var jitter = opts.ReconnectJitter.TotalMilliseconds * Random.Shared.NextDouble(); + + var delay = Math.Min(baseDelay + jitter, opts.ReconnectWaitMax.TotalMilliseconds); + return Task.Delay(TimeSpan.FromMilliseconds(delay)); + } +} diff --git a/src/NATS.Client.JetStream/NatsJSOrderedConsumer.cs b/src/NATS.Client.JetStream/NatsJSOrderedConsumer.cs index ce93c77b9..57560464e 100644 --- a/src/NATS.Client.JetStream/NatsJSOrderedConsumer.cs +++ b/src/NATS.Client.JetStream/NatsJSOrderedConsumer.cs @@ -2,6 +2,9 @@ using Microsoft.Extensions.Logging; using NATS.Client.Core; using NATS.Client.JetStream.Models; +#if NETSTANDARD +using Random = NATS.Client.Core.Internal.NetStandardExtensions.Random; +#endif namespace NATS.Client.JetStream; @@ -314,11 +317,16 @@ private async Task RecreateConsumer(string consumer, ulong seq, catch (NatsJSApiNoResponseException) { } + catch (NatsJSApiException apiException) when (apiException.Error.Code == 503) + { + } if (i == _opts.MaxResetAttempts) { throw new NatsJSException("Maximum number of create attempts reached."); } + + await _context.Connection.Opts.BackoffWithJitterAsync(i); } Info = info;