Skip to content

Commit

Permalink
fb
Browse files Browse the repository at this point in the history
  • Loading branch information
BrennanConroy committed Aug 12, 2022
1 parent 0c9d83c commit 955f12c
Show file tree
Hide file tree
Showing 13 changed files with 90 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public ChainedPartitionedRateLimiter(PartitionedRateLimiter<TResource>[] limiter
long lowestAvailablePermits = long.MaxValue;
long currentQueuedCount = 0;
long totalFailedLeases = 0;
long totalSuccessfulLeases = 0;
long innerMostSuccessfulLeases = 0;
foreach (PartitionedRateLimiter<TResource> limiter in _limiters)
{
if (limiter.GetStatistics(resource) is { } statistics)
Expand All @@ -40,15 +40,15 @@ public ChainedPartitionedRateLimiter(PartitionedRateLimiter<TResource>[] limiter
}
currentQueuedCount += statistics.CurrentQueuedCount;
totalFailedLeases += statistics.TotalFailedLeases;
totalSuccessfulLeases += statistics.TotalSuccessfulLeases;
innerMostSuccessfulLeases = statistics.TotalSuccessfulLeases;
}
}
return new RateLimiterStatistics()
{
CurrentAvailablePermits = lowestAvailablePermits,
CurrentQueuedCount = currentQueuedCount,
TotalFailedLeases = totalFailedLeases,
TotalSuccessfulLeases = totalSuccessfulLeases,
TotalSuccessfulLeases = innerMostSuccessfulLeases,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public ConcurrencyLimiter(ConcurrencyLimiterOptions options)
/// <inheritdoc/>
public override RateLimiterStatistics? GetStatistics()
{
ThrowIfDisposed();
return new RateLimiterStatistics()
{
CurrentAvailablePermits = _permitCount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ public FixedWindowRateLimiter(FixedWindowRateLimiterOptions options)
/// <inheritdoc/>
public override RateLimiterStatistics? GetStatistics()
{
ThrowIfDisposed();
return new RateLimiterStatistics()
{
CurrentAvailablePermits = _requestCount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,14 @@ public async ValueTask DisposeAsync()
/// </summary>
/// <typeparam name="TOuter">The type to translate into <typeparamref name="TResource"/>.</typeparam>
/// <param name="keyAdapter">The function to be called every time a <typeparamref name="TOuter"/> is passed to
/// PartitionedRateLimiter&lt;TOuter&gt;.Acquire(TOuter, int) or PartitionedRateLimiter&lt;TOuter&gt;.WaitAsync(TOuter, int, CancellationToken).</param>
/// <remarks><paramref name="keyAdapter"/> should be implemented in a thread-safe way.
/// PartitionedRateLimiter&lt;TOuter&gt;.Acquire(TOuter, int) or PartitionedRateLimiter&lt;TOuter&gt;.WaitAsync(TOuter, int, CancellationToken).
/// <para />
/// <remarks><paramref name="keyAdapter"/> should be implemented in a thread-safe way.</remarks></param>
/// <param name="leaveOpen">Specifies whether the returned <see cref="PartitionedRateLimiter{TOuter}"/> will dispose the wrapped <see cref="PartitionedRateLimiter{TResource}"/>.</param>
/// <returns>A new PartitionedRateLimiter&lt;TOuter&gt; that translates <typeparamref name="TOuter"/>
/// to <typeparamref name="TResource"/> and calls the inner <see cref="PartitionedRateLimiter{TResource}"/>.</returns>
public PartitionedRateLimiter<TOuter> WithTranslatedKey<TOuter>(Func<TOuter, TResource> keyAdapter, bool leaveOpen)
{
// REVIEW: Do we want to have an option to dispose the inner limiter?
// Should the default be to dispose the inner limiter and have an option to not dispose it?
// See Stream wrappers like SslStream for prior-art
return new TranslatingLimiter<TResource, TOuter>(this, keyAdapter, leaveOpen);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ public static PartitionedRateLimiter<TResource> Create<TResource, TPartitionKey>
/// Methods on the returned <see cref="PartitionedRateLimiter{TResource}"/> will iterate over the passed in <paramref name="limiters"/> in the order given.
/// </para>
/// <para>
/// <see cref="PartitionedRateLimiter{TResource}.GetStatistics(TResource)"/> will return the lowest value for <see cref="RateLimiterStatistics.CurrentAvailablePermits"/>
/// <see cref="PartitionedRateLimiter{TResource}.GetStatistics(TResource)"/> will return the lowest value for <see cref="RateLimiterStatistics.CurrentAvailablePermits"/>,
/// the inner-most limiter's <see cref="RateLimiterStatistics.TotalSuccessfulLeases"/>,
/// and the aggregate values for the rest of the properties from the <paramref name="limiters"/>.
/// </para>
/// <para>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ public SlidingWindowRateLimiter(SlidingWindowRateLimiterOptions options)
/// <inheritdoc/>
public override RateLimiterStatistics? GetStatistics()
{
ThrowIfDisposed();
return new RateLimiterStatistics()
{
CurrentAvailablePermits = _requestCount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public TokenBucketRateLimiter(TokenBucketRateLimiterOptions options)
/// <inheritdoc/>
public override RateLimiterStatistics? GetStatistics()
{
ThrowIfDisposed();
return new RateLimiterStatistics()
{
CurrentAvailablePermits = _tokenCount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,8 @@ public abstract class BaseRateLimiterTests

[Fact]
public abstract Task GetStatisticsWithZeroPermitCount();

[Fact]
public abstract void GetStatisticsThrowsAfterDispose();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ public void GetStatisticsReturnsNewInstances()
}

[Fact]
public void GetStatisticsHasCorrectValues()
public async Task GetStatisticsHasCorrectValues()
{
using var limiter1 = PartitionedRateLimiter.Create<string, int>(resource =>
{
Expand Down Expand Up @@ -231,7 +231,7 @@ public void GetStatisticsHasCorrectValues()

Assert.Equal(3, stats.CurrentAvailablePermits);
Assert.Equal(0, stats.CurrentQueuedCount);
Assert.Equal(3, stats.TotalSuccessfulLeases);
Assert.Equal(1, stats.TotalSuccessfulLeases);
Assert.Equal(0, stats.TotalFailedLeases);

var lease2 = chainedLimiter.AttemptAcquire("", 10);
Expand All @@ -240,7 +240,7 @@ public void GetStatisticsHasCorrectValues()

Assert.Equal(3, stats.CurrentAvailablePermits);
Assert.Equal(0, stats.CurrentQueuedCount);
Assert.Equal(5, stats.TotalSuccessfulLeases);
Assert.Equal(1, stats.TotalSuccessfulLeases);
Assert.Equal(1, stats.TotalFailedLeases);

var task = chainedLimiter.AcquireAsync("", 10);
Expand All @@ -249,7 +249,18 @@ public void GetStatisticsHasCorrectValues()

Assert.Equal(2, stats.CurrentAvailablePermits);
Assert.Equal(10, stats.CurrentQueuedCount);
Assert.Equal(7, stats.TotalSuccessfulLeases);
Assert.Equal(1, stats.TotalSuccessfulLeases);
Assert.Equal(1, stats.TotalFailedLeases);

lease.Dispose();

lease = await task;
Assert.True(lease.IsAcquired);
stats = chainedLimiter.GetStatistics("");

Assert.Equal(3, stats.CurrentAvailablePermits);
Assert.Equal(0, stats.CurrentQueuedCount);
Assert.Equal(2, stats.TotalSuccessfulLeases);
Assert.Equal(1, stats.TotalFailedLeases);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -917,5 +917,18 @@ public override async Task GetStatisticsWithZeroPermitCount()
Assert.Equal(1, limiter.GetStatistics().TotalFailedLeases);
Assert.Equal(0, limiter.GetStatistics().CurrentAvailablePermits);
}

[Fact]
public override void GetStatisticsThrowsAfterDispose()
{
var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions
{
PermitLimit = 100,
QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
QueueLimit = 50
});
limiter.Dispose();
Assert.Throws<ObjectDisposedException>(limiter.GetStatistics);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1136,5 +1136,20 @@ public override async Task GetStatisticsWithZeroPermitCount()
Assert.Equal(1, limiter.GetStatistics().TotalFailedLeases);
Assert.Equal(0, limiter.GetStatistics().CurrentAvailablePermits);
}

[Fact]
public override void GetStatisticsThrowsAfterDispose()
{
var limiter = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions
{
PermitLimit = 100,
QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
QueueLimit = 50,
Window = TimeSpan.Zero,
AutoReplenishment = false
});
limiter.Dispose();
Assert.Throws<ObjectDisposedException>(limiter.GetStatistics);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1199,5 +1199,21 @@ public override async Task GetStatisticsWithZeroPermitCount()
Assert.Equal(1, limiter.GetStatistics().TotalFailedLeases);
Assert.Equal(0, limiter.GetStatistics().CurrentAvailablePermits);
}

[Fact]
public override void GetStatisticsThrowsAfterDispose()
{
var limiter = new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions
{
PermitLimit = 100,
QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
QueueLimit = 50,
Window = TimeSpan.Zero,
SegmentsPerWindow = 3,
AutoReplenishment = false
});
limiter.Dispose();
Assert.Throws<ObjectDisposedException>(limiter.GetStatistics);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1322,5 +1322,21 @@ public override async Task GetStatisticsWithZeroPermitCount()
Assert.Equal(1, limiter.GetStatistics().TotalFailedLeases);
Assert.Equal(0, limiter.GetStatistics().CurrentAvailablePermits);
}

[Fact]
public override void GetStatisticsThrowsAfterDispose()
{
var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions
{
TokenLimit = 100,
QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
QueueLimit = 50,
ReplenishmentPeriod = TimeSpan.Zero,
TokensPerPeriod = 30,
AutoReplenishment = false
});
limiter.Dispose();
Assert.Throws<ObjectDisposedException>(limiter.GetStatistics);
}
}
}

0 comments on commit 955f12c

Please sign in to comment.