/// <summary>
 /// Initializes a new instance of <see cref="InMemoryTokenBucketConsumer"/> class.
 /// </summary>
 /// <param name="configuration">
 /// The request rate limiter configuration.
 /// </param>
 /// <param name="logger">
 /// The logger.
 /// </param>
 public InMemoryTokenBucketConsumer(
     RequestRateLimiterConfiguration configuration,
     ILogger <InMemoryTokenBucketConsumer> logger)
 {
     _configuration = configuration;
     _logger        = logger;
 }
Exemplo n.º 2
0
 /// <summary>
 /// Initializes a new instance of <see cref="RedisTokenBucketConsumer"/> class.
 /// </summary>
 /// <param name="redisClient">
 /// The Redis API client.
 /// </param>
 /// <param name="configuration">
 /// The request rate limiter configuration.
 /// </param>
 /// <param name="logger">
 /// The logger.
 /// </param>
 public RedisTokenBucketConsumer(
     IConnectionMultiplexer redisClient,
     RequestRateLimiterConfiguration configuration,
     ILogger <RedisTokenBucketConsumer> logger)
 {
     _redisClient   = redisClient;
     _configuration = configuration;
     _logger        = logger;
 }
Exemplo n.º 3
0
        public void ConfigurationValidatedWhileUsingDefaultOptions()
        {
            // Given
            var configuration = new RequestRateLimiterConfiguration();

            // When configuration is validated
            var exception = Record.Exception(() => configuration.Validate());

            // Then it should successfully validate
            exception.Should().BeNull();
        }
Exemplo n.º 4
0
        public void ConfigurationValidatedWithBurstingSetToZero()
        {
            // Given
            var configuration = new RequestRateLimiterConfiguration
            {
                Bursting = 0
            };

            // When configuration is validated
            var exception = Record.Exception(() => configuration.Validate());

            // Then it should throw ArgumentOutOfRangeException
            exception.Should().NotBeNull();
            exception.Should().BeOfType <ArgumentOutOfRangeException>();
            exception.Message.Should().Contain("Bursting must be greater than 0.");
            ((ArgumentOutOfRangeException)exception).ParamName.Should().Be("Bursting");
        }
Exemplo n.º 5
0
        public void ConfigurationValidatedWithKeysPrefixSetToNull()
        {
            // Given
            var configuration = new RequestRateLimiterConfiguration
            {
                KeysPrefix = null
            };

            // When configuration is validated
            var exception = Record.Exception(() => configuration.Validate());

            // Then it should throw ArgumentNullException
            exception.Should().NotBeNull();
            exception.Should().BeOfType <ArgumentNullException>();
            exception.Message.Should().Contain("Keys prefix must be provided.");
            ((ArgumentNullException)exception).ParamName.Should().Be("KeysPrefix");
        }
Exemplo n.º 6
0
        public async void ATokenIsConsumedForTheFirstTime()
        {
            // Given
            const string ClientId  = "tester";
            const int    Requested = 1;

            var configuration = new RequestRateLimiterConfiguration();
            var loggerMock    = new Mock <ILogger <InMemoryTokenBucketConsumer> >();
            var consumer      = new InMemoryTokenBucketConsumer(configuration, loggerMock.Object);

            var capacity = configuration.AverageRate * configuration.Bursting;

            // When a token is consumed
            var response = await consumer.ConsumeAsync(ClientId, Requested);

            // Then it should allow token consumption
            response.IsAllowed.Should().BeTrue();
            response.Limit.Should().Be(capacity);
            response.Remaining.Should().Be(capacity - 1);
        }
Exemplo n.º 7
0
        public async void UnexpectedExceptionThrownByRedis()
        {
            // Given
            var connectionMultplexerMock = new Mock <IConnectionMultiplexer>();
            var configuration            = new RequestRateLimiterConfiguration();
            var loggerMock = new Mock <ILogger <RedisTokenBucketConsumer> >();

            connectionMultplexerMock.Setup(mock => mock.GetDatabase(
                                               Moq.It.IsAny <int>(),
                                               Moq.It.IsAny <object>()))
            .Throws <Exception>();

            var consumer = new RedisTokenBucketConsumer(
                connectionMultplexerMock.Object,
                configuration,
                loggerMock.Object);

            // When a request is consumed
            var result = await consumer.ConsumeAsync(
                Guid.NewGuid().ToString(),
                1);

            // Then it should log a warning
            loggerMock.Verify(mock => mock.Log(
                                  LogLevel.Warning,
                                  Moq.It.IsAny <EventId>(),
                                  Moq.It.IsAny <FormattedLogValues>(),
                                  Moq.It.IsAny <Exception>(),
                                  Moq.It.IsAny <Func <object, Exception, string> >()));

            // And it should allow the request
            var capacity = configuration.AverageRate * configuration.Bursting;

            result.IsAllowed.Should().BeTrue();
            result.Limit.Should().Be(capacity);
            result.Remaining.Should().Be(capacity - 1);
        }