Skip to content
Merged
Show file tree
Hide file tree
Changes from 51 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
2e7c052
Update ConcurrencyLimiterOptions.cs
wtgodbe Jul 20, 2022
986b892
Update FixedWindowRateLimiterOptions.cs
wtgodbe Jul 20, 2022
e7f7dbb
Update FixedWindowRateLimiterOptions.cs
wtgodbe Jul 20, 2022
6d68534
Update FixedWindowRateLimiterOptions.cs
wtgodbe Jul 20, 2022
4b40874
Update SlidingWindowRateLimiterOptions.cs
wtgodbe Jul 20, 2022
4ae0731
Update TokenBucketRateLimiterOptions.cs
wtgodbe Jul 20, 2022
e8e3c31
Update ConcurrencyLimiter.cs
wtgodbe Jul 20, 2022
72b56f9
Update FixedWindowRateLimiter.cs
wtgodbe Jul 20, 2022
d4a7eac
Update SlidingWindowRateLimiter.cs
wtgodbe Jul 20, 2022
1ed959b
Update TokenBucketRateLimiter.cs
wtgodbe Jul 20, 2022
d40805d
Update ChainedLimiterTests.cs
wtgodbe Jul 20, 2022
9f27a6b
Update ConcurrencyLimiterOptions.cs
wtgodbe Jul 20, 2022
71d005b
Update FixedWindowRateLimiterOptions.cs
wtgodbe Jul 20, 2022
56335d4
Update SlidingWindowRateLimiterOptions.cs
wtgodbe Jul 20, 2022
9453bf3
Update TokenBucketRateLimiterOptions.cs
wtgodbe Jul 20, 2022
5ebd688
Update RateLimitPartition.cs
wtgodbe Jul 20, 2022
d5f10c0
Update System.Threading.RateLimiting.cs
wtgodbe Jul 20, 2022
136d7d4
Update ChainedLimiterTests.cs
wtgodbe Jul 20, 2022
5be2a01
Update ConcurrencyLimiter.cs
wtgodbe Jul 20, 2022
efebe3e
Update FixedWindowRateLimiter.cs
wtgodbe Jul 20, 2022
aaac3fc
Update SlidingWindowRateLimiter.cs
wtgodbe Jul 20, 2022
76380ea
Update TokenBucketRateLimiter.cs
wtgodbe Jul 20, 2022
faa5785
Update ConcurrencyLimiterOptions.cs
wtgodbe Jul 20, 2022
af59dd8
Update FixedWindowRateLimiterOptions.cs
wtgodbe Jul 20, 2022
1a8fbe0
Update SlidingWindowRateLimiterOptions.cs
wtgodbe Jul 20, 2022
a252814
Update ChainedLimiterTests.cs
wtgodbe Jul 20, 2022
ae6202d
Update ChainedLimiterTests.cs
wtgodbe Jul 20, 2022
c79b34b
Fix tests
wtgodbe Jul 20, 2022
1e732b5
Update ConcurrencyLimiter.cs
wtgodbe Jul 20, 2022
17df529
Update FixedWindowRateLimiter.cs
wtgodbe Jul 20, 2022
b422fe6
Update SlidingWindowRateLimiter.cs
wtgodbe Jul 20, 2022
62e863c
Update TokenBucketRateLimiter.cs
wtgodbe Jul 20, 2022
ce01501
Update FixedWindowRateLimiter.cs
wtgodbe Jul 21, 2022
1b3d366
Update SlidingWindowRateLimiter.cs
wtgodbe Jul 21, 2022
ae49b58
Update TokenBucketRateLimiter.cs
wtgodbe Jul 21, 2022
954b978
Update FixedWindowRateLimiterTests.cs
wtgodbe Jul 21, 2022
629e3f6
Update SlidingWindowRateLimiterTests.cs
wtgodbe Jul 21, 2022
111420f
Update TokenBucketRateLimiterTests.cs
wtgodbe Jul 21, 2022
efd9d41
Update TokenBucketRateLimiter.cs
wtgodbe Jul 21, 2022
bec4227
Update src/libraries/System.Threading.RateLimiting/src/System/Threadi…
wtgodbe Jul 21, 2022
08fa3be
Update src/libraries/System.Threading.RateLimiting/src/System/Threadi…
wtgodbe Jul 21, 2022
87ed111
Update FixedWindowRateLimiter.cs
wtgodbe Jul 21, 2022
82e4057
Update SlidingWindowRateLimiter.cs
wtgodbe Jul 21, 2022
7feff7e
Fixup
wtgodbe Jul 21, 2022
c7acb7b
Whitespace
wtgodbe Jul 21, 2022
f1345c4
ArgumentNullException
wtgodbe Jul 21, 2022
df99181
Merge remote-tracking branch 'origin/main' into wtgodbe/OptionsPattern
wtgodbe Jul 21, 2022
0e89029
React to test change
wtgodbe Jul 21, 2022
9d6b38b
Fix tests
wtgodbe Jul 21, 2022
d148152
Another test fix
wtgodbe Jul 21, 2022
8e06f6a
Feedback
wtgodbe Jul 22, 2022
dd9eca1
Update src/libraries/System.Threading.RateLimiting/src/System/Threadi…
wtgodbe Jul 22, 2022
8b11ec5
Update src/libraries/System.Threading.RateLimiting/src/System/Threadi…
wtgodbe Jul 22, 2022
3007da6
Update src/libraries/System.Threading.RateLimiting/src/System/Threadi…
wtgodbe Jul 22, 2022
1857521
Update src/libraries/System.Threading.RateLimiting/src/System/Threadi…
wtgodbe Jul 22, 2022
02831bd
Update src/libraries/System.Threading.RateLimiting/src/System/Threadi…
wtgodbe Jul 22, 2022
7966a36
Update src/libraries/System.Threading.RateLimiting/src/System/Threadi…
wtgodbe Jul 22, 2022
2c90029
Update src/libraries/System.Threading.RateLimiting/src/System/Threadi…
wtgodbe Jul 22, 2022
855fe11
Update src/libraries/System.Threading.RateLimiting/src/System/Threadi…
wtgodbe Jul 22, 2022
c31d883
Update src/libraries/System.Threading.RateLimiting/src/System/Threadi…
wtgodbe Jul 22, 2022
8fb231d
Fix checks, add test
wtgodbe Jul 22, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ protected override void Dispose(bool disposing) { }
}
public sealed partial class ConcurrencyLimiterOptions
{
public ConcurrencyLimiterOptions(int permitLimit, System.Threading.RateLimiting.QueueProcessingOrder queueProcessingOrder, int queueLimit) { }
public int PermitLimit { get { throw null; } }
public int QueueLimit { get { throw null; } }
public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } }
public ConcurrencyLimiterOptions() { }
public int PermitLimit { get { throw null; } set { throw null; } }
public int QueueLimit { get { throw null; } set { throw null; } }
public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } set { throw null; } }
}
public sealed partial class FixedWindowRateLimiter : System.Threading.RateLimiting.ReplenishingRateLimiter
{
Expand All @@ -38,12 +38,12 @@ protected override void Dispose(bool disposing) { }
}
public sealed partial class FixedWindowRateLimiterOptions
{
public FixedWindowRateLimiterOptions(int permitLimit, System.Threading.RateLimiting.QueueProcessingOrder queueProcessingOrder, int queueLimit, System.TimeSpan window, bool autoReplenishment = true) { }
public bool AutoReplenishment { get { throw null; } }
public int PermitLimit { get { throw null; } }
public int QueueLimit { get { throw null; } }
public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } }
public System.TimeSpan Window { get { throw null; } }
public FixedWindowRateLimiterOptions() { }
public bool AutoReplenishment { get { throw null; } set { throw null; } }
public int PermitLimit { get { throw null; } set { throw null; } }
public int QueueLimit { get { throw null; } set { throw null; } }
public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } set { throw null; } }
public System.TimeSpan Window { get { throw null; } set { throw null; } }
}
public static partial class MetadataName
{
Expand Down Expand Up @@ -151,13 +151,13 @@ protected override void Dispose(bool disposing) { }
}
public sealed partial class SlidingWindowRateLimiterOptions
{
public SlidingWindowRateLimiterOptions(int permitLimit, System.Threading.RateLimiting.QueueProcessingOrder queueProcessingOrder, int queueLimit, System.TimeSpan window, int segmentsPerWindow, bool autoReplenishment = true) { }
public bool AutoReplenishment { get { throw null; } }
public int PermitLimit { get { throw null; } }
public int QueueLimit { get { throw null; } }
public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } }
public int SegmentsPerWindow { get { throw null; } }
public System.TimeSpan Window { get { throw null; } }
public SlidingWindowRateLimiterOptions() { }
public bool AutoReplenishment { get { throw null; } set { throw null; } }
public int PermitLimit { get { throw null; } set { throw null; } }
public int QueueLimit { get { throw null; } set { throw null; } }
public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } set { throw null; } }
public int SegmentsPerWindow { get { throw null; } set { throw null; } }
public System.TimeSpan Window { get { throw null; } set { throw null; } }
}
public sealed partial class TokenBucketRateLimiter : System.Threading.RateLimiting.ReplenishingRateLimiter
{
Expand All @@ -174,12 +174,12 @@ protected override void Dispose(bool disposing) { }
}
public sealed partial class TokenBucketRateLimiterOptions
{
public TokenBucketRateLimiterOptions(int tokenLimit, System.Threading.RateLimiting.QueueProcessingOrder queueProcessingOrder, int queueLimit, System.TimeSpan replenishmentPeriod, int tokensPerPeriod, bool autoReplenishment = true) { }
public bool AutoReplenishment { get { throw null; } }
public int QueueLimit { get { throw null; } }
public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } }
public System.TimeSpan ReplenishmentPeriod { get { throw null; } }
public int TokenLimit { get { throw null; } }
public int TokensPerPeriod { get { throw null; } }
public TokenBucketRateLimiterOptions() { }
public bool AutoReplenishment { get { throw null; } set { throw null; } }
public int QueueLimit { get { throw null; } set { throw null; } }
public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get { throw null; } set { throw null; } }
public System.TimeSpan ReplenishmentPeriod { get { throw null; } set { throw null; } }
public int TokenLimit { get { throw null; } set { throw null; } }
public int TokensPerPeriod { get { throw null; } set { throw null; } }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,26 @@ public sealed class ConcurrencyLimiter : RateLimiter
/// <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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,24 @@ namespace System.Threading.RateLimiting
/// </summary>
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.
/// </summary>
/// <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; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,28 @@ public sealed class FixedWindowRateLimiter : ReplenishingRateLimiter
/// <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));
}

_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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,69 +8,39 @@ namespace System.Threading.RateLimiting
/// </summary>
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 nonzero value 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.
/// </summary>
/// <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; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,15 @@ public static RateLimitPartition<TKey> GetTokenBucketLimiter<TKey>(
// 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);
});
Expand All @@ -98,8 +105,15 @@ public static RateLimitPartition<TKey> GetSlidingWindowLimiter<TKey>(
// 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);
});
Expand All @@ -125,8 +139,14 @@ public static RateLimitPartition<TKey> GetFixedWindowLimiter<TKey>(
// 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);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,29 @@ public sealed class SlidingWindowRateLimiter : ReplenishingRateLimiter
/// <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));
}

_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
Expand Down
Loading