diff --git a/src/libraries/System.Threading.RateLimiting/ref/System.Threading.RateLimiting.cs b/src/libraries/System.Threading.RateLimiting/ref/System.Threading.RateLimiting.cs index c53f41ffa05e33..4c1f4280bd94ca 100644 --- a/src/libraries/System.Threading.RateLimiting/ref/System.Threading.RateLimiting.cs +++ b/src/libraries/System.Threading.RateLimiting/ref/System.Threading.RateLimiting.cs @@ -18,10 +18,10 @@ protected override void Dispose(bool disposing) { } } public sealed partial class ConcurrencyLimiterOptions { - public ConcurrencyLimiterOptions(int permitLimit, System.Threading.RateLimiting.QueueProcessingOrder queueProcessingOrder, int queueLimit) { } - public int PermitLimit { get { throw null; } } - public int QueueLimit { get { throw null; } } - public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } } + public ConcurrencyLimiterOptions() { } + public int PermitLimit { get { throw null; } set { throw null; } } + public int QueueLimit { get { throw null; } set { throw null; } } + public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } set { throw null; } } } public sealed partial class FixedWindowRateLimiter : System.Threading.RateLimiting.ReplenishingRateLimiter { @@ -38,12 +38,12 @@ protected override void Dispose(bool disposing) { } } public sealed partial class FixedWindowRateLimiterOptions { - public FixedWindowRateLimiterOptions(int permitLimit, System.Threading.RateLimiting.QueueProcessingOrder queueProcessingOrder, int queueLimit, System.TimeSpan window, bool autoReplenishment = true) { } - public bool AutoReplenishment { get { throw null; } } - public int PermitLimit { get { throw null; } } - public int QueueLimit { get { throw null; } } - public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } } - public System.TimeSpan Window { get { throw null; } } + public FixedWindowRateLimiterOptions() { } + public bool AutoReplenishment { get { throw null; } set { throw null; } } + public int PermitLimit { get { throw null; } set { throw null; } } + public int QueueLimit { get { throw null; } set { throw null; } } + public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } set { throw null; } } + public System.TimeSpan Window { get { throw null; } set { throw null; } } } public static partial class MetadataName { @@ -151,13 +151,13 @@ protected override void Dispose(bool disposing) { } } public sealed partial class SlidingWindowRateLimiterOptions { - public SlidingWindowRateLimiterOptions(int permitLimit, System.Threading.RateLimiting.QueueProcessingOrder queueProcessingOrder, int queueLimit, System.TimeSpan window, int segmentsPerWindow, bool autoReplenishment = true) { } - public bool AutoReplenishment { get { throw null; } } - public int PermitLimit { get { throw null; } } - public int QueueLimit { get { throw null; } } - public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } } - public int SegmentsPerWindow { get { throw null; } } - public System.TimeSpan Window { get { throw null; } } + public SlidingWindowRateLimiterOptions() { } + public bool AutoReplenishment { get { throw null; } set { throw null; } } + public int PermitLimit { get { throw null; } set { throw null; } } + public int QueueLimit { get { throw null; } set { throw null; } } + public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } set { throw null; } } + public int SegmentsPerWindow { get { throw null; } set { throw null; } } + public System.TimeSpan Window { get { throw null; } set { throw null; } } } public sealed partial class TokenBucketRateLimiter : System.Threading.RateLimiting.ReplenishingRateLimiter { @@ -174,12 +174,12 @@ protected override void Dispose(bool disposing) { } } public sealed partial class TokenBucketRateLimiterOptions { - public TokenBucketRateLimiterOptions(int tokenLimit, System.Threading.RateLimiting.QueueProcessingOrder queueProcessingOrder, int queueLimit, System.TimeSpan replenishmentPeriod, int tokensPerPeriod, bool autoReplenishment = true) { } - public bool AutoReplenishment { get { throw null; } } - public int QueueLimit { get { throw null; } } - public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } } - public System.TimeSpan ReplenishmentPeriod { get { throw null; } } - public int TokenLimit { get { throw null; } } - public int TokensPerPeriod { get { throw null; } } + public TokenBucketRateLimiterOptions() { } + public bool AutoReplenishment { get { throw null; } set { throw null; } } + public int QueueLimit { get { throw null; } set { throw null; } } + public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } set { throw null; } } + public System.TimeSpan ReplenishmentPeriod { get { throw null; } set { throw null; } } + public int TokenLimit { get { throw null; } set { throw null; } } + public int TokensPerPeriod { get { throw null; } set { throw null; } } } } diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs index 2b38d6d0eed005..0c4b8b7e1b328d 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiter.cs @@ -38,7 +38,26 @@ public sealed class ConcurrencyLimiter : RateLimiter /// Options to specify the behavior of the . public ConcurrencyLimiter(ConcurrencyLimiterOptions options) { - _options = options ?? throw new ArgumentNullException(nameof(options)); + if (options is null) + { + throw new ArgumentNullException(nameof(options)); + } + if (options.PermitLimit <= 0) + { + throw new ArgumentException($"{nameof(options.PermitLimit)} must be set to a value greater than 0.", nameof(options)); + } + if (options.QueueLimit < 0) + { + throw new ArgumentException($"{nameof(options.QueueLimit)} must be set to a value greater than or equal to 0.", nameof(options)); + } + + _options = new ConcurrencyLimiterOptions + { + PermitLimit = options.PermitLimit, + QueueProcessingOrder = options.QueueProcessingOrder, + QueueLimit = options.QueueLimit + }; + _permitCount = _options.PermitLimit; } diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiterOptions.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiterOptions.cs index 104de7cd3f04ef..23514c5906c117 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiterOptions.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ConcurrencyLimiterOptions.cs @@ -8,32 +8,11 @@ namespace System.Threading.RateLimiting /// public sealed class ConcurrencyLimiterOptions { - /// - /// Initializes the . - /// - /// Maximum number of permits that can be leased concurrently. - /// Determines the behaviour of when not enough resources can be leased. - /// Maximum number of permits that can be queued concurrently. - /// When or are less than 0. - public ConcurrencyLimiterOptions(int permitLimit, QueueProcessingOrder queueProcessingOrder, int queueLimit) - { - if (permitLimit < 0) - { - throw new ArgumentOutOfRangeException(nameof(permitLimit)); - } - if (queueLimit < 0) - { - throw new ArgumentOutOfRangeException(nameof(queueLimit)); - } - PermitLimit = permitLimit; - QueueProcessingOrder = queueProcessingOrder; - QueueLimit = queueLimit; - } - /// /// Maximum number of permits that can be leased concurrently. + /// Must be set to a value > 0 by the time these options are passed to the constructor of . /// - public int PermitLimit { get; } + public int PermitLimit { get; set; } /// /// Determines the behaviour of when not enough resources can be leased. @@ -41,11 +20,12 @@ public ConcurrencyLimiterOptions(int permitLimit, QueueProcessingOrder queueProc /// /// by default. /// - public QueueProcessingOrder QueueProcessingOrder { get; } = QueueProcessingOrder.OldestFirst; + public QueueProcessingOrder QueueProcessingOrder { get; set; } = QueueProcessingOrder.OldestFirst; /// /// Maximum number of permits that can be queued concurrently. + /// Must be set to a value >= 0 by the time these options are passed to the constructor of . /// - public int QueueLimit { get; } + public int QueueLimit { get; set; } } } diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs index c6b1b67ada3109..4538afa013c3e1 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiter.cs @@ -44,7 +44,32 @@ public sealed class FixedWindowRateLimiter : ReplenishingRateLimiter /// Options to specify the behavior of the . public FixedWindowRateLimiter(FixedWindowRateLimiterOptions options) { - _options = options ?? throw new ArgumentNullException(nameof(options)); + if (options is null) + { + throw new ArgumentNullException(nameof(options)); + } + if (options.PermitLimit <= 0) + { + throw new ArgumentException($"{nameof(options.PermitLimit)} must be set to a value greater than 0.", nameof(options)); + } + if (options.QueueLimit < 0) + { + throw new ArgumentException($"{nameof(options.QueueLimit)} must be set to a value greater than or equal to 0.", nameof(options)); + } + if (options.Window < TimeSpan.Zero) + { + throw new ArgumentException($"{nameof(options.Window)} must be set to a value greater than or equal to TimeSpan.Zero.", nameof(options)); + } + + _options = new FixedWindowRateLimiterOptions + { + PermitLimit = options.PermitLimit, + QueueProcessingOrder = options.QueueProcessingOrder, + QueueLimit = options.QueueLimit, + Window = options.Window, + AutoReplenishment = options.AutoReplenishment + }; + _requestCount = options.PermitLimit; _idleSince = _lastReplenishmentTick = Stopwatch.GetTimestamp(); diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiterOptions.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiterOptions.cs index a1a88deb7f04f7..8395b19d62d5d1 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiterOptions.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/FixedWindowRateLimiterOptions.cs @@ -8,57 +8,26 @@ namespace System.Threading.RateLimiting /// public sealed class FixedWindowRateLimiterOptions { - /// - /// Initializes the . - /// - /// Maximum number of requests that can be served in the window. - /// - /// Maximum number of unprocessed request counters waiting via . - /// - /// Specifies how often request counters can be replenished. Replenishing is triggered either by an internal timer if is true, or by calling . - /// - /// - /// Specifies whether request replenishment will be handled by the or by another party via . - /// - /// When or are less than 0. - public FixedWindowRateLimiterOptions( - int permitLimit, - QueueProcessingOrder queueProcessingOrder, - int queueLimit, - TimeSpan window, - bool autoReplenishment = true) - { - if (permitLimit < 0) - { - throw new ArgumentOutOfRangeException(nameof(permitLimit)); - } - if (queueLimit < 0) - { - throw new ArgumentOutOfRangeException(nameof(queueLimit)); - } - - PermitLimit = permitLimit; - QueueProcessingOrder = queueProcessingOrder; - QueueLimit = queueLimit; - Window = window; - AutoReplenishment = autoReplenishment; - } - /// /// Specifies the time window that takes in the requests. + /// Must be set to a value >= by the time these options are passed to the constructor of . /// - public TimeSpan Window { get; } + public TimeSpan Window { get; set; } = TimeSpan.Zero; /// /// Specified whether the is automatically refresh counters or if someone else /// will be calling to refresh counters. /// - public bool AutoReplenishment { get; } + /// + /// by default. + /// + public bool AutoReplenishment { get; set; } = true; /// /// Maximum number of permit counters that can be allowed in a window. + /// Must be set to a value > 0 by the time these options are passed to the constructor of . /// - public int PermitLimit { get; } + public int PermitLimit { get; set; } /// /// Determines the behaviour of when not enough resources can be leased. @@ -66,11 +35,12 @@ public FixedWindowRateLimiterOptions( /// /// by default. /// - public QueueProcessingOrder QueueProcessingOrder { get; } + public QueueProcessingOrder QueueProcessingOrder { get; set; } = QueueProcessingOrder.OldestFirst; /// /// Maximum cumulative permit count of queued acquisition requests. + /// Must be set to a value >= 0 by the time these options are passed to the constructor of . /// - public int QueueLimit { get; } + public int QueueLimit { get; set; } } } diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/RateLimitPartition.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/RateLimitPartition.cs index 4042cce53141b1..f6b3e1a2ad0e93 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/RateLimitPartition.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/RateLimitPartition.cs @@ -71,8 +71,15 @@ public static RateLimitPartition GetTokenBucketLimiter( // We don't want individual TokenBucketRateLimiters to have timers. We will instead have our own internal Timer handling all of them if (options.AutoReplenishment is true) { - options = new TokenBucketRateLimiterOptions(options.TokenLimit, options.QueueProcessingOrder, options.QueueLimit, - options.ReplenishmentPeriod, options.TokensPerPeriod, autoReplenishment: false); + options = new TokenBucketRateLimiterOptions + { + TokenLimit = options.TokenLimit, + QueueProcessingOrder = options.QueueProcessingOrder, + QueueLimit = options.QueueLimit, + ReplenishmentPeriod = options.ReplenishmentPeriod, + TokensPerPeriod = options.TokensPerPeriod, + AutoReplenishment = false + }; } return new TokenBucketRateLimiter(options); }); @@ -98,8 +105,15 @@ public static RateLimitPartition GetSlidingWindowLimiter( // We don't want individual SlidingWindowRateLimiters to have timers. We will instead have our own internal Timer handling all of them if (options.AutoReplenishment is true) { - options = new SlidingWindowRateLimiterOptions(options.PermitLimit, options.QueueProcessingOrder, options.QueueLimit, - options.Window, options.SegmentsPerWindow, autoReplenishment: false); + options = new SlidingWindowRateLimiterOptions + { + PermitLimit = options.PermitLimit, + QueueProcessingOrder = options.QueueProcessingOrder, + QueueLimit = options.QueueLimit, + Window = options.Window, + SegmentsPerWindow = options.SegmentsPerWindow, + AutoReplenishment = false + }; } return new SlidingWindowRateLimiter(options); }); @@ -125,8 +139,14 @@ public static RateLimitPartition GetFixedWindowLimiter( // We don't want individual FixedWindowRateLimiters to have timers. We will instead have our own internal Timer handling all of them if (options.AutoReplenishment is true) { - options = new FixedWindowRateLimiterOptions(options.PermitLimit, options.QueueProcessingOrder, options.QueueLimit, - options.Window, autoReplenishment: false); + options = new FixedWindowRateLimiterOptions + { + PermitLimit = options.PermitLimit, + QueueProcessingOrder = options.QueueProcessingOrder, + QueueLimit = options.QueueLimit, + Window = options.Window, + AutoReplenishment = false + }; } return new FixedWindowRateLimiter(options); }); diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs index 5911ef439afc24..1694ccf4b7b9ba 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiter.cs @@ -47,7 +47,33 @@ public sealed class SlidingWindowRateLimiter : ReplenishingRateLimiter /// Options to specify the behavior of the . public SlidingWindowRateLimiter(SlidingWindowRateLimiterOptions options) { - _options = options ?? throw new ArgumentNullException(nameof(options)); + if (options is null) + { + throw new ArgumentNullException(nameof(options)); + } + if (options.PermitLimit <= 0 || options.SegmentsPerWindow <= 0) + { + throw new ArgumentException($"Both {nameof(options.PermitLimit)} and {nameof(options.SegmentsPerWindow)} must be set to values greater than 0.", nameof(options)); + } + if (options.QueueLimit < 0) + { + throw new ArgumentException($"{nameof(options.QueueLimit)} must be set to a value greater than or equal to 0.", nameof(options)); + } + if (options.Window < TimeSpan.Zero) + { + throw new ArgumentException($"{nameof(options.Window)} must be set to a value greater than or equal to TimeSpan.Zero.", nameof(options)); + } + + _options = new SlidingWindowRateLimiterOptions + { + PermitLimit = options.PermitLimit, + QueueProcessingOrder = options.QueueProcessingOrder, + QueueLimit = options.QueueLimit, + Window = options.Window, + SegmentsPerWindow = options.SegmentsPerWindow, + AutoReplenishment = options.AutoReplenishment + }; + _requestCount = options.PermitLimit; // _requestsPerSegment holds the no. of acquired requests in each window segment diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiterOptions.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiterOptions.cs index 075f247471b85a..8d000e7656c4c7 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiterOptions.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/SlidingWindowRateLimiterOptions.cs @@ -8,69 +8,32 @@ namespace System.Threading.RateLimiting /// public sealed class SlidingWindowRateLimiterOptions { - /// - /// Initializes the . - /// - /// Maximum number of request counters that can be served in a window. - /// - /// Maximum number of unprocessed request counters waiting via . - /// - /// Specifies how often requests can be replenished. Replenishing is triggered either by an internal timer if is true, or by calling . - /// - /// Specified how many segments a window can be divided into. The total requests a segment can serve cannot exceed the max limit.. - /// - /// Specifies whether request replenishment will be handled by the or by another party via . - /// - /// When , , or are less than 0. - public SlidingWindowRateLimiterOptions( - int permitLimit, - QueueProcessingOrder queueProcessingOrder, - int queueLimit, - TimeSpan window, - int segmentsPerWindow, - bool autoReplenishment = true) - { - if (permitLimit < 0) - { - throw new ArgumentOutOfRangeException(nameof(permitLimit)); - } - if (queueLimit < 0) - { - throw new ArgumentOutOfRangeException(nameof(queueLimit)); - } - if (segmentsPerWindow <= 0) - { - throw new ArgumentOutOfRangeException(nameof(segmentsPerWindow)); - } - - PermitLimit = permitLimit; - QueueProcessingOrder = queueProcessingOrder; - QueueLimit = queueLimit; - Window = window; - SegmentsPerWindow = segmentsPerWindow; - AutoReplenishment = autoReplenishment; - } - /// /// Specifies the minimum period between replenishments. + /// Must be set to a value >= by the time these options are passed to the constructor of . /// - public TimeSpan Window { get; } + public TimeSpan Window { get; set; } = TimeSpan.Zero; /// /// Specifies the maximum number of segments a window is divided into. + /// Must be set to a value > 0 by the time these options are passed to the constructor of . /// - public int SegmentsPerWindow { get; } + public int SegmentsPerWindow { get; set; } /// /// Specified whether the is automatically replenishing request counters or if someone else /// will be calling to replenish tokens. /// - public bool AutoReplenishment { get; } + /// + /// by default. + /// + public bool AutoReplenishment { get; set; } = true; /// /// Maximum number of requests that can be served in a window. + /// Must be set to a value > 0 by the time these options are passed to the constructor of . /// - public int PermitLimit { get; } + public int PermitLimit { get; set; } /// /// Determines the behaviour of when not enough resources can be leased. @@ -78,11 +41,12 @@ public SlidingWindowRateLimiterOptions( /// /// by default. /// - public QueueProcessingOrder QueueProcessingOrder { get; } + public QueueProcessingOrder QueueProcessingOrder { get; set; } = QueueProcessingOrder.OldestFirst; /// /// Maximum cumulative permit count of queued acquisition requests. + /// Must be set to a value >= 0 by the time these options are passed to the constructor of . /// - public int QueueLimit { get; } + public int QueueLimit { get; set; } } } diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs index d971fc3a134663..257422fdc6d90a 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiter.cs @@ -45,7 +45,33 @@ public sealed class TokenBucketRateLimiter : ReplenishingRateLimiter /// Options to specify the behavior of the . public TokenBucketRateLimiter(TokenBucketRateLimiterOptions options) { - _options = options ?? throw new ArgumentNullException(nameof(options)); + if (options is null) + { + throw new ArgumentNullException(nameof(options)); + } + if (options.TokenLimit <= 0 || options.TokensPerPeriod <= 0) + { + throw new ArgumentException($"Both {nameof(options.TokenLimit)} and {nameof(options.TokensPerPeriod)} must be set to values greater than 0.", nameof(options)); + } + if (options.QueueLimit < 0) + { + throw new ArgumentException($"{nameof(options.QueueLimit)} must be set to a value greater than or equal to 0.", nameof(options)); + } + if (options.ReplenishmentPeriod < TimeSpan.Zero) + { + throw new ArgumentException($"{nameof(options.ReplenishmentPeriod)} must be set to a value greater than or equal to TimeSpan.Zero.", nameof(options)); + } + + _options = new TokenBucketRateLimiterOptions + { + TokenLimit = options.TokenLimit, + QueueProcessingOrder = options.QueueProcessingOrder, + QueueLimit = options.QueueLimit, + ReplenishmentPeriod = options.ReplenishmentPeriod, + TokensPerPeriod = options.TokensPerPeriod, + AutoReplenishment = options.AutoReplenishment + }; + _tokenCount = options.TokenLimit; _idleSince = _lastReplenishmentTick = Stopwatch.GetTimestamp(); diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiterOptions.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiterOptions.cs index 6c644ef85b077e..c3f29c169de69a 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiterOptions.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/TokenBucketRateLimiterOptions.cs @@ -8,69 +8,32 @@ namespace System.Threading.RateLimiting /// public sealed class TokenBucketRateLimiterOptions { - /// - /// Initializes the . - /// - /// Maximum number of tokens that can be in the token bucket. - /// - /// Maximum number of unprocessed tokens waiting via . - /// - /// Specifies how often tokens can be replenished. Replenishing is triggered either by an internal timer if is true, or by calling . - /// - /// Specified how many tokens can be added to the token bucket on a successful replenish. Available token count will not exceed . - /// - /// Specifies whether token replenishment will be handled by the or by another party via . - /// - /// When , , or are less than 0. - public TokenBucketRateLimiterOptions( - int tokenLimit, - QueueProcessingOrder queueProcessingOrder, - int queueLimit, - TimeSpan replenishmentPeriod, - int tokensPerPeriod, - bool autoReplenishment = true) - { - if (tokenLimit < 0) - { - throw new ArgumentOutOfRangeException(nameof(tokenLimit)); - } - if (queueLimit < 0) - { - throw new ArgumentOutOfRangeException(nameof(queueLimit)); - } - if (tokensPerPeriod <= 0) - { - throw new ArgumentOutOfRangeException(nameof(tokensPerPeriod)); - } - - TokenLimit = tokenLimit; - QueueProcessingOrder = queueProcessingOrder; - QueueLimit = queueLimit; - ReplenishmentPeriod = replenishmentPeriod; - TokensPerPeriod = tokensPerPeriod; - AutoReplenishment = autoReplenishment; - } - /// /// Specifies the minimum period between replenishments. + /// Must be set to a value >= by the time these options are passed to the constructor of . /// - public TimeSpan ReplenishmentPeriod { get; } + public TimeSpan ReplenishmentPeriod { get; set; } = TimeSpan.Zero; /// /// Specifies the maximum number of tokens to restore each replenishment. + /// Must be set to a value > 0 by the time these options are passed to the constructor of . /// - public int TokensPerPeriod { get; } + public int TokensPerPeriod { get; set; } /// /// Specified whether the is automatically replenishing tokens or if someone else /// will be calling to replenish tokens. /// - public bool AutoReplenishment { get; } + /// + /// by default. + /// + public bool AutoReplenishment { get; set; } = true; /// /// Maximum number of tokens that can be in the bucket at any time. + /// Must be set to a value > 0 by the time these options are passed to the constructor of . /// - public int TokenLimit { get; } + public int TokenLimit { get; set; } /// /// Determines the behaviour of when not enough resources can be leased. @@ -78,11 +41,12 @@ public TokenBucketRateLimiterOptions( /// /// by default. /// - public QueueProcessingOrder QueueProcessingOrder { get; } + public QueueProcessingOrder QueueProcessingOrder { get; set; } = QueueProcessingOrder.OldestFirst; /// /// Maximum cumulative token count of queued acquisition requests. + /// Must be set to a value >= 0 by the time these options are passed to the constructor of . /// - public int QueueLimit { get; } + public int QueueLimit { get; set; } } } diff --git a/src/libraries/System.Threading.RateLimiting/tests/ChainedLimiterTests.cs b/src/libraries/System.Threading.RateLimiting/tests/ChainedLimiterTests.cs index c0fc937d554391..b5dbd18c781c5a 100644 --- a/src/libraries/System.Threading.RateLimiting/tests/ChainedLimiterTests.cs +++ b/src/libraries/System.Threading.RateLimiting/tests/ChainedLimiterTests.cs @@ -30,11 +30,23 @@ public async Task DisposeMakesMethodsThrow() { using var limiter1 = PartitionedRateLimiter.Create(resource => { - return RateLimitPartition.GetConcurrencyLimiter(1, _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 0)); + return RateLimitPartition.GetConcurrencyLimiter(1, _ => + new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 0 + }); }); using var limiter2 = PartitionedRateLimiter.Create(resource => { - return RateLimitPartition.GetConcurrencyLimiter(1, _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 0)); + return RateLimitPartition.GetConcurrencyLimiter(1, _ => + new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 0 + }); }); var chainedLimiter = PartitionedRateLimiter.CreateChained(limiter1, limiter2); @@ -50,11 +62,23 @@ public async Task DisposeAsyncMakesMethodsThrow() { using var limiter1 = PartitionedRateLimiter.Create(resource => { - return RateLimitPartition.GetConcurrencyLimiter(1, _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 0)); + return RateLimitPartition.GetConcurrencyLimiter(1, _ => + new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 0 + }); }); using var limiter2 = PartitionedRateLimiter.Create(resource => { - return RateLimitPartition.GetConcurrencyLimiter(1, _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 0)); + return RateLimitPartition.GetConcurrencyLimiter(1, _ => + new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 0 + }); }); var chainedLimiter = PartitionedRateLimiter.CreateChained(limiter1, limiter2); @@ -70,15 +94,33 @@ public void AvailablePermitsReturnsLowestValue() { using var limiter1 = PartitionedRateLimiter.Create(resource => { - return RateLimitPartition.GetConcurrencyLimiter(1, _ => new ConcurrencyLimiterOptions(34, QueueProcessingOrder.NewestFirst, 0)); + return RateLimitPartition.GetConcurrencyLimiter(1, _ => + new ConcurrencyLimiterOptions + { + PermitLimit = 34, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 0 + }); }); using var limiter2 = PartitionedRateLimiter.Create(resource => { - return RateLimitPartition.GetConcurrencyLimiter(1, _ => new ConcurrencyLimiterOptions(22, QueueProcessingOrder.NewestFirst, 0)); + return RateLimitPartition.GetConcurrencyLimiter(1, _ => + new ConcurrencyLimiterOptions + { + PermitLimit = 22, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 0 + }); }); using var limiter3 = PartitionedRateLimiter.Create(resource => { - return RateLimitPartition.GetConcurrencyLimiter(1, _ => new ConcurrencyLimiterOptions(13, QueueProcessingOrder.NewestFirst, 0)); + return RateLimitPartition.GetConcurrencyLimiter(1, _ => + new ConcurrencyLimiterOptions + { + PermitLimit = 13, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 0 + }); }); using var chainedLimiter = PartitionedRateLimiter.CreateChained(limiter1, limiter2, limiter3); @@ -90,7 +132,13 @@ public void AvailablePermitsWithSingleLimiterWorks() { using var limiter = PartitionedRateLimiter.Create(resource => { - return RateLimitPartition.GetConcurrencyLimiter(1, _ => new ConcurrencyLimiterOptions(34, QueueProcessingOrder.NewestFirst, 0)); + return RateLimitPartition.GetConcurrencyLimiter(1, _ => + new ConcurrencyLimiterOptions + { + PermitLimit = 34, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 0 + }); }); using var chainedLimiter = PartitionedRateLimiter.CreateChained(limiter); @@ -184,8 +232,18 @@ public async Task WaitAndAcquireAsyncWorksWithMultipleLimiters() [Fact] public void AcquireLeaseCorrectlyDisposesWithMultipleLimiters() { - var concurrencyLimiter1 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); - var concurrencyLimiter2 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + var concurrencyLimiter1 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); + var concurrencyLimiter2 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => concurrencyLimiter1); @@ -210,8 +268,18 @@ public void AcquireLeaseCorrectlyDisposesWithMultipleLimiters() [Fact] public async Task WaitAndAcquireAsyncLeaseCorrectlyDisposesWithMultipleLimiters() { - var concurrencyLimiter1 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); - var concurrencyLimiter2 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + var concurrencyLimiter1 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); + var concurrencyLimiter2 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => concurrencyLimiter1); @@ -236,7 +304,12 @@ public async Task WaitAndAcquireAsyncLeaseCorrectlyDisposesWithMultipleLimiters( [Fact] public void AcquireLeaseCorrectlyDisposesWithSingleLimiter() { - var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => concurrencyLimiter); @@ -255,7 +328,12 @@ public void AcquireLeaseCorrectlyDisposesWithSingleLimiter() [Fact] public async Task WaitAndAcquireAsyncLeaseCorrectlyDisposesWithSingleLimiter() { - var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => concurrencyLimiter); @@ -275,7 +353,12 @@ public async Task WaitAndAcquireAsyncLeaseCorrectlyDisposesWithSingleLimiter() public void AcquireFailsWhenOneLimiterDoesNotHaveEnoughResources() { var limiterFactory = new TrackingRateLimiterFactory(); - using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => limiterFactory.GetLimiter(key)); @@ -301,7 +384,12 @@ public void AcquireFailsWhenOneLimiterDoesNotHaveEnoughResources() public async Task WaitAndAcquireAsyncFailsWhenOneLimiterDoesNotHaveEnoughResources() { var limiterFactory = new TrackingRateLimiterFactory(); - using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => limiterFactory.GetLimiter(key)); @@ -326,8 +414,18 @@ public async Task WaitAndAcquireAsyncFailsWhenOneLimiterDoesNotHaveEnoughResourc [Fact] public void AcquireFailsAndReleasesAcquiredResources() { - using var concurrencyLimiter1 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); - using var concurrencyLimiter2 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + using var concurrencyLimiter1 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); + using var concurrencyLimiter2 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => concurrencyLimiter1); @@ -350,8 +448,18 @@ public void AcquireFailsAndReleasesAcquiredResources() [Fact] public async Task WaitAndAcquireAsyncFailsAndReleasesAcquiredResources() { - using var concurrencyLimiter1 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); - using var concurrencyLimiter2 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + using var concurrencyLimiter1 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); + using var concurrencyLimiter2 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => concurrencyLimiter1); @@ -374,7 +482,12 @@ public async Task WaitAndAcquireAsyncFailsAndReleasesAcquiredResources() [Fact] public void AcquireThrowsAndReleasesAcquiredResources() { - using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => concurrencyLimiter); @@ -392,7 +505,12 @@ public void AcquireThrowsAndReleasesAcquiredResources() [Fact] public async Task WaitAndAcquireAsyncThrowsAndReleasesAcquiredResources() { - using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => concurrencyLimiter); @@ -445,7 +563,12 @@ internal sealed class ThrowDisposeLease : RateLimitLease [Fact] public void AcquireFailsDisposeThrows() { - using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => new CustomizableLimiter() { AcquireCoreImpl = _ => new ThrowDisposeLease() }); @@ -466,7 +589,12 @@ public void AcquireFailsDisposeThrows() [Fact] public async Task WaitAndAcquireAsyncFailsDisposeThrows() { - using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => new CustomizableLimiter() { AcquireCoreImpl = _ => new ThrowDisposeLease() }); @@ -487,7 +615,12 @@ public async Task WaitAndAcquireAsyncFailsDisposeThrows() [Fact] public void AcquireFailsDisposeThrowsMultipleLimitersThrow() { - using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => new CustomizableLimiter() { AcquireCoreImpl = _ => new ThrowDisposeLease() }); @@ -513,7 +646,12 @@ public void AcquireFailsDisposeThrowsMultipleLimitersThrow() [Fact] public async Task WaitAndAcquireAsyncFailsDisposeThrowsMultipleLimitersThrow() { - using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => new CustomizableLimiter() { WaitAndAcquireAsyncCoreImpl = (_, _) => new ValueTask(new ThrowDisposeLease()) }); @@ -539,7 +677,12 @@ public async Task WaitAndAcquireAsyncFailsDisposeThrowsMultipleLimitersThrow() [Fact] public void AcquireThrowsDisposeThrowsMultipleLimitersThrow() { - using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => new CustomizableLimiter() { AcquireCoreImpl = _ => new ThrowDisposeLease() }); @@ -566,7 +709,12 @@ public void AcquireThrowsDisposeThrowsMultipleLimitersThrow() [Fact] public async Task WaitAndAcquireAsyncThrowsDisposeThrowsMultipleLimitersThrow() { - using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => new CustomizableLimiter() { WaitAndAcquireAsyncCoreImpl = (_, _) => new ValueTask(new ThrowDisposeLease()) }); @@ -593,7 +741,12 @@ public async Task WaitAndAcquireAsyncThrowsDisposeThrowsMultipleLimitersThrow() [Fact] public void AcquireSucceedsDisposeThrowsAndReleasesResources() { - using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => new CustomizableLimiter() { AcquireCoreImpl = _ => new ThrowDisposeLease() }); @@ -617,7 +770,12 @@ public void AcquireSucceedsDisposeThrowsAndReleasesResources() [Fact] public async Task WaitAndAcquireAsyncSucceedsDisposeThrowsAndReleasesResources() { - using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + using var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => new CustomizableLimiter() { WaitAndAcquireAsyncCoreImpl = (_, _) => new ValueTask(new ThrowDisposeLease()) }); @@ -641,8 +799,18 @@ public async Task WaitAndAcquireAsyncSucceedsDisposeThrowsAndReleasesResources() [Fact] public void AcquireForwardsCorrectPermitCount() { - using var concurrencyLimiter1 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(5, QueueProcessingOrder.OldestFirst, 0)); - using var concurrencyLimiter2 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(3, QueueProcessingOrder.OldestFirst, 0)); + using var concurrencyLimiter1 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 5, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); + using var concurrencyLimiter2 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 3, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => concurrencyLimiter1); @@ -666,8 +834,18 @@ public void AcquireForwardsCorrectPermitCount() [Fact] public async Task WaitAndAcquireAsyncForwardsCorrectPermitCount() { - using var concurrencyLimiter1 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(5, QueueProcessingOrder.OldestFirst, 0)); - using var concurrencyLimiter2 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(3, QueueProcessingOrder.OldestFirst, 0)); + using var concurrencyLimiter1 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 5, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); + using var concurrencyLimiter2 = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 3, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => concurrencyLimiter1); @@ -751,7 +929,12 @@ public async Task WaitAndAcquireAsyncCanBeCanceled() { using var limiter = PartitionedRateLimiter.Create(resource => { - return RateLimitPartition.GetConcurrencyLimiter(1, key => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1)); + return RateLimitPartition.GetConcurrencyLimiter(1, key => new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1 + }); }); using var chainedLimiter = PartitionedRateLimiter.CreateChained(limiter); @@ -768,14 +951,24 @@ public async Task WaitAndAcquireAsyncCanBeCanceled() [Fact] public async Task WaitAndAcquireAsyncCanceledReleasesAcquiredResources() { - var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(2, QueueProcessingOrder.OldestFirst, 0)); + var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); using var limiter1 = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.Get(1, key => concurrencyLimiter); }); using var limiter2 = PartitionedRateLimiter.Create(resource => { - return RateLimitPartition.GetConcurrencyLimiter(1, key => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1)); + return RateLimitPartition.GetConcurrencyLimiter(1, key => new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1 + }); }); using var chainedLimiter = PartitionedRateLimiter.CreateChained(limiter1, limiter2); @@ -797,13 +990,23 @@ public async Task WaitAndAcquireAsyncWaitsForResourcesBeforeCallingNextLimiter() { using var limiter1 = PartitionedRateLimiter.Create(resource => { - return RateLimitPartition.GetConcurrencyLimiter(1, key => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1)); + return RateLimitPartition.GetConcurrencyLimiter(1, key => new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1 + }); }); using var limiter2 = PartitionedRateLimiter.Create(resource => { // 0 queue limit to verify this isn't called while the previous limiter is waiting for resource(s) // as it would return a failed lease when no queue is available - return RateLimitPartition.GetConcurrencyLimiter(1, key => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 0)); + return RateLimitPartition.GetConcurrencyLimiter(1, key => new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 0 + }); }); using var chainedLimiter = PartitionedRateLimiter.CreateChained(limiter1, limiter2); diff --git a/src/libraries/System.Threading.RateLimiting/tests/ConcurrencyLimiterTests.cs b/src/libraries/System.Threading.RateLimiting/tests/ConcurrencyLimiterTests.cs index bd65b91d70f546..ec6fac77c57304 100644 --- a/src/libraries/System.Threading.RateLimiting/tests/ConcurrencyLimiterTests.cs +++ b/src/libraries/System.Threading.RateLimiting/tests/ConcurrencyLimiterTests.cs @@ -11,14 +11,29 @@ public class ConcurrencyLimiterTests : BaseRateLimiterTests [Fact] public override void InvalidOptionsThrows() { - Assert.Throws(() => new ConcurrencyLimiterOptions(-1, QueueProcessingOrder.NewestFirst, 1)); - Assert.Throws(() => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, -1)); + Assert.Throws(() => new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = -1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + })); + Assert.Throws(() => new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = -1 + })); } [Fact] public override void CanAcquireResource() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); var lease = limiter.Acquire(); Assert.True(lease.IsAcquired); @@ -32,7 +47,12 @@ public override void CanAcquireResource() [Fact] public override async Task CanAcquireResourceAsync() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); var lease = await limiter.WaitAndAcquireAsync(); Assert.True(lease.IsAcquired); @@ -47,7 +67,12 @@ public override async Task CanAcquireResourceAsync() [Fact] public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2 + }); var lease = await limiter.WaitAndAcquireAsync(); Assert.True(lease.IsAcquired); @@ -71,7 +96,12 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() [Fact] public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(2, QueueProcessingOrder.NewestFirst, 3)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 3 + }); var lease = await limiter.WaitAndAcquireAsync(2); Assert.True(lease.IsAcquired); @@ -96,7 +126,12 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() [Fact] public override async Task FailsWhenQueuingMoreThanLimit_OldestFirst() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1 + }); using var lease = limiter.Acquire(1); var wait = limiter.WaitAndAcquireAsync(1); @@ -107,7 +142,12 @@ public override async Task FailsWhenQueuingMoreThanLimit_OldestFirst() [Fact] public override async Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); var lease = limiter.Acquire(1); var wait = limiter.WaitAndAcquireAsync(1); Assert.False(wait.IsCompleted); @@ -126,7 +166,12 @@ public override async Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst() [Fact] public override async Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFirst() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(2, QueueProcessingOrder.NewestFirst, 2)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 2 + }); var lease = limiter.Acquire(2); Assert.True(lease.IsAcquired); var wait = limiter.WaitAndAcquireAsync(1); @@ -151,7 +196,12 @@ public override async Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFir [Fact] public override async Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimitAndNoAvailability_NewestFirst() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(2, QueueProcessingOrder.NewestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); var lease = limiter.Acquire(2); Assert.True(lease.IsAcquired); @@ -170,7 +220,12 @@ public override async Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimit [Fact] public override async Task LargeAcquiresAndQueuesDoNotIntegerOverflow() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(int.MaxValue, QueueProcessingOrder.NewestFirst, int.MaxValue)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = int.MaxValue, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = int.MaxValue + }); var lease = limiter.Acquire(int.MaxValue); Assert.True(lease.IsAcquired); @@ -192,7 +247,12 @@ public override async Task LargeAcquiresAndQueuesDoNotIntegerOverflow() [Fact] public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAvailable() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1 + }); var lease = limiter.Acquire(1); var wait = limiter.WaitAndAcquireAsync(1); @@ -214,7 +274,12 @@ public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAv [Fact] public override void ThrowsWhenAcquiringMoreThanLimit() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); var ex = Assert.Throws(() => limiter.Acquire(2)); Assert.Equal("permitCount", ex.ParamName); } @@ -222,7 +287,12 @@ public override void ThrowsWhenAcquiringMoreThanLimit() [Fact] public override async Task ThrowsWhenWaitingForMoreThanLimit() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); var ex = await Assert.ThrowsAsync(async () => await limiter.WaitAndAcquireAsync(2)); Assert.Equal("permitCount", ex.ParamName); } @@ -230,21 +300,36 @@ public override async Task ThrowsWhenWaitingForMoreThanLimit() [Fact] public override void ThrowsWhenAcquiringLessThanZero() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); Assert.Throws(() => limiter.Acquire(-1)); } [Fact] public override async Task ThrowsWhenWaitingForLessThanZero() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); await Assert.ThrowsAsync(async () => await limiter.WaitAndAcquireAsync(-1)); } [Fact] public override void AcquireZero_WithAvailability() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); using var lease = limiter.Acquire(0); Assert.True(lease.IsAcquired); @@ -253,7 +338,12 @@ public override void AcquireZero_WithAvailability() [Fact] public override void AcquireZero_WithoutAvailability() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); using var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -265,7 +355,12 @@ public override void AcquireZero_WithoutAvailability() [Fact] public override async Task WaitAndAcquireAsyncZero_WithAvailability() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); using var lease = await limiter.WaitAndAcquireAsync(0); Assert.True(lease.IsAcquired); @@ -274,7 +369,12 @@ public override async Task WaitAndAcquireAsyncZero_WithAvailability() [Fact] public override async Task WaitAndAcquireAsyncZero_WithoutAvailabilityWaitsForAvailability() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); var lease = await limiter.WaitAndAcquireAsync(1); Assert.True(lease.IsAcquired); @@ -289,7 +389,12 @@ public override async Task WaitAndAcquireAsyncZero_WithoutAvailabilityWaitsForAv [Fact] public override async Task CanDequeueMultipleResourcesAtOnce() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(2, QueueProcessingOrder.OldestFirst, 2)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2 + }); using var lease = await limiter.WaitAndAcquireAsync(2); Assert.True(lease.IsAcquired); @@ -309,7 +414,12 @@ public override async Task CanDequeueMultipleResourcesAtOnce() [Fact] public override async Task CanAcquireResourcesWithWaitAndAcquireAsyncWithQueuedItemsIfNewestFirst() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(2, QueueProcessingOrder.NewestFirst, 3)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 3 + }); using var lease = await limiter.WaitAndAcquireAsync(1); Assert.True(lease.IsAcquired); @@ -331,7 +441,12 @@ public override async Task CanAcquireResourcesWithWaitAndAcquireAsyncWithQueuedI [Fact] public override async Task CannotAcquireResourcesWithWaitAndAcquireAsyncWithQueuedItemsIfOldestFirst() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(2, QueueProcessingOrder.OldestFirst, 3)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 3 + }); using var lease = await limiter.WaitAndAcquireAsync(1); Assert.True(lease.IsAcquired); @@ -354,7 +469,12 @@ public override async Task CannotAcquireResourcesWithWaitAndAcquireAsyncWithQueu [Fact] public override async Task CanAcquireResourcesWithAcquireWithQueuedItemsIfNewestFirst() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(2, QueueProcessingOrder.NewestFirst, 3)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 3 + }); using var lease = await limiter.WaitAndAcquireAsync(1); Assert.True(lease.IsAcquired); @@ -375,7 +495,12 @@ public override async Task CanAcquireResourcesWithAcquireWithQueuedItemsIfNewest [Fact] public override async Task CannotAcquireResourcesWithAcquireWithQueuedItemsIfOldestFirst() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(2, QueueProcessingOrder.OldestFirst, 3)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 3 + }); using var lease = await limiter.WaitAndAcquireAsync(1); Assert.True(lease.IsAcquired); @@ -393,7 +518,12 @@ public override async Task CannotAcquireResourcesWithAcquireWithQueuedItemsIfOld [Fact] public override async Task CanCancelWaitAndAcquireAsyncAfterQueuing() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1 + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -412,7 +542,12 @@ public override async Task CanCancelWaitAndAcquireAsyncAfterQueuing() [Fact] public override async Task CanCancelWaitAndAcquireAsyncBeforeQueuing() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1 + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -430,7 +565,12 @@ public override async Task CanCancelWaitAndAcquireAsyncBeforeQueuing() [Fact] public override async Task CancelUpdatesQueueLimit() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1 + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -452,7 +592,12 @@ public override async Task CancelUpdatesQueueLimit() [Fact] public override async Task CanFillQueueWithNewestFirstAfterCancelingQueuedRequestWithAnotherQueuedRequest() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(2, QueueProcessingOrder.NewestFirst, 2)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 2 + }); var lease = limiter.Acquire(2); Assert.True(lease.IsAcquired); @@ -483,7 +628,12 @@ public override async Task CanFillQueueWithNewestFirstAfterCancelingQueuedReques [Fact] public override async Task CanDisposeAfterCancelingQueuedRequest() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1 + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -501,7 +651,12 @@ public override async Task CanDisposeAfterCancelingQueuedRequest() [Fact] public override void NoMetadataOnAcquiredLease() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1 + }); using var lease = limiter.Acquire(1); Assert.False(lease.TryGetMetadata(MetadataName.ReasonPhrase.Name, out _)); } @@ -509,7 +664,12 @@ public override void NoMetadataOnAcquiredLease() [Fact] public override void MetadataNamesContainsAllMetadata() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1 + }); using var lease = limiter.Acquire(1); Assert.Collection(lease.MetadataNames, metadataName => Assert.Equal(metadataName, MetadataName.ReasonPhrase.Name)); } @@ -517,7 +677,12 @@ public override void MetadataNamesContainsAllMetadata() [Fact] public override async Task DisposeReleasesQueuedAcquires() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 3)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 3 + }); using var lease = limiter.Acquire(1); var wait1 = limiter.WaitAndAcquireAsync(1); @@ -546,7 +711,12 @@ public override async Task DisposeReleasesQueuedAcquires() [Fact] public override async Task DisposeAsyncReleasesQueuedAcquires() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 3)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 3 + }); using var lease = limiter.Acquire(1); var wait1 = limiter.WaitAndAcquireAsync(1); @@ -575,7 +745,12 @@ public override async Task DisposeAsyncReleasesQueuedAcquires() [Fact] public async Task ReasonMetadataOnFailedWaitAsync() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(2, QueueProcessingOrder.OldestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1 + }); using var lease = limiter.Acquire(2); var failedLease = await limiter.WaitAndAcquireAsync(2); @@ -591,7 +766,12 @@ public async Task ReasonMetadataOnFailedWaitAsync() [Fact] public override void NullIdleDurationWhenActive() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1 + }); using var lease = limiter.Acquire(1); Assert.Null(limiter.IdleDuration); } @@ -599,7 +779,12 @@ public override void NullIdleDurationWhenActive() [Fact] public override async Task IdleDurationUpdatesWhenIdle() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1 + }); Assert.NotNull(limiter.IdleDuration); var previousDuration = limiter.IdleDuration; await Task.Delay(15); @@ -609,7 +794,12 @@ public override async Task IdleDurationUpdatesWhenIdle() [Fact] public override void IdleDurationUpdatesWhenChangingFromActive() { - var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1)); + var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1 + }); var lease = limiter.Acquire(1); lease.Dispose(); Assert.NotNull(limiter.IdleDuration); diff --git a/src/libraries/System.Threading.RateLimiting/tests/FixedWindowRateLimiterTests.cs b/src/libraries/System.Threading.RateLimiting/tests/FixedWindowRateLimiterTests.cs index 0c0063a5aff031..0f4b6bf9e7b16e 100644 --- a/src/libraries/System.Threading.RateLimiting/tests/FixedWindowRateLimiterTests.cs +++ b/src/libraries/System.Threading.RateLimiting/tests/FixedWindowRateLimiterTests.cs @@ -12,8 +12,14 @@ public class FixedWindowRateLimiterTests : BaseRateLimiterTests [Fact] public override void CanAcquireResource() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(); Assert.True(lease.IsAcquired); @@ -29,17 +35,46 @@ public override void CanAcquireResource() [Fact] public override void InvalidOptionsThrows() { - Assert.Throws( - () => new FixedWindowRateLimiterOptions(-1, QueueProcessingOrder.NewestFirst, 1, TimeSpan.FromMinutes(2), autoReplenishment: false)); - Assert.Throws( - () => new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, -1, TimeSpan.FromMinutes(2), autoReplenishment: false)); + Assert.Throws( + () => new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = -1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.FromMinutes(2), + AutoReplenishment = false + })); + Assert.Throws( + () => new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = -1, + Window = TimeSpan.FromMinutes(2), + AutoReplenishment = false + })); + Assert.Throws( + () => new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.MinValue, + AutoReplenishment = false + })); } [Fact] public override async Task CanAcquireResourceAsync() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); using var lease = await limiter.WaitAndAcquireAsync(); @@ -55,8 +90,14 @@ public override async Task CanAcquireResourceAsync() [Fact] public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = await limiter.WaitAndAcquireAsync(); Assert.True(lease.IsAcquired); @@ -83,8 +124,14 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() [Fact] public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 3, - TimeSpan.FromMinutes(0), autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 3, + Window = TimeSpan.FromMinutes(0), + AutoReplenishment = false + }); var lease = await limiter.WaitAndAcquireAsync(2); Assert.True(lease.IsAcquired); @@ -113,8 +160,14 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() [Fact] public override async Task FailsWhenQueuingMoreThanLimit_OldestFirst() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); using var lease = limiter.Acquire(1); var wait = limiter.WaitAndAcquireAsync(1); @@ -127,8 +180,14 @@ public override async Task FailsWhenQueuingMoreThanLimit_OldestFirst() [Fact] public override async Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); var wait = limiter.WaitAndAcquireAsync(1); Assert.False(wait.IsCompleted); @@ -147,8 +206,14 @@ public override async Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst() [Fact] public override async Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFirst() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 2, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 2, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(2); Assert.True(lease.IsAcquired); var wait = limiter.WaitAndAcquireAsync(1); @@ -173,8 +238,14 @@ public override async Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFir [Fact] public override async Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimitAndNoAvailability_NewestFirst() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(2); Assert.True(lease.IsAcquired); @@ -194,8 +265,14 @@ public override async Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimit [Fact] public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAvailable() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); var wait = limiter.WaitAndAcquireAsync(1); @@ -217,8 +294,14 @@ public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAv [Fact] public override async Task LargeAcquiresAndQueuesDoNotIntegerOverflow() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(int.MaxValue, QueueProcessingOrder.NewestFirst, int.MaxValue, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = int.MaxValue, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = int.MaxValue, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(int.MaxValue); Assert.True(lease.IsAcquired); @@ -240,40 +323,70 @@ public override async Task LargeAcquiresAndQueuesDoNotIntegerOverflow() [Fact] public override void ThrowsWhenAcquiringMoreThanLimit() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); Assert.Throws(() => limiter.Acquire(2)); } [Fact] public override async Task ThrowsWhenWaitingForMoreThanLimit() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); await Assert.ThrowsAsync(async () => await limiter.WaitAndAcquireAsync(2)); } [Fact] public override void ThrowsWhenAcquiringLessThanZero() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); Assert.Throws(() => limiter.Acquire(-1)); } [Fact] public override async Task ThrowsWhenWaitingForLessThanZero() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); await Assert.ThrowsAsync(async () => await limiter.WaitAndAcquireAsync(-1)); } [Fact] public override void AcquireZero_WithAvailability() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); using var lease = limiter.Acquire(0); Assert.True(lease.IsAcquired); @@ -282,8 +395,14 @@ public override void AcquireZero_WithAvailability() [Fact] public override void AcquireZero_WithoutAvailability() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); using var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -295,8 +414,14 @@ public override void AcquireZero_WithoutAvailability() [Fact] public override async Task WaitAndAcquireAsyncZero_WithAvailability() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); using var lease = await limiter.WaitAndAcquireAsync(0); Assert.True(lease.IsAcquired); @@ -305,8 +430,14 @@ public override async Task WaitAndAcquireAsyncZero_WithAvailability() [Fact] public override async Task WaitAndAcquireAsyncZero_WithoutAvailabilityWaitsForAvailability() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = await limiter.WaitAndAcquireAsync(1); Assert.True(lease.IsAcquired); @@ -322,8 +453,14 @@ public override async Task WaitAndAcquireAsyncZero_WithoutAvailabilityWaitsForAv [Fact] public override async Task CanDequeueMultipleResourcesAtOnce() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 2, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); using var lease = await limiter.WaitAndAcquireAsync(2); Assert.True(lease.IsAcquired); @@ -344,8 +481,14 @@ public override async Task CanDequeueMultipleResourcesAtOnce() [Fact] public override async Task CanCancelWaitAndAcquireAsyncAfterQueuing() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -365,8 +508,14 @@ public override async Task CanCancelWaitAndAcquireAsyncAfterQueuing() [Fact] public override async Task CanCancelWaitAndAcquireAsyncBeforeQueuing() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -385,8 +534,14 @@ public override async Task CanCancelWaitAndAcquireAsyncBeforeQueuing() [Fact] public override async Task CancelUpdatesQueueLimit() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -408,8 +563,14 @@ public override async Task CancelUpdatesQueueLimit() [Fact] public override void NoMetadataOnAcquiredLease() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); using var lease = limiter.Acquire(1); Assert.False(lease.TryGetMetadata(MetadataName.RetryAfter, out _)); } @@ -417,8 +578,14 @@ public override void NoMetadataOnAcquiredLease() [Fact] public override void MetadataNamesContainsAllMetadata() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); using var lease = limiter.Acquire(1); Assert.Collection(lease.MetadataNames, metadataName => Assert.Equal(metadataName, MetadataName.RetryAfter.Name)); } @@ -426,8 +593,14 @@ public override void MetadataNamesContainsAllMetadata() [Fact] public override async Task DisposeReleasesQueuedAcquires() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 3, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 3, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); var wait1 = limiter.WaitAndAcquireAsync(1); var wait2 = limiter.WaitAndAcquireAsync(1); @@ -453,8 +626,14 @@ public override async Task DisposeReleasesQueuedAcquires() [Fact] public override async Task DisposeAsyncReleasesQueuedAcquires() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 3, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 3, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); var wait1 = limiter.WaitAndAcquireAsync(1); var wait2 = limiter.WaitAndAcquireAsync(1); @@ -480,8 +659,14 @@ public override async Task DisposeAsyncReleasesQueuedAcquires() [Fact] public async Task RetryMetadataOnFailedWaitAsync() { - var options = new FixedWindowRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.FromSeconds(20), autoReplenishment: false); + var options = new FixedWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.FromSeconds(20), + AutoReplenishment = false + }; var limiter = new FixedWindowRateLimiter(options); using var lease = limiter.Acquire(2); @@ -500,8 +685,14 @@ public async Task RetryMetadataOnFailedWaitAsync() [Fact] public async Task CorrectRetryMetadataWithQueuedItem() { - var options = new FixedWindowRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.FromSeconds(20), autoReplenishment: false); + var options = new FixedWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.FromSeconds(20), + AutoReplenishment = false + }; var limiter = new FixedWindowRateLimiter(options); using var lease = limiter.Acquire(2); @@ -519,8 +710,14 @@ public async Task CorrectRetryMetadataWithQueuedItem() [Fact] public async Task CorrectRetryMetadataWithNonZeroAvailableItems() { - var options = new FixedWindowRateLimiterOptions(3, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.FromSeconds(20), autoReplenishment: false); + var options = new FixedWindowRateLimiterOptions + { + PermitLimit = 3, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.FromSeconds(20), + AutoReplenishment = false + }; var limiter = new FixedWindowRateLimiter(options); using var lease = limiter.Acquire(2); @@ -534,8 +731,14 @@ public async Task CorrectRetryMetadataWithNonZeroAvailableItems() [Fact] public void TryReplenishWithAutoReplenish_ReturnsFalse() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.FromSeconds(1), autoReplenishment: true)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.FromSeconds(1), + AutoReplenishment = true + }); Assert.Equal(2, limiter.GetAvailablePermits()); Assert.False(limiter.TryReplenish()); Assert.Equal(2, limiter.GetAvailablePermits()); @@ -544,8 +747,14 @@ public void TryReplenishWithAutoReplenish_ReturnsFalse() [Fact] public async Task AutoReplenish_ReplenishesCounters() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.FromMilliseconds(1000), autoReplenishment: true)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.FromMilliseconds(1000), + AutoReplenishment = true + }); Assert.Equal(2, limiter.GetAvailablePermits()); limiter.Acquire(2); @@ -556,8 +765,14 @@ public async Task AutoReplenish_ReplenishesCounters() [Fact] public override async Task CanAcquireResourcesWithWaitAndAcquireAsyncWithQueuedItemsIfNewestFirst() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 2, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 2, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -579,8 +794,14 @@ public override async Task CanAcquireResourcesWithWaitAndAcquireAsyncWithQueuedI [Fact] public override async Task CannotAcquireResourcesWithWaitAndAcquireAsyncWithQueuedItemsIfOldestFirst() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 3, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 3, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -605,8 +826,14 @@ public override async Task CannotAcquireResourcesWithWaitAndAcquireAsyncWithQueu [Fact] public override async Task CanAcquireResourcesWithAcquireWithQueuedItemsIfNewestFirst() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 3, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 3, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -627,8 +854,14 @@ public override async Task CanAcquireResourcesWithAcquireWithQueuedItemsIfNewest [Fact] public override async Task CannotAcquireResourcesWithAcquireWithQueuedItemsIfOldestFirst() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 3, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 3, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -648,8 +881,14 @@ public override async Task CannotAcquireResourcesWithAcquireWithQueuedItemsIfOld [Fact] public override void NullIdleDurationWhenActive() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2, - TimeSpan.FromMilliseconds(2), autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + Window = TimeSpan.FromMilliseconds(2), + AutoReplenishment = false + }); limiter.Acquire(1); Assert.Null(limiter.IdleDuration); } @@ -657,8 +896,14 @@ public override void NullIdleDurationWhenActive() [Fact] public override async Task IdleDurationUpdatesWhenIdle() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2, - TimeSpan.FromMilliseconds(2), autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + Window = TimeSpan.FromMilliseconds(2), + AutoReplenishment = false + }); Assert.NotNull(limiter.IdleDuration); var previousDuration = limiter.IdleDuration; await Task.Delay(15); @@ -668,8 +913,14 @@ public override async Task IdleDurationUpdatesWhenIdle() [Fact] public override void IdleDurationUpdatesWhenChangingFromActive() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); limiter.Acquire(1); limiter.TryReplenish(); Assert.NotNull(limiter.IdleDuration); @@ -679,14 +930,26 @@ public override void IdleDurationUpdatesWhenChangingFromActive() public void ReplenishingRateLimiterPropertiesHaveCorrectValues() { var replenishPeriod = TimeSpan.FromMinutes(1); - using ReplenishingRateLimiter limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2, - replenishPeriod, autoReplenishment: true)); + using ReplenishingRateLimiter limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + Window = replenishPeriod, + AutoReplenishment = true + }); Assert.True(limiter.IsAutoReplenishing); Assert.Equal(replenishPeriod, limiter.ReplenishmentPeriod); replenishPeriod = TimeSpan.FromSeconds(2); - using ReplenishingRateLimiter limiter2 = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2, - replenishPeriod, autoReplenishment: false)); + using ReplenishingRateLimiter limiter2 = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + Window = replenishPeriod, + AutoReplenishment = false + }); Assert.False(limiter2.IsAutoReplenishing); Assert.Equal(replenishPeriod, limiter2.ReplenishmentPeriod); } @@ -694,8 +957,14 @@ public void ReplenishingRateLimiterPropertiesHaveCorrectValues() [Fact] public override async Task CanFillQueueWithNewestFirstAfterCancelingQueuedRequestWithAnotherQueuedRequest() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 2, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 2, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(2); Assert.True(lease.IsAcquired); @@ -727,8 +996,14 @@ public override async Task CanFillQueueWithNewestFirstAfterCancelingQueuedReques [Fact] public override async Task CanDisposeAfterCancelingQueuedRequest() { - var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, autoReplenishment: false)); + var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); diff --git a/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs b/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs index 1c8604443516dc..4c97b03c65d59a 100644 --- a/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs +++ b/src/libraries/System.Threading.RateLimiting/tests/PartitionedRateLimiterTests.cs @@ -133,7 +133,12 @@ public async Task Create_BlockingWaitDoesNotBlockOtherPartitions() return RateLimitPartition.Get(1, key => limiterFactory.GetLimiter(key)); } return RateLimitPartition.GetConcurrencyLimiter(2, - _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2)); + _ => new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2 + }); }); var lease = await limiter.WaitAndAcquireAsync("2"); @@ -370,7 +375,15 @@ public async Task Create_WithTokenBucketReplenishesAutomatically() using var limiter = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.GetTokenBucketLimiter(1, - _ => new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, TimeSpan.FromMilliseconds(100), 1, false)); + _ => new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(100), + TokensPerPeriod = 1, + AutoReplenishment = false + }); }); var lease = limiter.Acquire(""); @@ -387,7 +400,15 @@ public async Task Create_WithReplenishingLimiterReplenishesAutomatically() { // Use the non-specific Create method to make sure ReplenishingRateLimiters are still handled properly return RateLimitPartition.Get(1, - _ => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, TimeSpan.FromMilliseconds(100), 1, false))); + _ => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(100), + TokensPerPeriod = 1, + AutoReplenishment = false + })); }); var lease = limiter.Acquire(""); @@ -405,10 +426,26 @@ public async Task Create_MultipleReplenishingLimitersReplenishAutomatically() if (resource == "1") { return RateLimitPartition.GetTokenBucketLimiter(1, - _ => new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, TimeSpan.FromMilliseconds(100), 1, false)); + _ => new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(100), + TokensPerPeriod = 1, + AutoReplenishment = false + }); } return RateLimitPartition.GetTokenBucketLimiter(2, - _ => new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, TimeSpan.FromMilliseconds(100), 1, false)); + _ => new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(100), + TokensPerPeriod = 1, + AutoReplenishment = false + }); }); var lease = limiter.Acquire("1"); @@ -434,7 +471,12 @@ public async Task Create_CancellationTokenPassedToUnderlyingLimiter() using var limiter = PartitionedRateLimiter.Create(resource => { return RateLimitPartition.GetConcurrencyLimiter(1, - _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + _ => new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); }); var lease = limiter.Acquire(""); @@ -606,12 +648,22 @@ public void Translate_AcquirePassesThroughToInnerLimiter() if (resource == "1") { return RateLimitPartition.GetConcurrencyLimiter(1, - _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + _ => new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); } else { return RateLimitPartition.GetConcurrencyLimiter(1, - _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + _ => new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); } }); @@ -645,12 +697,22 @@ public async Task Translate_WaitAsyncPassesThroughToInnerLimiter() if (resource == "1") { return RateLimitPartition.GetConcurrencyLimiter(1, - _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + _ => new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); } else { return RateLimitPartition.GetConcurrencyLimiter(1, - _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + _ => new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); } }); @@ -684,12 +746,22 @@ public void Translate_GetAvailablePermitsPassesThroughToInnerLimiter() if (resource == "1") { return RateLimitPartition.GetConcurrencyLimiter(1, - _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + _ => new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); } else { return RateLimitPartition.GetConcurrencyLimiter(1, - _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + _ => new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); } }); @@ -732,12 +804,22 @@ public void Translate_DisposeDoesNotDisposeInnerLimiter() if (resource == "1") { return RateLimitPartition.GetConcurrencyLimiter(1, - _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + _ => new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); } else { return RateLimitPartition.GetConcurrencyLimiter(1, - _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + _ => new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); } }); @@ -764,12 +846,22 @@ public async Task Translate_DisposeAsyncDoesNotDisposeInnerLimiter() if (resource == "1") { return RateLimitPartition.GetConcurrencyLimiter(1, - _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + _ => new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); } else { return RateLimitPartition.GetConcurrencyLimiter(1, - _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1)); + _ => new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1 + }); } }); diff --git a/src/libraries/System.Threading.RateLimiting/tests/RateLimiterPartitionTests.cs b/src/libraries/System.Threading.RateLimiting/tests/RateLimiterPartitionTests.cs index 4987ab3186bedd..be797b1feba498 100644 --- a/src/libraries/System.Threading.RateLimiting/tests/RateLimiterPartitionTests.cs +++ b/src/libraries/System.Threading.RateLimiting/tests/RateLimiterPartitionTests.cs @@ -11,7 +11,12 @@ public class RateLimiterPartitionTests [Fact] public void Create_Concurrency() { - var options = new ConcurrencyLimiterOptions(10, QueueProcessingOrder.OldestFirst, 10); + var options = new ConcurrencyLimiterOptions + { + PermitLimit = 10, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 10 + }; var partition = RateLimitPartition.GetConcurrencyLimiter(1, key => options); var limiter = partition.Factory(1); @@ -22,7 +27,15 @@ public void Create_Concurrency() [Fact] public void Create_TokenBucket() { - var options = new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 10, TimeSpan.FromMinutes(1), 1, true); + var options = new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 10, + ReplenishmentPeriod = TimeSpan.FromMinutes(1), + TokensPerPeriod = 1, + AutoReplenishment = true + }; var partition = RateLimitPartition.GetTokenBucketLimiter(1, key => options); var limiter = partition.Factory(1); @@ -59,13 +72,26 @@ public async Task Create_NoLimiter() [Fact] public void Create_AnyLimiter() { - var partition = RateLimitPartition.Get(1, key => new ConcurrencyLimiter(new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 10))); + var partition = RateLimitPartition.Get(1, key => new ConcurrencyLimiter(new ConcurrencyLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 10 + })); var limiter = partition.Factory(1); var concurrencyLimiter = Assert.IsType(limiter); Assert.Equal(1, concurrencyLimiter.GetAvailablePermits()); - var partition2 = RateLimitPartition.Get(1, key => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 10, TimeSpan.FromMilliseconds(100), 1, autoReplenishment: false))); + var partition2 = RateLimitPartition.Get(1, key => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 10, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(100), + TokensPerPeriod = 1, + AutoReplenishment = false + })); limiter = partition2.Factory(1); var tokenBucketLimiter = Assert.IsType(limiter); Assert.Equal(1, tokenBucketLimiter.GetAvailablePermits()); @@ -74,7 +100,14 @@ public void Create_AnyLimiter() [Fact] public void Create_FixedWindow() { - var options = new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 10, TimeSpan.FromMinutes(1), true); + var options = new FixedWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 10, + Window = TimeSpan.FromMinutes(1), + AutoReplenishment = true + }; var partition = RateLimitPartition.GetFixedWindowLimiter(1, key => options); var limiter = partition.Factory(1); @@ -87,7 +120,15 @@ public void Create_FixedWindow() [Fact] public void Create_SlidingWindow() { - var options = new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 10, TimeSpan.FromSeconds(33), 3, true); + var options = new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 10, + Window = TimeSpan.FromSeconds(33), + SegmentsPerWindow = 3, + AutoReplenishment = true + }; var partition = RateLimitPartition.GetSlidingWindowLimiter(1, key => options); var limiter = partition.Factory(1); diff --git a/src/libraries/System.Threading.RateLimiting/tests/SlidingWindowRateLimiterTests.cs b/src/libraries/System.Threading.RateLimiting/tests/SlidingWindowRateLimiterTests.cs index ff838e9a44e863..a582cc07d4d053 100644 --- a/src/libraries/System.Threading.RateLimiting/tests/SlidingWindowRateLimiterTests.cs +++ b/src/libraries/System.Threading.RateLimiting/tests/SlidingWindowRateLimiterTests.cs @@ -12,8 +12,15 @@ public class SlidingWindowRateLimiterTests : BaseRateLimiterTests [Fact] public override void CanAcquireResource() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(); Assert.True(lease.IsAcquired); @@ -30,19 +37,60 @@ public override void CanAcquireResource() [Fact] public override void InvalidOptionsThrows() { - Assert.Throws( - () => new SlidingWindowRateLimiterOptions(-1, QueueProcessingOrder.NewestFirst, 1, TimeSpan.FromMinutes(2), 1, autoReplenishment: false)); - Assert.Throws( - () => new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, -1, TimeSpan.FromMinutes(2), 1, autoReplenishment: false)); - Assert.Throws( - () => new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, TimeSpan.FromMinutes(2), -1, autoReplenishment: false)); + Assert.Throws( + () => new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = -1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.FromMinutes(2), + SegmentsPerWindow = 1, + AutoReplenishment = false + })); + Assert.Throws( + () => new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = -1, + Window = TimeSpan.FromMinutes(2), + SegmentsPerWindow = 1, + AutoReplenishment = false + })); + Assert.Throws( + () => new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.FromMinutes(2), + SegmentsPerWindow = -1, + AutoReplenishment = false + })); + Assert.Throws( + () => new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.MinValue, + SegmentsPerWindow = 1, + AutoReplenishment = false + })); } [Fact] public override async Task CanAcquireResourceAsync() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 4, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 4, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); using var lease = await limiter.WaitAndAcquireAsync(); @@ -68,8 +116,15 @@ public async Task CanAcquireMultipleRequestsAsync() // This test verifies the following behavior // 1. when we have available permits after replenish to serve the queued requests // 2. when the oldest item from queue is remove to accommodate new requests (QueueProcessingOrder: NewestFirst) - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(4, QueueProcessingOrder.NewestFirst, 4, - TimeSpan.Zero, 3, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 4, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 4, + Window = TimeSpan.Zero, + SegmentsPerWindow = 3, + AutoReplenishment = false + }); using var lease = await limiter.WaitAndAcquireAsync(2); @@ -99,8 +154,15 @@ public async Task CanAcquireMultipleRequestsAsync() [Fact] public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 3, - TimeSpan.FromMinutes(0), 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 3, + Window = TimeSpan.FromMinutes(0), + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = await limiter.WaitAndAcquireAsync(2); Assert.True(lease.IsAcquired); @@ -131,8 +193,15 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() [Fact] public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 3, - TimeSpan.FromMinutes(0), 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 3, + Window = TimeSpan.FromMinutes(0), + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = await limiter.WaitAndAcquireAsync(2); Assert.True(lease.IsAcquired); @@ -164,8 +233,15 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() [Fact] public override async Task FailsWhenQueuingMoreThanLimit_OldestFirst() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); using var lease = limiter.Acquire(1); var wait = limiter.WaitAndAcquireAsync(1); @@ -176,8 +252,15 @@ public override async Task FailsWhenQueuingMoreThanLimit_OldestFirst() [Fact] public override async Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); var wait = limiter.WaitAndAcquireAsync(1); Assert.False(wait.IsCompleted); @@ -197,8 +280,15 @@ public override async Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst() [Fact] public override async Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFirst() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 2, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 2, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(2); Assert.True(lease.IsAcquired); var wait = limiter.WaitAndAcquireAsync(1); @@ -224,8 +314,15 @@ public override async Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFir [Fact] public override async Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimitAndNoAvailability_NewestFirst() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(2); Assert.True(lease.IsAcquired); @@ -246,8 +343,15 @@ public override async Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimit [Fact] public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAvailable() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(3, QueueProcessingOrder.OldestFirst, 2, - TimeSpan.Zero, 3, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 3, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + Window = TimeSpan.Zero, + SegmentsPerWindow = 3, + AutoReplenishment = false + }); var lease = limiter.Acquire(2); var wait = limiter.WaitAndAcquireAsync(2); @@ -276,8 +380,15 @@ public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAv [Fact] public override async Task LargeAcquiresAndQueuesDoNotIntegerOverflow() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(int.MaxValue, QueueProcessingOrder.NewestFirst, int.MaxValue, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = int.MaxValue, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = int.MaxValue, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(int.MaxValue); Assert.True(lease.IsAcquired); @@ -300,40 +411,75 @@ public override async Task LargeAcquiresAndQueuesDoNotIntegerOverflow() [Fact] public override void ThrowsWhenAcquiringMoreThanLimit() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 1, + AutoReplenishment = false + }); Assert.Throws(() => limiter.Acquire(2)); } [Fact] public override async Task ThrowsWhenWaitingForMoreThanLimit() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 1, + AutoReplenishment = false + }); await Assert.ThrowsAsync(async () => await limiter.WaitAndAcquireAsync(2)); } [Fact] public override void ThrowsWhenAcquiringLessThanZero() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 1, + AutoReplenishment = false + }); Assert.Throws(() => limiter.Acquire(-1)); } [Fact] public override async Task ThrowsWhenWaitingForLessThanZero() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 1, + AutoReplenishment = false + }); await Assert.ThrowsAsync(async () => await limiter.WaitAndAcquireAsync(-1)); } [Fact] public override void AcquireZero_WithAvailability() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 1, + AutoReplenishment = false + }); using var lease = limiter.Acquire(0); Assert.True(lease.IsAcquired); @@ -342,8 +488,15 @@ public override void AcquireZero_WithAvailability() [Fact] public override void AcquireZero_WithoutAvailability() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 1, + AutoReplenishment = false + }); using var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -355,8 +508,15 @@ public override void AcquireZero_WithoutAvailability() [Fact] public override async Task WaitAndAcquireAsyncZero_WithAvailability() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 1, + AutoReplenishment = false + }); using var lease = await limiter.WaitAndAcquireAsync(0); Assert.True(lease.IsAcquired); @@ -365,8 +525,15 @@ public override async Task WaitAndAcquireAsyncZero_WithAvailability() [Fact] public override async Task WaitAndAcquireAsyncZero_WithoutAvailabilityWaitsForAvailability() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = await limiter.WaitAndAcquireAsync(1); Assert.True(lease.IsAcquired); @@ -383,8 +550,15 @@ public override async Task WaitAndAcquireAsyncZero_WithoutAvailabilityWaitsForAv [Fact] public override async Task CanDequeueMultipleResourcesAtOnce() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 4, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 4, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); using var lease = await limiter.WaitAndAcquireAsync(2); Assert.True(lease.IsAcquired); @@ -406,8 +580,15 @@ public override async Task CanDequeueMultipleResourcesAtOnce() [Fact] public override async Task CanCancelWaitAndAcquireAsyncAfterQueuing() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(2); Assert.True(lease.IsAcquired); @@ -427,8 +608,15 @@ public override async Task CanCancelWaitAndAcquireAsyncAfterQueuing() [Fact] public override async Task CanCancelWaitAndAcquireAsyncBeforeQueuing() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(2); Assert.True(lease.IsAcquired); @@ -447,8 +635,15 @@ public override async Task CanCancelWaitAndAcquireAsyncBeforeQueuing() [Fact] public override async Task CancelUpdatesQueueLimit() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(2); Assert.True(lease.IsAcquired); @@ -473,8 +668,15 @@ public override async Task CancelUpdatesQueueLimit() [Fact] public override void NoMetadataOnAcquiredLease() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); using var lease = limiter.Acquire(1); Assert.False(lease.TryGetMetadata(MetadataName.RetryAfter, out _)); } @@ -482,8 +684,15 @@ public override void NoMetadataOnAcquiredLease() [Fact] public override void MetadataNamesContainsAllMetadata() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 1, + AutoReplenishment = false + }); using var lease = limiter.Acquire(1); Assert.Collection(lease.MetadataNames, metadataName => Assert.Equal(metadataName, MetadataName.RetryAfter.Name)); } @@ -491,8 +700,15 @@ public override void MetadataNamesContainsAllMetadata() [Fact] public override async Task DisposeReleasesQueuedAcquires() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 3, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 3, + Window = TimeSpan.Zero, + SegmentsPerWindow = 1, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); var wait1 = limiter.WaitAndAcquireAsync(1); var wait2 = limiter.WaitAndAcquireAsync(1); @@ -518,8 +734,15 @@ public override async Task DisposeReleasesQueuedAcquires() [Fact] public override async Task DisposeAsyncReleasesQueuedAcquires() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 3, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 3, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); var wait1 = limiter.WaitAndAcquireAsync(1); var wait2 = limiter.WaitAndAcquireAsync(1); @@ -545,8 +768,15 @@ public override async Task DisposeAsyncReleasesQueuedAcquires() [Fact] public void TryReplenishWithAutoReplenish_ReturnsFalse() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.FromSeconds(1), 1, autoReplenishment: true)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.FromSeconds(1), + SegmentsPerWindow = 1, + AutoReplenishment = true + }); Assert.Equal(2, limiter.GetAvailablePermits()); Assert.False(limiter.TryReplenish()); Assert.Equal(2, limiter.GetAvailablePermits()); @@ -555,8 +785,15 @@ public void TryReplenishWithAutoReplenish_ReturnsFalse() [Fact] public async Task AutoReplenish_ReplenishesCounters() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.FromMilliseconds(1000), 2, autoReplenishment: true)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.FromMilliseconds(1000), + SegmentsPerWindow = 2, + AutoReplenishment = true + }); Assert.Equal(2, limiter.GetAvailablePermits()); limiter.Acquire(2); @@ -567,8 +804,15 @@ public async Task AutoReplenish_ReplenishesCounters() [Fact] public override async Task CanAcquireResourcesWithWaitAndAcquireAsyncWithQueuedItemsIfNewestFirst() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 2, - TimeSpan.Zero, 3, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 2, + Window = TimeSpan.Zero, + SegmentsPerWindow = 3, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -594,8 +838,15 @@ public override async Task CanAcquireResourcesWithWaitAndAcquireAsyncWithQueuedI [Fact] public override async Task CannotAcquireResourcesWithWaitAndAcquireAsyncWithQueuedItemsIfOldestFirst() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(3, QueueProcessingOrder.OldestFirst, 5, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 3, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 5, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(3); Assert.True(lease.IsAcquired); @@ -625,8 +876,15 @@ public override async Task CannotAcquireResourcesWithWaitAndAcquireAsyncWithQueu [Fact] public override async Task CanAcquireResourcesWithAcquireWithQueuedItemsIfNewestFirst() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 3, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 3, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -648,8 +906,15 @@ public override async Task CanAcquireResourcesWithAcquireWithQueuedItemsIfNewest [Fact] public override async Task CannotAcquireResourcesWithAcquireWithQueuedItemsIfOldestFirst() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 3, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 3, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -670,8 +935,15 @@ public override async Task CannotAcquireResourcesWithAcquireWithQueuedItemsIfOld [Fact] public override void NullIdleDurationWhenActive() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2, - TimeSpan.FromMilliseconds(2), 1, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + Window = TimeSpan.FromMilliseconds(2), + SegmentsPerWindow = 1, + AutoReplenishment = false + }); limiter.Acquire(1); Assert.Null(limiter.IdleDuration); } @@ -679,8 +951,15 @@ public override void NullIdleDurationWhenActive() [Fact] public override async Task IdleDurationUpdatesWhenIdle() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(3, QueueProcessingOrder.OldestFirst, 2, - TimeSpan.FromMilliseconds(2), 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 3, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + Window = TimeSpan.FromMilliseconds(2), + SegmentsPerWindow = 2, + AutoReplenishment = false + }); Assert.NotNull(limiter.IdleDuration); var previousDuration = limiter.IdleDuration; await Task.Delay(15); @@ -690,8 +969,15 @@ public override async Task IdleDurationUpdatesWhenIdle() [Fact] public override void IdleDurationUpdatesWhenChangingFromActive() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); limiter.Acquire(1); limiter.TryReplenish(); limiter.TryReplenish(); @@ -702,14 +988,28 @@ public override void IdleDurationUpdatesWhenChangingFromActive() public void ReplenishingRateLimiterPropertiesHaveCorrectValues() { var replenishPeriod = TimeSpan.FromMinutes(1); - using ReplenishingRateLimiter limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2, - replenishPeriod, 1, autoReplenishment: true)); + using ReplenishingRateLimiter limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + Window = replenishPeriod, + SegmentsPerWindow = 1, + AutoReplenishment = true + }); Assert.True(limiter.IsAutoReplenishing); Assert.Equal(replenishPeriod, limiter.ReplenishmentPeriod); replenishPeriod = TimeSpan.FromSeconds(2); - using ReplenishingRateLimiter limiter2 = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2, - replenishPeriod, 1, autoReplenishment: false)); + using ReplenishingRateLimiter limiter2 = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + Window = replenishPeriod, + SegmentsPerWindow = 1, + AutoReplenishment = false + }); Assert.False(limiter2.IsAutoReplenishing); Assert.Equal(replenishPeriod, limiter2.ReplenishmentPeriod); } @@ -717,8 +1017,15 @@ public void ReplenishingRateLimiterPropertiesHaveCorrectValues() [Fact] public override async Task CanFillQueueWithNewestFirstAfterCancelingQueuedRequestWithAnotherQueuedRequest() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 2, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 2, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(2); Assert.True(lease.IsAcquired); @@ -751,8 +1058,15 @@ public override async Task CanFillQueueWithNewestFirstAfterCancelingQueuedReques [Fact] public override async Task CanDisposeAfterCancelingQueuedRequest() { - var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions + { + PermitLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + Window = TimeSpan.Zero, + SegmentsPerWindow = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); diff --git a/src/libraries/System.Threading.RateLimiting/tests/TokenBucketRateLimiterTests.cs b/src/libraries/System.Threading.RateLimiting/tests/TokenBucketRateLimiterTests.cs index 14232bf61eee94..9bfeac0ab2e9eb 100644 --- a/src/libraries/System.Threading.RateLimiting/tests/TokenBucketRateLimiterTests.cs +++ b/src/libraries/System.Threading.RateLimiting/tests/TokenBucketRateLimiterTests.cs @@ -12,8 +12,15 @@ public class TokenBucketRateLimiterTests : BaseRateLimiterTests [Fact] public override void CanAcquireResource() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); var lease = limiter.Acquire(); Assert.True(lease.IsAcquired); @@ -29,19 +36,60 @@ public override void CanAcquireResource() [Fact] public override void InvalidOptionsThrows() { - Assert.Throws( - () => new TokenBucketRateLimiterOptions(-1, QueueProcessingOrder.NewestFirst, 1, TimeSpan.FromMinutes(2), 1, autoReplenishment: false)); - Assert.Throws( - () => new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, -1, TimeSpan.FromMinutes(2), 1, autoReplenishment: false)); - Assert.Throws( - () => new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, TimeSpan.FromMinutes(2), -1, autoReplenishment: false)); + Assert.Throws( + () => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = -1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.FromMinutes(2), + TokensPerPeriod = 1, + AutoReplenishment = false + })); + Assert.Throws( + () => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = -1, + ReplenishmentPeriod = TimeSpan.FromMinutes(2), + TokensPerPeriod = 1, + AutoReplenishment = false + })); + Assert.Throws( + () => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.FromMinutes(2), + TokensPerPeriod = -1, + AutoReplenishment = false + })); + Assert.Throws( + () => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.MinValue, + TokensPerPeriod = 1, + AutoReplenishment = false + })); } [Fact] public override async Task CanAcquireResourceAsync() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); using var lease = await limiter.WaitAndAcquireAsync(); @@ -57,8 +105,15 @@ public override async Task CanAcquireResourceAsync() [Fact] public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); var lease = await limiter.WaitAndAcquireAsync(); Assert.True(lease.IsAcquired); @@ -85,8 +140,15 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsOldest() [Fact] public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 3, - TimeSpan.FromMinutes(0), 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 3, + ReplenishmentPeriod = TimeSpan.FromMinutes(0), + TokensPerPeriod = 1, + AutoReplenishment = false + }); var lease = await limiter.WaitAndAcquireAsync(2); Assert.True(lease.IsAcquired); @@ -116,8 +178,15 @@ public override async Task CanAcquireResourceAsync_QueuesAndGrabsNewest() [Fact] public override async Task FailsWhenQueuingMoreThanLimit_OldestFirst() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); using var lease = limiter.Acquire(1); var wait = limiter.WaitAndAcquireAsync(1); @@ -130,8 +199,15 @@ public override async Task FailsWhenQueuingMoreThanLimit_OldestFirst() [Fact] public override async Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); var wait = limiter.WaitAndAcquireAsync(1); Assert.False(wait.IsCompleted); @@ -150,8 +226,15 @@ public override async Task DropsOldestWhenQueuingMoreThanLimit_NewestFirst() [Fact] public override async Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFirst() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 2, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 2, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); var lease = limiter.Acquire(2); Assert.True(lease.IsAcquired); var wait = limiter.WaitAndAcquireAsync(1); @@ -177,8 +260,15 @@ public override async Task DropsMultipleOldestWhenQueuingMoreThanLimit_NewestFir [Fact] public override async Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimitAndNoAvailability_NewestFirst() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); var lease = limiter.Acquire(2); Assert.True(lease.IsAcquired); @@ -198,8 +288,15 @@ public override async Task DropsRequestedLeaseIfPermitCountGreaterThanQueueLimit [Fact] public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAvailable() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); var wait = limiter.WaitAndAcquireAsync(1); @@ -221,8 +318,15 @@ public override async Task QueueAvailableAfterQueueLimitHitAndResources_BecomeAv [Fact] public override async Task LargeAcquiresAndQueuesDoNotIntegerOverflow() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(int.MaxValue, QueueProcessingOrder.NewestFirst, int.MaxValue, - TimeSpan.Zero, int.MaxValue, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = int.MaxValue, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = int.MaxValue, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = int.MaxValue, + AutoReplenishment = false + }); var lease = limiter.Acquire(int.MaxValue); Assert.True(lease.IsAcquired); @@ -244,40 +348,75 @@ public override async Task LargeAcquiresAndQueuesDoNotIntegerOverflow() [Fact] public override void ThrowsWhenAcquiringMoreThanLimit() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); Assert.Throws(() => limiter.Acquire(2)); } [Fact] public override async Task ThrowsWhenWaitingForMoreThanLimit() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); await Assert.ThrowsAsync(async () => await limiter.WaitAndAcquireAsync(2)); } [Fact] public override void ThrowsWhenAcquiringLessThanZero() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); Assert.Throws(() => limiter.Acquire(-1)); } [Fact] public override async Task ThrowsWhenWaitingForLessThanZero() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); await Assert.ThrowsAsync(async () => await limiter.WaitAndAcquireAsync(-1)); } [Fact] public override void AcquireZero_WithAvailability() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); using var lease = limiter.Acquire(0); Assert.True(lease.IsAcquired); @@ -286,8 +425,15 @@ public override void AcquireZero_WithAvailability() [Fact] public override void AcquireZero_WithoutAvailability() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); using var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -299,8 +445,15 @@ public override void AcquireZero_WithoutAvailability() [Fact] public override async Task WaitAndAcquireAsyncZero_WithAvailability() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); using var lease = await limiter.WaitAndAcquireAsync(0); Assert.True(lease.IsAcquired); @@ -309,8 +462,15 @@ public override async Task WaitAndAcquireAsyncZero_WithAvailability() [Fact] public override async Task WaitAndAcquireAsyncZero_WithoutAvailabilityWaitsForAvailability() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); var lease = await limiter.WaitAndAcquireAsync(1); Assert.True(lease.IsAcquired); @@ -326,8 +486,15 @@ public override async Task WaitAndAcquireAsyncZero_WithoutAvailabilityWaitsForAv [Fact] public override async Task CanDequeueMultipleResourcesAtOnce() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 2, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 2, + AutoReplenishment = false + }); using var lease = await limiter.WaitAndAcquireAsync(2); Assert.True(lease.IsAcquired); @@ -348,8 +515,15 @@ public override async Task CanDequeueMultipleResourcesAtOnce() [Fact] public override async Task CanCancelWaitAndAcquireAsyncAfterQueuing() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -369,8 +543,15 @@ public override async Task CanCancelWaitAndAcquireAsyncAfterQueuing() [Fact] public override async Task CanFillQueueWithNewestFirstAfterCancelingQueuedRequestWithAnotherQueuedRequest() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 2, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 2, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(2); Assert.True(lease.IsAcquired); @@ -402,8 +583,15 @@ public override async Task CanFillQueueWithNewestFirstAfterCancelingQueuedReques [Fact] public override async Task CanDisposeAfterCancelingQueuedRequest() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -421,8 +609,15 @@ public override async Task CanDisposeAfterCancelingQueuedRequest() [Fact] public override async Task CanCancelWaitAndAcquireAsyncBeforeQueuing() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -441,8 +636,15 @@ public override async Task CanCancelWaitAndAcquireAsyncBeforeQueuing() [Fact] public override async Task CancelUpdatesQueueLimit() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -464,8 +666,15 @@ public override async Task CancelUpdatesQueueLimit() [Fact] public override void NoMetadataOnAcquiredLease() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); using var lease = limiter.Acquire(1); Assert.False(lease.TryGetMetadata(MetadataName.RetryAfter, out _)); } @@ -473,8 +682,15 @@ public override void NoMetadataOnAcquiredLease() [Fact] public override void MetadataNamesContainsAllMetadata() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); using var lease = limiter.Acquire(1); Assert.Collection(lease.MetadataNames, metadataName => Assert.Equal(metadataName, MetadataName.RetryAfter.Name)); } @@ -482,8 +698,15 @@ public override void MetadataNamesContainsAllMetadata() [Fact] public override async Task DisposeReleasesQueuedAcquires() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 3, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 3, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); var wait1 = limiter.WaitAndAcquireAsync(1); var wait2 = limiter.WaitAndAcquireAsync(1); @@ -509,8 +732,15 @@ public override async Task DisposeReleasesQueuedAcquires() [Fact] public override async Task DisposeAsyncReleasesQueuedAcquires() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 3, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 3, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); var wait1 = limiter.WaitAndAcquireAsync(1); var wait2 = limiter.WaitAndAcquireAsync(1); @@ -536,8 +766,15 @@ public override async Task DisposeAsyncReleasesQueuedAcquires() [Fact] public async Task RetryMetadataOnFailedWaitAsync() { - var options = new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.FromSeconds(20), 1, autoReplenishment: false); + var options = new TokenBucketRateLimiterOptions + { + TokenLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.FromSeconds(20), + TokensPerPeriod = 1, + AutoReplenishment = false + }; var limiter = new TokenBucketRateLimiter(options); using var lease = limiter.Acquire(2); @@ -556,8 +793,15 @@ public async Task RetryMetadataOnFailedWaitAsync() [Fact] public async Task CorrectRetryMetadataWithQueuedItem() { - var options = new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.FromSeconds(20), 1, autoReplenishment: false); + var options = new TokenBucketRateLimiterOptions + { + TokenLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.FromSeconds(20), + TokensPerPeriod = 1, + AutoReplenishment = false + }; var limiter = new TokenBucketRateLimiter(options); using var lease = limiter.Acquire(2); @@ -574,8 +818,15 @@ public async Task CorrectRetryMetadataWithQueuedItem() [Fact] public async Task CorrectRetryMetadataWithMultipleTokensPerPeriod() { - var options = new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.FromSeconds(20), 2, autoReplenishment: false); + var options = new TokenBucketRateLimiterOptions + { + TokenLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.FromSeconds(20), + TokensPerPeriod = 2, + AutoReplenishment = false + }; var limiter = new TokenBucketRateLimiter(options); using var lease = limiter.Acquire(2); @@ -592,8 +843,15 @@ public async Task CorrectRetryMetadataWithMultipleTokensPerPeriod() [Fact] public async Task CorrectRetryMetadataWithLargeTokensPerPeriod() { - var options = new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.FromSeconds(20), 100, autoReplenishment: false); + var options = new TokenBucketRateLimiterOptions + { + TokenLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.FromSeconds(20), + TokensPerPeriod = 100, + AutoReplenishment = false + }; var limiter = new TokenBucketRateLimiter(options); using var lease = limiter.Acquire(2); @@ -610,8 +868,15 @@ public async Task CorrectRetryMetadataWithLargeTokensPerPeriod() [Fact] public async Task CorrectRetryMetadataWithNonZeroAvailableItems() { - var options = new TokenBucketRateLimiterOptions(3, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.FromSeconds(20), 1, autoReplenishment: false); + var options = new TokenBucketRateLimiterOptions + { + TokenLimit = 3, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.FromSeconds(20), + TokensPerPeriod = 1, + AutoReplenishment = false + }; var limiter = new TokenBucketRateLimiter(options); using var lease = limiter.Acquire(2); @@ -625,8 +890,15 @@ public async Task CorrectRetryMetadataWithNonZeroAvailableItems() [Fact] public void TryReplenishHonorsTokensPerPeriod() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(7, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, 3, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 7, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 3, + AutoReplenishment = false + }); Assert.True(limiter.Acquire(5).IsAcquired); Assert.False(limiter.Acquire(3).IsAcquired); @@ -641,8 +913,15 @@ public void TryReplenishHonorsTokensPerPeriod() [Fact] public void TryReplenishWithAllTokensAvailable_Noops() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); Assert.Equal(2, limiter.GetAvailablePermits()); Assert.True(limiter.TryReplenish()); Assert.Equal(2, limiter.GetAvailablePermits()); @@ -651,8 +930,15 @@ public void TryReplenishWithAllTokensAvailable_Noops() [Fact] public void TryReplenishWithAutoReplenish_ReturnsFalse() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.FromSeconds(1), 1, autoReplenishment: true)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.FromSeconds(1), + TokensPerPeriod = 1, + AutoReplenishment = true + }); Assert.Equal(2, limiter.GetAvailablePermits()); Assert.False(limiter.TryReplenish()); Assert.Equal(2, limiter.GetAvailablePermits()); @@ -661,8 +947,15 @@ public void TryReplenishWithAutoReplenish_ReturnsFalse() [Fact] public async Task AutoReplenish_ReplenishesTokens() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 1, - TimeSpan.FromMilliseconds(1000), 1, autoReplenishment: true)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(1000), + TokensPerPeriod = 1, + AutoReplenishment = true + }); Assert.Equal(2, limiter.GetAvailablePermits()); limiter.Acquire(2); @@ -673,8 +966,15 @@ public async Task AutoReplenish_ReplenishesTokens() [Fact] public override async Task CanAcquireResourcesWithWaitAndAcquireAsyncWithQueuedItemsIfNewestFirst() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 2, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 2, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -696,8 +996,15 @@ public override async Task CanAcquireResourcesWithWaitAndAcquireAsyncWithQueuedI [Fact] public override async Task CannotAcquireResourcesWithWaitAndAcquireAsyncWithQueuedItemsIfOldestFirst() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 3, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 3, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -722,8 +1029,15 @@ public override async Task CannotAcquireResourcesWithWaitAndAcquireAsyncWithQueu [Fact] public override async Task CanAcquireResourcesWithAcquireWithQueuedItemsIfNewestFirst() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.NewestFirst, 3, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.NewestFirst, + QueueLimit = 3, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -744,8 +1058,15 @@ public override async Task CanAcquireResourcesWithAcquireWithQueuedItemsIfNewest [Fact] public override async Task CannotAcquireResourcesWithAcquireWithQueuedItemsIfOldestFirst() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(2, QueueProcessingOrder.OldestFirst, 3, - TimeSpan.Zero, 2, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 2, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 3, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 2, + AutoReplenishment = false + }); var lease = limiter.Acquire(1); Assert.True(lease.IsAcquired); @@ -767,8 +1088,15 @@ public override async Task CannotAcquireResourcesWithAcquireWithQueuedItemsIfOld [Fact] public async Task ReplenishWorksWithTicksOverInt32Max() { - using var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(10, QueueProcessingOrder.OldestFirst, 2, - TimeSpan.FromMilliseconds(2), 1, autoReplenishment: false)); + using var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 10, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(2), + TokensPerPeriod = 1, + AutoReplenishment = false + }); var lease = limiter.Acquire(10); Assert.True(lease.IsAcquired); @@ -800,8 +1128,15 @@ public async Task ReplenishWorksWithTicksOverInt32Max() [Fact] public override void NullIdleDurationWhenActive() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2, - TimeSpan.FromMilliseconds(2), 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(2), + TokensPerPeriod = 1, + AutoReplenishment = false + }); limiter.Acquire(1); Assert.Null(limiter.IdleDuration); } @@ -809,8 +1144,15 @@ public override void NullIdleDurationWhenActive() [Fact] public override async Task IdleDurationUpdatesWhenIdle() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2, - TimeSpan.FromMilliseconds(2), 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + ReplenishmentPeriod = TimeSpan.FromMilliseconds(2), + TokensPerPeriod = 1, + AutoReplenishment = false + }); Assert.NotNull(limiter.IdleDuration); var previousDuration = limiter.IdleDuration; await Task.Delay(15); @@ -820,8 +1162,15 @@ public override async Task IdleDurationUpdatesWhenIdle() [Fact] public override void IdleDurationUpdatesWhenChangingFromActive() { - var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2, - TimeSpan.Zero, 1, autoReplenishment: false)); + var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + ReplenishmentPeriod = TimeSpan.Zero, + TokensPerPeriod = 1, + AutoReplenishment = false + }); limiter.Acquire(1); limiter.TryReplenish(); Assert.NotNull(limiter.IdleDuration); @@ -831,14 +1180,28 @@ public override void IdleDurationUpdatesWhenChangingFromActive() public void ReplenishingRateLimiterPropertiesHaveCorrectValues() { var replenishPeriod = TimeSpan.FromMinutes(1); - using ReplenishingRateLimiter limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2, - replenishPeriod, 1, autoReplenishment: true)); + using ReplenishingRateLimiter limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + ReplenishmentPeriod = replenishPeriod, + TokensPerPeriod = 1, + AutoReplenishment = true + }); Assert.True(limiter.IsAutoReplenishing); Assert.Equal(replenishPeriod, limiter.ReplenishmentPeriod); replenishPeriod = TimeSpan.FromSeconds(2); - using ReplenishingRateLimiter limiter2 = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.OldestFirst, 2, - replenishPeriod, 1, autoReplenishment: false)); + using ReplenishingRateLimiter limiter2 = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions + { + TokenLimit = 1, + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2, + ReplenishmentPeriod = replenishPeriod, + TokensPerPeriod = 1, + AutoReplenishment = false + }); Assert.False(limiter2.IsAutoReplenishing); Assert.Equal(replenishPeriod, limiter2.ReplenishmentPeriod); }