All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hotels.bdp.waggledance.extensions.ExtensionBeans Maven / Gradle / Ivy

/**
 * Copyright (C) 2016-2024 Expedia, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hotels.bdp.waggledance.extensions;

import java.io.IOException;
import java.time.Duration;

import org.redisson.Redisson;
import org.redisson.command.CommandAsyncExecutor;
import org.redisson.config.Config;
import org.redisson.connection.ConnectionManager;
import org.redisson.liveobject.core.RedissonObjectBuilder;
import org.redisson.reactive.CommandReactiveService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import io.github.bucket4j.distributed.ExpirationAfterWriteStrategy;
import io.github.bucket4j.distributed.serialization.Mapper;
import io.github.bucket4j.redis.redisson.cas.RedissonBasedProxyManager;
import io.micrometer.core.instrument.MeterRegistry;

import com.hotels.bdp.waggledance.client.ThriftClientFactory;
import com.hotels.bdp.waggledance.extensions.client.ratelimit.BucketBandwidthProvider;
import com.hotels.bdp.waggledance.extensions.client.ratelimit.BucketKeyGenerator;
import com.hotels.bdp.waggledance.extensions.client.ratelimit.BucketService;
import com.hotels.bdp.waggledance.extensions.client.ratelimit.RateLimitingClientFactory;
import com.hotels.bdp.waggledance.extensions.client.ratelimit.RefillType;
import com.hotels.bdp.waggledance.extensions.client.ratelimit.memory.InMemoryBucketService;
import com.hotels.bdp.waggledance.extensions.client.ratelimit.redis.RedisBucketService;

@Configuration
@ConditionalOnProperty(name = "waggledance.extensions.ratelimit.enabled", havingValue = "true")
public class ExtensionBeans {

  private static final String STORAGE_MEMORY = "MEMORY";
  private static final String STORAGE_REDIS = "REDIS";

  @Bean
  public ThriftClientFactory thriftClientFactory(
      ThriftClientFactory defaultWaggleDanceClientFactory,
      BucketService bucketService,
      BucketKeyGenerator bucketKeyGenerator, MeterRegistry meterRegistry) {
    return new RateLimitingClientFactory(defaultWaggleDanceClientFactory, bucketService, bucketKeyGenerator, meterRegistry);
  }

  @Bean
  public BucketKeyGenerator bucketKeyGenerator(
      @Value("${waggledance.extensions.ratelimit.keyPrefix:\"\"}") String keyPrefix) {
    return new BucketKeyGenerator(keyPrefix);
  }

  @ConditionalOnProperty(name = "waggledance.extensions.ratelimit.storage", havingValue = STORAGE_MEMORY)
  @Bean
  public BucketService inMemoryBucketService(BucketBandwidthProvider bucketBandwidthProvider) {
    return new InMemoryBucketService(bucketBandwidthProvider);
  }

  @ConditionalOnProperty(name = "waggledance.extensions.ratelimit.storage", havingValue = STORAGE_REDIS)
  @Bean
  public BucketService redisBucketService(
      BucketBandwidthProvider bucketBandwidthProvider,
      RedissonBasedProxyManager redissonBasedProxyManager) {
    return new RedisBucketService(bucketBandwidthProvider, redissonBasedProxyManager);
  }

  @ConditionalOnProperty(name = "waggledance.extensions.ratelimit.storage", havingValue = STORAGE_REDIS)
  @Bean
  public RedissonBasedProxyManager redissonBasedProxyManager(
      @Value("${waggledance.extensions.ratelimit.reddison.embedded.config}") String embeddedConfigString)
    throws IOException {
    Config config = Config.fromYAML(embeddedConfigString);
    Redisson redisson = (Redisson) Redisson.create(config);
    ConnectionManager connectionManager = redisson.getConnectionManager();
    RedissonObjectBuilder objectBuilder = new RedissonObjectBuilder(redisson.reactive());
    CommandAsyncExecutor commandExecutor = new CommandReactiveService(connectionManager, objectBuilder);
    RedissonBasedProxyManager proxyManager = RedissonBasedProxyManager
        .builderFor(commandExecutor)
        .withExpirationStrategy(ExpirationAfterWriteStrategy.basedOnTimeForRefillingBucketUpToMax(Duration.ofHours(24)))
        .withKeyMapper(Mapper.STRING)
        .build();
    return proxyManager;
  }

  @Bean
  public BucketBandwidthProvider bucketBandwidthProvider(
      @Value("${waggledance.extensions.ratelimit.capacity:2000}") long capacity,
      @Value("${waggledance.extensions.ratelimit.tokensPerMinute:1000}") long tokensPerMinute,
      @Value("${waggledance.extensions.ratelimit.refillType:GREEDY}") RefillType refillType) {
    return refillType.createBandwidthProvider(capacity, tokensPerMinute);
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy