Example #1
0
        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");
        }
Example #2
0
        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);
        }
Example #3
0
        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);
        }
Example #4
0
        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);
        }
Example #5
0
        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);
        }
Example #6
0
        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);
        }
Example #7
0
 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");
     }
 }
Example #8
0
 private IBotPolicy <T> CreatePolicyWithResultWithRateLimit <T>(RateLimiterConfiguration configuration) =>
 new BotPolicy <T>(config => config
                   .Configure(botconfig => botconfig
                              .RateLimit(configuration)));
Example #9
0
 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));
        }
Example #11
0
 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);
     }
 }