Skip to content

Commit c1522a8

Browse files
authored
Merge pull request #160 from cristipufu/fix/token_buckets_multi_permits
Token bucket support for multi permits
2 parents 0817d99 + be9011e commit c1522a8

File tree

3 files changed

+28
-5
lines changed

3 files changed

+28
-5
lines changed

src/RedisRateLimiting/TokenBucket/RedisTokenBucketManager.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public RedisTokenBucketManager(
7676
RateLimitTimestampKey = new RedisKey($"rl:tb:{{{partitionKey}}}:ts");
7777
}
7878

79-
internal async Task<RedisTokenBucketResponse> TryAcquireLeaseAsync()
79+
internal async Task<RedisTokenBucketResponse> TryAcquireLeaseAsync(int permitCount)
8080
{
8181
var database = _connectionMultiplexer.GetDatabase();
8282

@@ -89,7 +89,7 @@ internal async Task<RedisTokenBucketResponse> TryAcquireLeaseAsync()
8989
tokens_per_period = (RedisValue)_options.TokensPerPeriod,
9090
token_limit = (RedisValue)_options.TokenLimit,
9191
replenish_period = (RedisValue)_options.ReplenishmentPeriod.TotalMilliseconds,
92-
permit_count = (RedisValue)1D,
92+
permit_count = (RedisValue)permitCount,
9393
current_time = (RedisValue)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
9494
});
9595

src/RedisRateLimiting/TokenBucket/RedisTokenBucketRateLimiter.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ protected override ValueTask<RateLimitLease> AcquireAsyncCore(int permitCount, C
6262
throw new ArgumentOutOfRangeException(nameof(permitCount), permitCount, string.Format("{0} permit(s) exceeds the permit limit of {1}.", permitCount, _options.TokenLimit));
6363
}
6464

65-
return AcquireAsyncCoreInternal();
65+
return AcquireAsyncCoreInternal(permitCount);
6666
}
6767

6868
protected override RateLimitLease AttemptAcquireCore(int permitCount)
@@ -71,14 +71,14 @@ protected override RateLimitLease AttemptAcquireCore(int permitCount)
7171
return FailedLease;
7272
}
7373

74-
private async ValueTask<RateLimitLease> AcquireAsyncCoreInternal()
74+
private async ValueTask<RateLimitLease> AcquireAsyncCoreInternal(int permitCount)
7575
{
7676
var leaseContext = new TokenBucketLeaseContext
7777
{
7878
Limit = _options.TokenLimit,
7979
};
8080

81-
var response = await _redisManager.TryAcquireLeaseAsync();
81+
var response = await _redisManager.TryAcquireLeaseAsync(permitCount);
8282

8383
leaseContext.Allowed = response.Allowed;
8484
leaseContext.Count = response.Count;

test/RedisRateLimiting.Tests/UnitTests/TokenBucketUnitTests.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,28 @@ public async Task CanAcquireAsyncResource()
100100
using var lease2 = await limiter.AcquireAsync();
101101
Assert.False(lease2.IsAcquired);
102102
}
103+
104+
[Fact]
105+
public async Task CanAcquireMultiPermits()
106+
{
107+
using var limiter = new RedisTokenBucketRateLimiter<string>(
108+
partitionKey: Guid.NewGuid().ToString(),
109+
new RedisTokenBucketRateLimiterOptions
110+
{
111+
TokenLimit = 5,
112+
TokensPerPeriod = 5,
113+
ReplenishmentPeriod = TimeSpan.FromMinutes(1),
114+
ConnectionMultiplexerFactory = Fixture.ConnectionMultiplexerFactory,
115+
});
116+
117+
using var lease = await limiter.AcquireAsync(4);
118+
Assert.True(lease.IsAcquired);
119+
120+
using var lease2 = await limiter.AcquireAsync(3);
121+
Assert.False(lease2.IsAcquired);
122+
123+
using var lease3 = await limiter.AcquireAsync(1);
124+
Assert.True(lease3.IsAcquired);
125+
}
103126
}
104127
}

0 commit comments

Comments
 (0)