public async Task RateLimiter_WhenOneMoreCallThanLimitMadeInTimespan_LastCallTimeIsGreaterThanTimespanAfterFirstCall() { var callTimes = new List <DateTime>(); Func <Task> callLogger = () => { callTimes.Add(ReferenceTime.UtcNow); return(Task.CompletedTask); }; var rateLimitTimespan = TimeSpan.FromMilliseconds(200); var config = new RateLimiterConfiguration(); config.AddRateLimit(new StandardRateLimit(3, rateLimitTimespan)); var limiter = config.BuildRateLimiter(); await Task.WhenAll(new List <Task> { limiter.LimitAsync(callLogger), limiter.LimitAsync(callLogger), limiter.LimitAsync(callLogger), limiter.LimitAsync(callLogger) }); var firstCall = callTimes.Min(); var lastCall = callTimes.Max(); var elapsedTimeBetweenFirstAndLastCall = lastCall.Subtract(firstCall); Assert.True( elapsedTimeBetweenFirstAndLastCall.TotalMilliseconds > rateLimitTimespan.TotalMilliseconds, $"Time between first and last call should be at least {rateLimitTimespan.TotalMilliseconds} milliseconds but was '{elapsedTimeBetweenFirstAndLastCall.TotalMilliseconds}' milliseconds"); }
public async Task RateLimiter_WhenOneMoreCallThanLimitMadeInTimespan_SaysReachedLimitOnce() { var config = new RateLimiterConfiguration(); config.AddRateLimit(new StandardRateLimit(3, TimeSpan.FromMilliseconds(200))); var limiter = config.BuildRateLimiter(); var timesLimitReached = 0; Func <Task> callLogger = () => { if (limiter.HasReachedLimit) { timesLimitReached++; } return(Task.CompletedTask); }; var rateLimitTimespan = TimeSpan.FromMilliseconds(500); await Task.WhenAll(new List <Task> { limiter.LimitAsync(callLogger), limiter.LimitAsync(callLogger), limiter.LimitAsync(callLogger), limiter.LimitAsync(callLogger) }); Assert.Equal(1, timesLimitReached); }
public async Task RateLimiter_WhenOneCallMadeToLimitAsync_AddsCallToCallTracker() { var config = new RateLimiterConfiguration(); config.AddRateLimit(new StandardRateLimit(5, TimeSpan.FromSeconds(1))); var limiter = config.BuildRateLimiter(); await limiter.LimitAsync(() => Task.CompletedTask); Assert.Single(limiter.CallHistory); }
public void RateLimiter_WhenOneCallMadeToLimit_AddsCallToCallTracker() { var config = new RateLimiterConfiguration(); config.AddRateLimit(new StandardRateLimit(5, TimeSpan.FromSeconds(1))); var limiter = config.BuildRateLimiter(); limiter.Limit(() => { }); Assert.Single(limiter.CallHistory); }
public async Task RateLimiter_WhenOneCallMadeToLimitAsyncWithReturn_AddsCallToCallTracker() { var config = new RateLimiterConfiguration(); config.AddRateLimit(new StandardRateLimit(5, TimeSpan.FromSeconds(1))); Func <Task <int> > returningMethod = async() => await Task.FromResult(5); var limiter = config.BuildRateLimiter(); var result = await limiter.Limit(returningMethod); Assert.Single(limiter.CallHistory); }
public void RateLimiter_WhenOneCallMadeToLimitWithReturn_AddsCallToCallTracker() { var config = new RateLimiterConfiguration(); config.AddRateLimit(new StandardRateLimit(5, TimeSpan.FromSeconds(1))); Func <int> returningMethod = () => 5; var limiter = config.BuildRateLimiter(); var result = limiter.Limit(returningMethod); Assert.Single(limiter.CallHistory); }
public override void Execute(IrcMessage message, string args) { string[] elem = args.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (elem.Length != 1 && elem.Length != 3) { throw new Exception("Expected syntaxis: " + GetKeyword() + " <command> [<subscriber> <other>]"); } RateLimiter limiter = null; if (!CommandHandler.GetCommands().ContainsKey(elem[0])) { string special = elem[0].ToLower(); if (special == "chat") { limiter = Alice.limiter; elem[0] = "flavor-chat"; } else if (special == "joke") { limiter = Alice.joke_limiter; elem[0] = "auto-joking"; } else if (special == "user") { limiter = UserLimiter; elem[0] = "command interval per user"; } else throw new Exception("Command not found"); } else { limiter = CommandHandler.GetCommands()[elem[0]].Limiter; } if (elem.Length == 3) { RateLimiterConfiguration config = new RateLimiterConfiguration(); config.sub = double.Parse(elem[1]); config.nor = double.Parse(elem[2]); limiter.Configuration = config; message.ReplyAuto("Limit for " + elem[0] + " has been set to once every " + config.sub.ToString() + "s for subscribers and " + config.nor.ToString() + "s for other users"); } else { RateLimiterConfiguration config = limiter.Configuration; message.ReplyAuto("Limit for " + elem[0] + " is set to once every " + config.sub.ToString() + "s for subscribers and " + config.nor.ToString() + "s for other users"); } }
private IBotPolicy <T> CreatePolicyWithResultWithRateLimit <T>(RateLimiterConfiguration configuration) => new BotPolicy <T>(config => config .Configure(botconfig => botconfig .RateLimit(configuration)));
private IBotPolicy CreatePolicyWithRateLimit(RateLimiterConfiguration configuration) => new BotPolicy(config => config .Configure(botconfig => botconfig .RateLimit(configuration)));
/// <summary> /// Adds a rate limiter bot to a <see cref="IBotPolicy"/> with the given configuration. /// </summary> /// <typeparam name="TResult">The result type of the passed operation.</typeparam> /// <param name="builder">The policy builder.</param> /// <param name="configuration">The configuraton.</param> /// <returns>The policy builder.</returns> /// <example> /// <code> /// builder.RateLimit(new RetryConfiguration() /// .MaxAmountOfAllowedOperations(10) /// .WithinTimeInterval(TimeSpan.FromSeconds(5)) /// .UseStrategy(RateLimiterStrategy.SlidingWindow)) /// </code> /// </example> public static IBotPolicyBuilder <TResult> RateLimit <TResult>(this IBotPolicyBuilder <TResult> builder, RateLimiterConfiguration configuration) { Shield.EnsureNotNull(configuration, nameof(configuration)); return(builder.AddBot((innerBot, rateLimitConfig) => new RateLimiterBot <TResult>(innerBot, rateLimitConfig), configuration)); }
static void PushLimiter(RateLimiterConfiguration config) { RateLimiterConfiguration other = State.LimiterList.Lookup(config.key); if (other == null || other.nor != config.nor || other.sub != config.sub) { if (other != null) State.LimiterList.Remove(other); State.LimiterList.Add(config); } }