}
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
{
}
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
{
}
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
{
}
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; } }
}
}
/// <param name="options">Options to specify the behavior of the <see cref="ConcurrencyLimiter"/>.</param>
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;
}
public sealed class ConcurrencyLimiterOptions
{
/// <summary>
- /// Initializes the <see cref="ConcurrencyLimiterOptions"/>.
- /// </summary>
- /// <param name="permitLimit">Maximum number of permits that can be leased concurrently.</param>
- /// <param name="queueProcessingOrder">Determines the behaviour of <see cref="RateLimiter.WaitAndAcquireAsync"/> when not enough resources can be leased.</param>
- /// <param name="queueLimit">Maximum number of permits that can be queued concurrently.</param>
- /// <exception cref="ArgumentOutOfRangeException">When <paramref name="permitLimit"/> or <paramref name="queueLimit"/> are less than 0.</exception>
- 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;
- }
-
- /// <summary>
/// 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 <see cref="ConcurrencyLimiter"/>.
/// </summary>
- public int PermitLimit { get; }
+ public int PermitLimit { get; set; }
/// <summary>
/// Determines the behaviour of <see cref="RateLimiter.WaitAndAcquireAsync"/> when not enough resources can be leased.
/// <value>
/// <see cref="QueueProcessingOrder.OldestFirst"/> by default.
/// </value>
- public QueueProcessingOrder QueueProcessingOrder { get; } = QueueProcessingOrder.OldestFirst;
+ public QueueProcessingOrder QueueProcessingOrder { get; set; } = QueueProcessingOrder.OldestFirst;
/// <summary>
/// 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 <see cref="ConcurrencyLimiter"/>.
/// </summary>
- public int QueueLimit { get; }
+ public int QueueLimit { get; set; }
}
}
/// <param name="options">Options to specify the behavior of the <see cref="FixedWindowRateLimiter"/>.</param>
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();
public sealed class FixedWindowRateLimiterOptions
{
/// <summary>
- /// Initializes the <see cref="FixedWindowRateLimiterOptions"/>.
- /// </summary>
- /// <param name="permitLimit">Maximum number of requests that can be served in the window.</param>
- /// <param name="queueProcessingOrder"></param>
- /// <param name="queueLimit">Maximum number of unprocessed request counters waiting via <see cref="RateLimiter.WaitAndAcquireAsync(int, CancellationToken)"/>.</param>
- /// <param name="window">
- /// Specifies how often request counters can be replenished. Replenishing is triggered either by an internal timer if <paramref name="autoReplenishment"/> is true, or by calling <see cref="FixedWindowRateLimiter.TryReplenish"/>.
- /// </param>
- /// <param name="autoReplenishment">
- /// Specifies whether request replenishment will be handled by the <see cref="FixedWindowRateLimiter"/> or by another party via <see cref="FixedWindowRateLimiter.TryReplenish"/>.
- /// </param>
- /// <exception cref="ArgumentOutOfRangeException">When <paramref name="permitLimit"/> or <paramref name="queueLimit"/> are less than 0. </exception>
- 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;
- }
-
- /// <summary>
/// Specifies the time window that takes in the requests.
+ /// Must be set to a value >= <see cref="TimeSpan.Zero" /> by the time these options are passed to the constructor of <see cref="FixedWindowRateLimiter"/>.
/// </summary>
- public TimeSpan Window { get; }
+ public TimeSpan Window { get; set; } = TimeSpan.Zero;
/// <summary>
/// Specified whether the <see cref="FixedWindowRateLimiter"/> is automatically refresh counters or if someone else
/// will be calling <see cref="FixedWindowRateLimiter.TryReplenish"/> to refresh counters.
/// </summary>
- public bool AutoReplenishment { get; }
+ /// <value>
+ /// <see langword="true" /> by default.
+ /// </value>
+ public bool AutoReplenishment { get; set; } = true;
/// <summary>
/// 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 <see cref="FixedWindowRateLimiter"/>.
/// </summary>
- public int PermitLimit { get; }
+ public int PermitLimit { get; set; }
/// <summary>
/// Determines the behaviour of <see cref="RateLimiter.WaitAndAcquireAsync"/> when not enough resources can be leased.
/// <value>
/// <see cref="QueueProcessingOrder.OldestFirst"/> by default.
/// </value>
- public QueueProcessingOrder QueueProcessingOrder { get; }
+ public QueueProcessingOrder QueueProcessingOrder { get; set; } = QueueProcessingOrder.OldestFirst;
/// <summary>
/// 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 <see cref="FixedWindowRateLimiter"/>.
/// </summary>
- public int QueueLimit { get; }
+ public int QueueLimit { get; set; }
}
}
// 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);
});
// 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);
});
// 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);
});
/// <param name="options">Options to specify the behavior of the <see cref="SlidingWindowRateLimiter"/>.</param>
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
public sealed class SlidingWindowRateLimiterOptions
{
/// <summary>
- /// Initializes the <see cref="SlidingWindowRateLimiterOptions"/>.
- /// </summary>
- /// <param name="permitLimit">Maximum number of request counters that can be served in a window.</param>
- /// <param name="queueProcessingOrder"></param>
- /// <param name="queueLimit">Maximum number of unprocessed request counters waiting via <see cref="RateLimiter.WaitAndAcquireAsync(int, CancellationToken)"/>.</param>
- /// <param name="window">
- /// Specifies how often requests can be replenished. Replenishing is triggered either by an internal timer if <paramref name="autoReplenishment"/> is true, or by calling <see cref="SlidingWindowRateLimiter.TryReplenish"/>.
- /// </param>
- /// <param name="segmentsPerWindow">Specified how many segments a window can be divided into. The total requests a segment can serve cannot exceed the max limit.<paramref name="permitLimit"/>.</param>
- /// <param name="autoReplenishment">
- /// Specifies whether request replenishment will be handled by the <see cref="SlidingWindowRateLimiter"/> or by another party via <see cref="SlidingWindowRateLimiter.TryReplenish"/>.
- /// </param>
- /// <exception cref="ArgumentOutOfRangeException">When <paramref name="permitLimit"/>, <paramref name="queueLimit"/>, or <paramref name="segmentsPerWindow"/> are less than 0. </exception>
- 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;
- }
-
- /// <summary>
/// Specifies the minimum period between replenishments.
+ /// Must be set to a value >= <see cref="TimeSpan.Zero" /> by the time these options are passed to the constructor of <see cref="SlidingWindowRateLimiter"/>.
/// </summary>
- public TimeSpan Window { get; }
+ public TimeSpan Window { get; set; } = TimeSpan.Zero;
/// <summary>
/// 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 <see cref="SlidingWindowRateLimiter"/>.
/// </summary>
- public int SegmentsPerWindow { get; }
+ public int SegmentsPerWindow { get; set; }
/// <summary>
/// Specified whether the <see cref="SlidingWindowRateLimiter"/> is automatically replenishing request counters or if someone else
/// will be calling <see cref="SlidingWindowRateLimiter.TryReplenish"/> to replenish tokens.
/// </summary>
- public bool AutoReplenishment { get; }
+ /// <value>
+ /// <see langword="true" /> by default.
+ /// </value>
+ public bool AutoReplenishment { get; set; } = true;
/// <summary>
/// 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 <see cref="SlidingWindowRateLimiter"/>.
/// </summary>
- public int PermitLimit { get; }
+ public int PermitLimit { get; set; }
/// <summary>
/// Determines the behaviour of <see cref="RateLimiter.WaitAndAcquireAsync"/> when not enough resources can be leased.
/// <value>
/// <see cref="QueueProcessingOrder.OldestFirst"/> by default.
/// </value>
- public QueueProcessingOrder QueueProcessingOrder { get; }
+ public QueueProcessingOrder QueueProcessingOrder { get; set; } = QueueProcessingOrder.OldestFirst;
/// <summary>
/// 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 <see cref="SlidingWindowRateLimiter"/>.
/// </summary>
- public int QueueLimit { get; }
+ public int QueueLimit { get; set; }
}
}
/// <param name="options">Options to specify the behavior of the <see cref="TokenBucketRateLimiter"/>.</param>
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();
public sealed class TokenBucketRateLimiterOptions
{
/// <summary>
- /// Initializes the <see cref="TokenBucketRateLimiterOptions"/>.
- /// </summary>
- /// <param name="tokenLimit">Maximum number of tokens that can be in the token bucket.</param>
- /// <param name="queueProcessingOrder"></param>
- /// <param name="queueLimit">Maximum number of unprocessed tokens waiting via <see cref="RateLimiter.WaitAndAcquireAsync(int, CancellationToken)"/>.</param>
- /// <param name="replenishmentPeriod">
- /// Specifies how often tokens can be replenished. Replenishing is triggered either by an internal timer if <paramref name="autoReplenishment"/> is true, or by calling <see cref="TokenBucketRateLimiter.TryReplenish"/>.
- /// </param>
- /// <param name="tokensPerPeriod">Specified how many tokens can be added to the token bucket on a successful replenish. Available token count will not exceed <paramref name="tokenLimit"/>.</param>
- /// <param name="autoReplenishment">
- /// Specifies whether token replenishment will be handled by the <see cref="TokenBucketRateLimiter"/> or by another party via <see cref="TokenBucketRateLimiter.TryReplenish"/>.
- /// </param>
- /// <exception cref="ArgumentOutOfRangeException">When <paramref name="tokenLimit"/>, <paramref name="queueLimit"/>, or <paramref name="tokensPerPeriod"/> are less than 0.</exception>
- 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;
- }
-
- /// <summary>
/// Specifies the minimum period between replenishments.
+ /// Must be set to a value >= <see cref="TimeSpan.Zero" /> by the time these options are passed to the constructor of <see cref="TokenBucketRateLimiter"/>.
/// </summary>
- public TimeSpan ReplenishmentPeriod { get; }
+ public TimeSpan ReplenishmentPeriod { get; set; } = TimeSpan.Zero;
/// <summary>
/// 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 <see cref="TokenBucketRateLimiter"/>.
/// </summary>
- public int TokensPerPeriod { get; }
+ public int TokensPerPeriod { get; set; }
/// <summary>
/// Specified whether the <see cref="TokenBucketRateLimiter"/> is automatically replenishing tokens or if someone else
/// will be calling <see cref="TokenBucketRateLimiter.TryReplenish"/> to replenish tokens.
/// </summary>
- public bool AutoReplenishment { get; }
+ /// <value>
+ /// <see langword="true" /> by default.
+ /// </value>
+ public bool AutoReplenishment { get; set; } = true;
/// <summary>
/// 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 <see cref="TokenBucketRateLimiter"/>.
/// </summary>
- public int TokenLimit { get; }
+ public int TokenLimit { get; set; }
/// <summary>
/// Determines the behaviour of <see cref="RateLimiter.WaitAndAcquireAsync"/> when not enough resources can be leased.
/// <value>
/// <see cref="QueueProcessingOrder.OldestFirst"/> by default.
/// </value>
- public QueueProcessingOrder QueueProcessingOrder { get; }
+ public QueueProcessingOrder QueueProcessingOrder { get; set; } = QueueProcessingOrder.OldestFirst;
/// <summary>
/// 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 <see cref="TokenBucketRateLimiter"/>.
/// </summary>
- public int QueueLimit { get; }
+ public int QueueLimit { get; set; }
}
}
{
using var limiter1 = PartitionedRateLimiter.Create<string, int>(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<string, int>(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<string>(limiter1, limiter2);
{
using var limiter1 = PartitionedRateLimiter.Create<string, int>(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<string, int>(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<string>(limiter1, limiter2);
{
using var limiter1 = PartitionedRateLimiter.Create<string, int>(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<string, int>(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<string, int>(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<string>(limiter1, limiter2, limiter3);
{
using var limiter = PartitionedRateLimiter.Create<string, int>(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<string>(limiter);
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => concurrencyLimiter1);
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => concurrencyLimiter1);
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => concurrencyLimiter);
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => concurrencyLimiter);
public void AcquireFailsWhenOneLimiterDoesNotHaveEnoughResources()
{
var limiterFactory = new TrackingRateLimiterFactory<int>();
- 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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => limiterFactory.GetLimiter(key));
public async Task WaitAndAcquireAsyncFailsWhenOneLimiterDoesNotHaveEnoughResources()
{
var limiterFactory = new TrackingRateLimiterFactory<int>();
- 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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => limiterFactory.GetLimiter(key));
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => concurrencyLimiter1);
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => concurrencyLimiter1);
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => concurrencyLimiter);
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => concurrencyLimiter);
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => new CustomizableLimiter() { AcquireCoreImpl = _ => new ThrowDisposeLease() });
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => new CustomizableLimiter() { AcquireCoreImpl = _ => new ThrowDisposeLease() });
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => new CustomizableLimiter() { AcquireCoreImpl = _ => new ThrowDisposeLease() });
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => new CustomizableLimiter() { WaitAndAcquireAsyncCoreImpl = (_, _) => new ValueTask<RateLimitLease>(new ThrowDisposeLease()) });
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => new CustomizableLimiter() { AcquireCoreImpl = _ => new ThrowDisposeLease() });
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => new CustomizableLimiter() { WaitAndAcquireAsyncCoreImpl = (_, _) => new ValueTask<RateLimitLease>(new ThrowDisposeLease()) });
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => new CustomizableLimiter() { AcquireCoreImpl = _ => new ThrowDisposeLease() });
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => new CustomizableLimiter() { WaitAndAcquireAsyncCoreImpl = (_, _) => new ValueTask<RateLimitLease>(new ThrowDisposeLease()) });
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => concurrencyLimiter1);
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => concurrencyLimiter1);
{
using var limiter = PartitionedRateLimiter.Create<string, int>(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<string>(limiter);
[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<string, int>(resource =>
{
return RateLimitPartition.Get(1, key => concurrencyLimiter);
});
using var limiter2 = PartitionedRateLimiter.Create<string, int>(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<string>(limiter1, limiter2);
{
using var limiter1 = PartitionedRateLimiter.Create<string, int>(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<string, int>(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<string>(limiter1, limiter2);
[Fact]
public override void InvalidOptionsThrows()
{
- Assert.Throws<ArgumentOutOfRangeException>(() => new ConcurrencyLimiterOptions(-1, QueueProcessingOrder.NewestFirst, 1));
- Assert.Throws<ArgumentOutOfRangeException>(() => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, -1));
+ Assert.Throws<ArgumentException>(() => new ConcurrencyLimiter(new ConcurrencyLimiterOptions
+ {
+ PermitLimit = -1,
+ QueueProcessingOrder = QueueProcessingOrder.NewestFirst,
+ QueueLimit = 1
+ }));
+ Assert.Throws<ArgumentException>(() => 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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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<ArgumentOutOfRangeException>(() => limiter.Acquire(2));
Assert.Equal("permitCount", ex.ParamName);
}
[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<ArgumentOutOfRangeException>(async () => await limiter.WaitAndAcquireAsync(2));
Assert.Equal("permitCount", ex.ParamName);
}
[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<ArgumentOutOfRangeException>(() => 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<ArgumentOutOfRangeException>(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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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 _));
}
[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));
}
[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);
[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);
[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);
[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);
}
[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);
[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);
[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);
[Fact]
public override void InvalidOptionsThrows()
{
- Assert.Throws<ArgumentOutOfRangeException>(
- () => new FixedWindowRateLimiterOptions(-1, QueueProcessingOrder.NewestFirst, 1, TimeSpan.FromMinutes(2), autoReplenishment: false));
- Assert.Throws<ArgumentOutOfRangeException>(
- () => new FixedWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, -1, TimeSpan.FromMinutes(2), autoReplenishment: false));
+ Assert.Throws<ArgumentException>(
+ () => new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions
+ {
+ PermitLimit = -1,
+ QueueProcessingOrder = QueueProcessingOrder.NewestFirst,
+ QueueLimit = 1,
+ Window = TimeSpan.FromMinutes(2),
+ AutoReplenishment = false
+ }));
+ Assert.Throws<ArgumentException>(
+ () => new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions
+ {
+ PermitLimit = 1,
+ QueueProcessingOrder = QueueProcessingOrder.NewestFirst,
+ QueueLimit = -1,
+ Window = TimeSpan.FromMinutes(2),
+ AutoReplenishment = false
+ }));
+ Assert.Throws<ArgumentException>(
+ () => 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();
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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<ArgumentOutOfRangeException>(() => 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<ArgumentOutOfRangeException>(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<ArgumentOutOfRangeException>(() => 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<ArgumentOutOfRangeException>(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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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 _));
}
[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));
}
[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);
[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);
[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);
[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);
[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);
[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());
[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);
[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);
[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);
[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);
[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);
[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);
}
[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);
[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);
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);
}
[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);
[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);
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");
using var limiter = PartitionedRateLimiter.Create<string, int>(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("");
{
// 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("");
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");
using var limiter = PartitionedRateLimiter.Create<string, int>(resource =>
{
return RateLimitPartition.GetConcurrencyLimiter(1,
- _ => new ConcurrencyLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1));
+ _ => new ConcurrencyLimiterOptions
+ {
+ PermitLimit = 1,
+ QueueProcessingOrder = QueueProcessingOrder.NewestFirst,
+ QueueLimit = 1
+ });
});
var lease = limiter.Acquire("");
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
+ });
}
});
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
+ });
}
});
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
+ });
}
});
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
+ });
}
});
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
+ });
}
});
[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);
[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);
[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<ConcurrencyLimiter>(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<TokenBucketRateLimiter>(limiter);
Assert.Equal(1, tokenBucketLimiter.GetAvailablePermits());
[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);
[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);
[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);
[Fact]
public override void InvalidOptionsThrows()
{
- Assert.Throws<ArgumentOutOfRangeException>(
- () => new SlidingWindowRateLimiterOptions(-1, QueueProcessingOrder.NewestFirst, 1, TimeSpan.FromMinutes(2), 1, autoReplenishment: false));
- Assert.Throws<ArgumentOutOfRangeException>(
- () => new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, -1, TimeSpan.FromMinutes(2), 1, autoReplenishment: false));
- Assert.Throws<ArgumentOutOfRangeException>(
- () => new SlidingWindowRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, TimeSpan.FromMinutes(2), -1, autoReplenishment: false));
+ Assert.Throws<ArgumentException>(
+ () => new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions
+ {
+ PermitLimit = -1,
+ QueueProcessingOrder = QueueProcessingOrder.NewestFirst,
+ QueueLimit = 1,
+ Window = TimeSpan.FromMinutes(2),
+ SegmentsPerWindow = 1,
+ AutoReplenishment = false
+ }));
+ Assert.Throws<ArgumentException>(
+ () => new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions
+ {
+ PermitLimit = 1,
+ QueueProcessingOrder = QueueProcessingOrder.NewestFirst,
+ QueueLimit = -1,
+ Window = TimeSpan.FromMinutes(2),
+ SegmentsPerWindow = 1,
+ AutoReplenishment = false
+ }));
+ Assert.Throws<ArgumentException>(
+ () => new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions
+ {
+ PermitLimit = 1,
+ QueueProcessingOrder = QueueProcessingOrder.NewestFirst,
+ QueueLimit = 1,
+ Window = TimeSpan.FromMinutes(2),
+ SegmentsPerWindow = -1,
+ AutoReplenishment = false
+ }));
+ Assert.Throws<ArgumentException>(
+ () => 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();
// 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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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<ArgumentOutOfRangeException>(() => 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<ArgumentOutOfRangeException>(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<ArgumentOutOfRangeException>(() => 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<ArgumentOutOfRangeException>(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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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 _));
}
[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));
}
[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);
[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);
[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());
[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);
[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);
[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);
[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);
[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);
[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);
}
[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);
[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();
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);
}
[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);
[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);
[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);
[Fact]
public override void InvalidOptionsThrows()
{
- Assert.Throws<ArgumentOutOfRangeException>(
- () => new TokenBucketRateLimiterOptions(-1, QueueProcessingOrder.NewestFirst, 1, TimeSpan.FromMinutes(2), 1, autoReplenishment: false));
- Assert.Throws<ArgumentOutOfRangeException>(
- () => new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, -1, TimeSpan.FromMinutes(2), 1, autoReplenishment: false));
- Assert.Throws<ArgumentOutOfRangeException>(
- () => new TokenBucketRateLimiterOptions(1, QueueProcessingOrder.NewestFirst, 1, TimeSpan.FromMinutes(2), -1, autoReplenishment: false));
+ Assert.Throws<ArgumentException>(
+ () => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions
+ {
+ TokenLimit = -1,
+ QueueProcessingOrder = QueueProcessingOrder.NewestFirst,
+ QueueLimit = 1,
+ ReplenishmentPeriod = TimeSpan.FromMinutes(2),
+ TokensPerPeriod = 1,
+ AutoReplenishment = false
+ }));
+ Assert.Throws<ArgumentException>(
+ () => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions
+ {
+ TokenLimit = 1,
+ QueueProcessingOrder = QueueProcessingOrder.NewestFirst,
+ QueueLimit = -1,
+ ReplenishmentPeriod = TimeSpan.FromMinutes(2),
+ TokensPerPeriod = 1,
+ AutoReplenishment = false
+ }));
+ Assert.Throws<ArgumentException>(
+ () => new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions
+ {
+ TokenLimit = 1,
+ QueueProcessingOrder = QueueProcessingOrder.NewestFirst,
+ QueueLimit = 1,
+ ReplenishmentPeriod = TimeSpan.FromMinutes(2),
+ TokensPerPeriod = -1,
+ AutoReplenishment = false
+ }));
+ Assert.Throws<ArgumentException>(
+ () => 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();
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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<ArgumentOutOfRangeException>(() => 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<ArgumentOutOfRangeException>(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<ArgumentOutOfRangeException>(() => 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<ArgumentOutOfRangeException>(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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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 _));
}
[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));
}
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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);
[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());
[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());
[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);
[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);
[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);
[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);
[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);
[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);
[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);
}
[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);
[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);
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);
}