From 72e51053e45edb6d6b7fcef6661596f94ca362a0 Mon Sep 17 00:00:00 2001 From: MRomeh Date: Thu, 9 Jan 2020 15:08:04 +0100 Subject: [PATCH] Issue 773: Aded support to rate limiter configuration customization (#793) --- .../common/CompositeCustomizer.java | 33 +++++++++++++++++ .../common/CustomizerWithName.java | 12 +++++++ .../CircuitBreakerConfigCustomizer.java | 7 ++-- ...CircuitBreakerConfigurationProperties.java | 17 +++++---- .../CompositeCircuitBreakerCustomizer.java | 36 ------------------- .../CompositeRateLimiterCustomizer.java | 34 ++++++++++++++++++ .../RateLimiterConfigCustomizer.java | 18 ++++++++++ .../RateLimiterConfigurationProperties.java | 31 ++++++++++------ .../configuration/RetryConfigCustomizer.java | 8 ++--- ...uitBreakerConfigurationPropertiesTest.java | 5 +-- ...ateLimiterConfigurationPropertiesTest.java | 18 ++++++---- .../ratpack/Resilience4jModule.java | 14 +++++--- ...cuitBreakerConfigurationOnMissingBean.java | 5 +-- ...RateLimiterConfigurationOnMissingBean.java | 6 ++-- .../resilience4j/SpringBootCommonTest.java | 8 +++-- ...cuitBreakerConfigurationOnMissingBean.java | 6 ++-- ...RateLimiterConfigurationOnMissingBean.java | 14 ++++++++ ...cuitBreakerConfigurationOnMissingBean.java | 6 ++-- ...RateLimiterConfigurationOnMissingBean.java | 12 +++++++ .../RateLimiterAutoConfigurationTest.java | 15 +++++--- .../service/test/TestApplication.java | 18 ++++++++++ .../src/test/resources/application.yaml | 4 +++ ...reshScopedCircuitBreakerConfiguration.java | 5 +-- ...RefreshScopedRateLimiterConfiguration.java | 6 ++-- ...ScopedCircuitBreakerConfigurationTest.java | 4 +-- ...eshScopedRateLimiterConfigurationTest.java | 5 ++- .../CircuitBreakerConfiguration.java | 12 +++---- .../configure/RateLimiterConfiguration.java | 24 ++++++++++--- .../CircuitBreakerConfigurationTest.java | 7 ++-- .../RateLimiterConfigurationTest.java | 15 ++++++-- 30 files changed, 287 insertions(+), 118 deletions(-) create mode 100644 resilience4j-framework-common/src/main/java/io/github/resilience4j/common/CompositeCustomizer.java create mode 100644 resilience4j-framework-common/src/main/java/io/github/resilience4j/common/CustomizerWithName.java delete mode 100644 resilience4j-framework-common/src/main/java/io/github/resilience4j/common/circuitbreaker/configuration/CompositeCircuitBreakerCustomizer.java create mode 100644 resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/CompositeRateLimiterCustomizer.java create mode 100644 resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigCustomizer.java diff --git a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/CompositeCustomizer.java b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/CompositeCustomizer.java new file mode 100644 index 0000000000..063d3fc849 --- /dev/null +++ b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/CompositeCustomizer.java @@ -0,0 +1,33 @@ +package io.github.resilience4j.common; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * the composite of any spring resilience4j type config customizer implementations. + */ +public class CompositeCustomizer { + + private final Map customizerMap = new HashMap<>(); + + public CompositeCustomizer(List customizers) { + if (customizers != null && !customizers.isEmpty()) { + customizerMap.putAll(customizers.stream() + .collect( + Collectors.toMap(CustomizerWithName::name, Function.identity()))); + } + } + + /** + * @param instanceName the resilience4j instance name + * @return the found spring customizer if any . + */ + public Optional getCustomizer(String instanceName) { + return Optional.ofNullable(customizerMap.get(instanceName)); + } + +} diff --git a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/CustomizerWithName.java b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/CustomizerWithName.java new file mode 100644 index 0000000000..828a550909 --- /dev/null +++ b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/CustomizerWithName.java @@ -0,0 +1,12 @@ +package io.github.resilience4j.common; + +/** + * common interface for different spring config customizers implementation + */ +public interface CustomizerWithName { + + /** + * @return name of the resilience4j type instance to be customized + */ + String name(); +} diff --git a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigCustomizer.java b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigCustomizer.java index 45874c76f4..5716cf813c 100644 --- a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigCustomizer.java +++ b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigCustomizer.java @@ -1,11 +1,12 @@ package io.github.resilience4j.common.circuitbreaker.configuration; import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig; +import io.github.resilience4j.common.CustomizerWithName; /** * Enable customization circuit breaker configuration builders programmatically. */ -public interface CircuitBreakerConfigCustomizer { +public interface CircuitBreakerConfigCustomizer extends CustomizerWithName { /** * Customize circuit breaker configuration builder. @@ -14,8 +15,4 @@ public interface CircuitBreakerConfigCustomizer { */ void customize(CircuitBreakerConfig.Builder configBuilder); - /** - * @return name of the circuit breaker instance to be customized - */ - String name(); } diff --git a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigurationProperties.java b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigurationProperties.java index 509593d773..9bd87ef3a1 100644 --- a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigurationProperties.java +++ b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigurationProperties.java @@ -20,6 +20,7 @@ import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.Builder; import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.SlidingWindowType; import io.github.resilience4j.common.CommonProperties; +import io.github.resilience4j.common.CompositeCustomizer; import io.github.resilience4j.common.utils.ConfigUtils; import io.github.resilience4j.core.ClassUtils; import io.github.resilience4j.core.ConfigurationNotFoundException; @@ -52,7 +53,7 @@ public Optional findCircuitBreakerProperties(String name) { public CircuitBreakerConfig createCircuitBreakerConfig(String backendName, InstanceProperties instanceProperties, - CompositeCircuitBreakerCustomizer compositeCircuitBreakerCustomizer) { + CompositeCustomizer compositeCircuitBreakerCustomizer) { if (StringUtils.isNotEmpty(instanceProperties.getBaseConfig())) { InstanceProperties baseProperties = configs.get(instanceProperties.getBaseConfig()); if (baseProperties == null) { @@ -68,16 +69,20 @@ public CircuitBreakerConfig createCircuitBreakerConfig(String backendName, private CircuitBreakerConfig buildConfigFromBaseConfig(InstanceProperties instanceProperties, InstanceProperties baseProperties, - CompositeCircuitBreakerCustomizer customizerMap, String backendName) { + CompositeCustomizer compositeCircuitBreakerCustomizer, + String backendName) { ConfigUtils.mergePropertiesIfAny(instanceProperties, baseProperties); - CircuitBreakerConfig baseConfig = buildConfig(custom(), baseProperties, customizerMap, + CircuitBreakerConfig baseConfig = buildConfig(custom(), baseProperties, + compositeCircuitBreakerCustomizer, + backendName); + return buildConfig(from(baseConfig), instanceProperties, compositeCircuitBreakerCustomizer, backendName); - return buildConfig(from(baseConfig), instanceProperties, customizerMap, backendName); } @SuppressWarnings("deprecation") // deprecated API use left for backward compatibility private CircuitBreakerConfig buildConfig(Builder builder, InstanceProperties properties, - CompositeCircuitBreakerCustomizer compositeCircuitBreakerCustomizer, String backendName) { + CompositeCustomizer compositeCircuitBreakerCustomizer, + String backendName) { if (properties == null) { return builder.build(); } @@ -147,7 +152,7 @@ private CircuitBreakerConfig buildConfig(Builder builder, InstanceProperties pro builder.automaticTransitionFromOpenToHalfOpenEnabled( properties.automaticTransitionFromOpenToHalfOpenEnabled); } - compositeCircuitBreakerCustomizer.getCircuitBreakerConfigCustomizer(backendName).ifPresent( + compositeCircuitBreakerCustomizer.getCustomizer(backendName).ifPresent( circuitBreakerConfigCustomizer -> circuitBreakerConfigCustomizer.customize(builder)); return builder.build(); } diff --git a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/circuitbreaker/configuration/CompositeCircuitBreakerCustomizer.java b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/circuitbreaker/configuration/CompositeCircuitBreakerCustomizer.java deleted file mode 100644 index 4492f586b4..0000000000 --- a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/circuitbreaker/configuration/CompositeCircuitBreakerCustomizer.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.github.resilience4j.common.circuitbreaker.configuration; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * the composite of any circuit breaker {@link CircuitBreakerConfigCustomizer} implementations. - */ -public class CompositeCircuitBreakerCustomizer { - - private final Map customizerMap = new HashMap<>(); - - public CompositeCircuitBreakerCustomizer(List customizers) { - - if (customizers != null && !customizers.isEmpty()) { - customizerMap.putAll(customizers.stream() - .collect( - Collectors.toMap(CircuitBreakerConfigCustomizer::name, Function.identity()))); - } - - } - - /** - * @param circuitBreakerInstanceName the circuit breaker instance name - * @return the found {@link CircuitBreakerConfigCustomizer} if any . - */ - public Optional getCircuitBreakerConfigCustomizer( - String circuitBreakerInstanceName) { - return Optional.ofNullable(customizerMap.get(circuitBreakerInstanceName)); - } - -} diff --git a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/CompositeRateLimiterCustomizer.java b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/CompositeRateLimiterCustomizer.java new file mode 100644 index 0000000000..12b383a39a --- /dev/null +++ b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/CompositeRateLimiterCustomizer.java @@ -0,0 +1,34 @@ +package io.github.resilience4j.common.ratelimiter.configuration; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * the composite of any rate limiter {@link RateLimiterConfigCustomizer} implementations. + */ +public class CompositeRateLimiterCustomizer { + + private final Map customizerMap = new HashMap<>(); + + public CompositeRateLimiterCustomizer(List customizers) { + if (customizers != null && !customizers.isEmpty()) { + customizerMap.putAll(customizers.stream() + .collect( + Collectors.toMap(RateLimiterConfigCustomizer::name, Function.identity()))); + } + } + + /** + * @param rateLimiterInstanceName the rate limiter instance name + * @return the found {@link RateLimiterConfigCustomizer} if any . + */ + public Optional getRateLimiterConfigCustomizer( + String rateLimiterInstanceName) { + return Optional.ofNullable(customizerMap.get(rateLimiterInstanceName)); + } + +} diff --git a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigCustomizer.java b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigCustomizer.java new file mode 100644 index 0000000000..6278a94eac --- /dev/null +++ b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigCustomizer.java @@ -0,0 +1,18 @@ +package io.github.resilience4j.common.ratelimiter.configuration; + +import io.github.resilience4j.common.CustomizerWithName; +import io.github.resilience4j.ratelimiter.RateLimiterConfig; + +/** + * Enable customization rate limiter configuration builders programmatically. + */ +public interface RateLimiterConfigCustomizer extends CustomizerWithName { + + /** + * Customize rate limiter configuration builder. + * + * @param configBuilder to be customized + */ + void customize(RateLimiterConfig.Builder configBuilder); + +} diff --git a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationProperties.java b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationProperties.java index 26c03047ed..d5614af015 100644 --- a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationProperties.java +++ b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationProperties.java @@ -28,7 +28,7 @@ import java.util.Objects; import java.util.Optional; -public class RateLimiterConfigurationProperties extends CommonProperties{ +public class RateLimiterConfigurationProperties extends CommonProperties { private Map instances = new HashMap<>(); private Map configs = new HashMap<>(); @@ -42,7 +42,8 @@ public Optional findRateLimiterProperties(String name) { } public RateLimiterConfig createRateLimiterConfig( - @Nullable InstanceProperties instanceProperties) { + @Nullable InstanceProperties instanceProperties, + CompositeRateLimiterCustomizer compositeRateLimiterCustomizer, String instanceName) { if (instanceProperties == null) { return RateLimiterConfig.ofDefaults(); } @@ -51,21 +52,26 @@ public RateLimiterConfig createRateLimiterConfig( if (baseProperties == null) { throw new ConfigurationNotFoundException(instanceProperties.getBaseConfig()); } - return buildConfigFromBaseConfig(baseProperties, instanceProperties); + return buildConfigFromBaseConfig(baseProperties, instanceProperties, + compositeRateLimiterCustomizer, instanceName); } - return buildRateLimiterConfig(RateLimiterConfig.custom(), instanceProperties); + return buildRateLimiterConfig(RateLimiterConfig.custom(), instanceProperties, + compositeRateLimiterCustomizer, instanceName); } private RateLimiterConfig buildConfigFromBaseConfig(InstanceProperties baseProperties, - InstanceProperties instanceProperties) { + InstanceProperties instanceProperties, + CompositeRateLimiterCustomizer compositeRateLimiterCustomizer, String instanceName) { ConfigUtils.mergePropertiesIfAny(baseProperties, instanceProperties); RateLimiterConfig baseConfig = buildRateLimiterConfig(RateLimiterConfig.custom(), - baseProperties); - return buildRateLimiterConfig(RateLimiterConfig.from(baseConfig), instanceProperties); + baseProperties, compositeRateLimiterCustomizer, instanceName); + return buildRateLimiterConfig(RateLimiterConfig.from(baseConfig), instanceProperties, + compositeRateLimiterCustomizer, instanceName); } private RateLimiterConfig buildRateLimiterConfig(RateLimiterConfig.Builder builder, - @Nullable InstanceProperties instanceProperties) { + @Nullable InstanceProperties instanceProperties, + CompositeRateLimiterCustomizer compositeRateLimiterCustomizer, String instanceName) { if (instanceProperties == null) { return builder.build(); } @@ -85,7 +91,8 @@ private RateLimiterConfig buildRateLimiterConfig(RateLimiterConfig.Builder build if (instanceProperties.getWritableStackTraceEnabled() != null) { builder.writableStackTraceEnabled(instanceProperties.getWritableStackTraceEnabled()); } - + compositeRateLimiterCustomizer.getRateLimiterConfigCustomizer(instanceName).ifPresent( + rateLimiterConfigCustomizer -> rateLimiterConfigCustomizer.customize(builder)); return builder.build(); } @@ -93,8 +100,10 @@ private InstanceProperties getLimiterProperties(String limiter) { return instances.get(limiter); } - public RateLimiterConfig createRateLimiterConfig(String limiter) { - return createRateLimiterConfig(getLimiterProperties(limiter)); + public RateLimiterConfig createRateLimiterConfig(String limiter, + CompositeRateLimiterCustomizer compositeRateLimiterCustomizer) { + return createRateLimiterConfig(getLimiterProperties(limiter), + compositeRateLimiterCustomizer, limiter); } @Nullable diff --git a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/retry/configuration/RetryConfigCustomizer.java b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/retry/configuration/RetryConfigCustomizer.java index 6d140f7b99..17e4d93c1e 100644 --- a/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/retry/configuration/RetryConfigCustomizer.java +++ b/resilience4j-framework-common/src/main/java/io/github/resilience4j/common/retry/configuration/RetryConfigCustomizer.java @@ -1,11 +1,12 @@ package io.github.resilience4j.common.retry.configuration; +import io.github.resilience4j.common.CustomizerWithName; import io.github.resilience4j.retry.RetryConfig; /** * Enable customization retry configuration builders programmatically. */ -public interface RetryConfigCustomizer { +public interface RetryConfigCustomizer extends CustomizerWithName { /** * Retry configuration builder. @@ -13,9 +14,4 @@ public interface RetryConfigCustomizer { * @param configBuilder to be customized */ void customize(RetryConfig.Builder configBuilder); - - /** - * @return name of the retry instance to be customized - */ - String name(); } diff --git a/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigurationPropertiesTest.java b/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigurationPropertiesTest.java index 9ad2d7745f..e3a63510b1 100644 --- a/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigurationPropertiesTest.java +++ b/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/circuitbreaker/configuration/CircuitBreakerConfigurationPropertiesTest.java @@ -16,6 +16,7 @@ package io.github.resilience4j.common.circuitbreaker.configuration; import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig; +import io.github.resilience4j.common.CompositeCustomizer; import io.github.resilience4j.common.RecordFailurePredicate; import io.github.resilience4j.core.ConfigurationNotFoundException; import org.junit.Test; @@ -286,7 +287,7 @@ public void testIllegalArgumentOnSlowCallDurationThreshold() { defaultProperties.setSlowCallDurationThreshold(Duration.ZERO); } - private CompositeCircuitBreakerCustomizer compositeCircuitBreakerCustomizer() { - return new CompositeCircuitBreakerCustomizer(Collections.emptyList()); + private CompositeCustomizer compositeCircuitBreakerCustomizer() { + return new CompositeCustomizer<>(Collections.emptyList()); } } diff --git a/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationPropertiesTest.java b/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationPropertiesTest.java index 76694c1080..a874dc724b 100644 --- a/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationPropertiesTest.java +++ b/resilience4j-framework-common/src/test/java/io/github/resilience4j/common/ratelimiter/configuration/RateLimiterConfigurationPropertiesTest.java @@ -20,6 +20,7 @@ import org.junit.Test; import java.time.Duration; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -58,13 +59,13 @@ public void testRateLimiterRegistry() { assertThat(rateLimiterConfigurationProperties.getInstances().size()).isEqualTo(2); assertThat(rateLimiterConfigurationProperties.getLimiters().size()).isEqualTo(2); RateLimiterConfig rateLimiter = rateLimiterConfigurationProperties - .createRateLimiterConfig("backend1"); + .createRateLimiterConfig("backend1", compositeRateLimiterCustomizer()); assertThat(rateLimiter).isNotNull(); assertThat(rateLimiter.getLimitForPeriod()).isEqualTo(2); assertThat(rateLimiter.isWritableStackTraceEnabled()).isFalse(); RateLimiterConfig rateLimiter2 = rateLimiterConfigurationProperties - .createRateLimiterConfig("backend2"); + .createRateLimiterConfig("backend2", compositeRateLimiterCustomizer()); assertThat(rateLimiter2).isNotNull(); assertThat(rateLimiter2.getLimitForPeriod()).isEqualTo(4); assertThat(rateLimiter2.isWritableStackTraceEnabled()).isTrue(); @@ -112,7 +113,7 @@ public void testCreateRateLimiterRegistryWithSharedConfigs() { // Should get default config and override LimitForPeriod RateLimiterConfig rateLimiter1 = rateLimiterConfigurationProperties - .createRateLimiterConfig("backendWithDefaultConfig"); + .createRateLimiterConfig("backendWithDefaultConfig", compositeRateLimiterCustomizer()); assertThat(rateLimiter1).isNotNull(); assertThat(rateLimiter1.getLimitForPeriod()).isEqualTo(200); assertThat(rateLimiter1.getLimitRefreshPeriod()).isEqualTo(Duration.ofMillis(5)); @@ -120,7 +121,7 @@ public void testCreateRateLimiterRegistryWithSharedConfigs() { // Should get shared config and override LimitForPeriod RateLimiterConfig rateLimiter2 = rateLimiterConfigurationProperties - .createRateLimiterConfig("backendWithSharedConfig"); + .createRateLimiterConfig("backendWithSharedConfig", compositeRateLimiterCustomizer()); assertThat(rateLimiter2).isNotNull(); assertThat(rateLimiter2.getLimitForPeriod()).isEqualTo(300); assertThat(rateLimiter2.getLimitRefreshPeriod()).isEqualTo(Duration.ofMillis(6)); @@ -128,7 +129,7 @@ public void testCreateRateLimiterRegistryWithSharedConfigs() { // Unknown backend should get default config of Registry RateLimiterConfig rerateLimiter3 = rateLimiterConfigurationProperties - .createRateLimiterConfig("unknownBackend"); + .createRateLimiterConfig("unknownBackend", compositeRateLimiterCustomizer()); assertThat(rerateLimiter3).isNotNull(); assertThat(rerateLimiter3.getLimitForPeriod()).isEqualTo(50); assertThat(rerateLimiter3.isWritableStackTraceEnabled()).isTrue(); @@ -146,7 +147,8 @@ public void testCreateRateLimiterRegistryWithUnknownConfig() { //When assertThatThrownBy( - () -> rateLimiterConfigurationProperties.createRateLimiterConfig("backend")) + () -> rateLimiterConfigurationProperties + .createRateLimiterConfig("backend", compositeRateLimiterCustomizer())) .isInstanceOf(ConfigurationNotFoundException.class) .hasMessage("Configuration with name 'unknownConfig' does not exist"); } @@ -176,4 +178,8 @@ public void testIllegalArgumentOnEventConsumerBufferSize() { defaultProperties.setEventConsumerBufferSize(-1); } + private CompositeRateLimiterCustomizer compositeRateLimiterCustomizer() { + return new CompositeRateLimiterCustomizer(Collections.emptyList()); + } + } \ No newline at end of file diff --git a/resilience4j-ratpack/src/main/java/io/github/resilience4j/ratpack/Resilience4jModule.java b/resilience4j-ratpack/src/main/java/io/github/resilience4j/ratpack/Resilience4jModule.java index 543d282ab1..52b9d784a9 100644 --- a/resilience4j-ratpack/src/main/java/io/github/resilience4j/ratpack/Resilience4jModule.java +++ b/resilience4j-ratpack/src/main/java/io/github/resilience4j/ratpack/Resilience4jModule.java @@ -31,10 +31,11 @@ import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry; import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker; import io.github.resilience4j.circuitbreaker.event.CircuitBreakerEvent; +import io.github.resilience4j.common.CompositeCustomizer; import io.github.resilience4j.common.bulkhead.configuration.BulkheadConfigurationProperties; import io.github.resilience4j.common.bulkhead.configuration.ThreadPoolBulkheadConfigurationProperties; import io.github.resilience4j.common.circuitbreaker.configuration.CircuitBreakerConfigurationProperties; -import io.github.resilience4j.common.circuitbreaker.configuration.CompositeCircuitBreakerCustomizer; +import io.github.resilience4j.common.ratelimiter.configuration.CompositeRateLimiterCustomizer; import io.github.resilience4j.common.ratelimiter.configuration.RateLimiterConfigurationProperties; import io.github.resilience4j.common.retry.configuration.CompositeRetryCustomizer; import io.github.resilience4j.common.retry.configuration.RetryConfigurationProperties; @@ -210,7 +211,7 @@ public CircuitBreakerRegistry get() { .entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> circuitBreakerProperties .createCircuitBreakerConfig(entry.getKey(), entry.getValue(), - new CompositeCircuitBreakerCustomizer(Collections.emptyList())))); + new CompositeCustomizer<>(Collections.emptyList())))); CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.of(configs); // build circuit breakers @@ -220,7 +221,7 @@ public CircuitBreakerRegistry get() { circuitBreakerRegistry.circuitBreaker(name, circuitBreakerProperties.createCircuitBreakerConfig(name, circuitBreakerConfig, - new CompositeCircuitBreakerCustomizer(Collections.emptyList()))); + new CompositeCustomizer<>(Collections.emptyList()))); if (endpointsConfig.getCircuitbreaker().isEnabled()) { circuitBreaker.getEventPublisher().onEvent(eventConsumerRegistry .createEventConsumer(name, @@ -252,7 +253,9 @@ public RateLimiterRegistry get() { .getRatelimiter(); Map configs = rateLimiterProperties.getConfigs() .entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, - entry -> rateLimiterProperties.createRateLimiterConfig(entry.getValue()))); + entry -> rateLimiterProperties.createRateLimiterConfig(entry.getValue(), + new CompositeRateLimiterCustomizer(Collections.emptyList()), + entry.getKey()))); RateLimiterRegistry rateLimiterRegistry = RateLimiterRegistry.of(configs); // build ratelimiters @@ -260,7 +263,8 @@ public RateLimiterRegistry get() { rateLimiterProperties.getInstances().forEach((name, rateLimiterConfig) -> { io.github.resilience4j.ratelimiter.RateLimiter rateLimiter = rateLimiterRegistry.rateLimiter(name, - rateLimiterProperties.createRateLimiterConfig(rateLimiterConfig)); + rateLimiterProperties.createRateLimiterConfig(rateLimiterConfig, + new CompositeRateLimiterCustomizer(Collections.emptyList()), name)); if (endpointsConfig.getRatelimiter().isEnabled()) { rateLimiter.getEventPublisher().onEvent(eventConsumerRegistry .createEventConsumer(name, diff --git a/resilience4j-spring-boot-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractCircuitBreakerConfigurationOnMissingBean.java b/resilience4j-spring-boot-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractCircuitBreakerConfigurationOnMissingBean.java index 8053b2fab6..9fab3709e6 100644 --- a/resilience4j-spring-boot-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractCircuitBreakerConfigurationOnMissingBean.java +++ b/resilience4j-spring-boot-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractCircuitBreakerConfigurationOnMissingBean.java @@ -19,7 +19,8 @@ import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry; import io.github.resilience4j.circuitbreaker.configure.*; import io.github.resilience4j.circuitbreaker.event.CircuitBreakerEvent; -import io.github.resilience4j.common.circuitbreaker.configuration.CompositeCircuitBreakerCustomizer; +import io.github.resilience4j.common.CompositeCustomizer; +import io.github.resilience4j.common.circuitbreaker.configuration.CircuitBreakerConfigCustomizer; import io.github.resilience4j.consumer.EventConsumerRegistry; import io.github.resilience4j.core.registry.RegistryEventConsumer; import io.github.resilience4j.fallback.FallbackDecorators; @@ -53,7 +54,7 @@ public AbstractCircuitBreakerConfigurationOnMissingBean( public CircuitBreakerRegistry circuitBreakerRegistry( EventConsumerRegistry eventConsumerRegistry, RegistryEventConsumer circuitBreakerRegistryEventConsumer, - CompositeCircuitBreakerCustomizer compositeCircuitBreakerCustomizer) { + CompositeCustomizer compositeCircuitBreakerCustomizer) { return circuitBreakerConfiguration .circuitBreakerRegistry(eventConsumerRegistry, circuitBreakerRegistryEventConsumer, compositeCircuitBreakerCustomizer); diff --git a/resilience4j-spring-boot-common/src/main/java/io/github/resilience4j/ratelimiter/autoconfigure/AbstractRateLimiterConfigurationOnMissingBean.java b/resilience4j-spring-boot-common/src/main/java/io/github/resilience4j/ratelimiter/autoconfigure/AbstractRateLimiterConfigurationOnMissingBean.java index 874d9fc03c..807481da96 100644 --- a/resilience4j-spring-boot-common/src/main/java/io/github/resilience4j/ratelimiter/autoconfigure/AbstractRateLimiterConfigurationOnMissingBean.java +++ b/resilience4j-spring-boot-common/src/main/java/io/github/resilience4j/ratelimiter/autoconfigure/AbstractRateLimiterConfigurationOnMissingBean.java @@ -15,6 +15,7 @@ */ package io.github.resilience4j.ratelimiter.autoconfigure; +import io.github.resilience4j.common.ratelimiter.configuration.CompositeRateLimiterCustomizer; import io.github.resilience4j.consumer.EventConsumerRegistry; import io.github.resilience4j.core.registry.RegistryEventConsumer; import io.github.resilience4j.fallback.FallbackDecorators; @@ -48,10 +49,11 @@ public AbstractRateLimiterConfigurationOnMissingBean() { public RateLimiterRegistry rateLimiterRegistry( RateLimiterConfigurationProperties rateLimiterProperties, EventConsumerRegistry rateLimiterEventsConsumerRegistry, - RegistryEventConsumer rateLimiterRegistryEventConsumer) { + RegistryEventConsumer rateLimiterRegistryEventConsumer, + CompositeRateLimiterCustomizer compositeRateLimiterCustomizer) { return rateLimiterConfiguration .rateLimiterRegistry(rateLimiterProperties, rateLimiterEventsConsumerRegistry, - rateLimiterRegistryEventConsumer); + rateLimiterRegistryEventConsumer, compositeRateLimiterCustomizer); } @Bean diff --git a/resilience4j-spring-boot-common/src/test/java/io/github/resilience4j/SpringBootCommonTest.java b/resilience4j-spring-boot-common/src/test/java/io/github/resilience4j/SpringBootCommonTest.java index a9cf7e0b43..c116616e02 100644 --- a/resilience4j-spring-boot-common/src/test/java/io/github/resilience4j/SpringBootCommonTest.java +++ b/resilience4j-spring-boot-common/src/test/java/io/github/resilience4j/SpringBootCommonTest.java @@ -22,9 +22,10 @@ import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry; import io.github.resilience4j.circuitbreaker.autoconfigure.AbstractCircuitBreakerConfigurationOnMissingBean; import io.github.resilience4j.circuitbreaker.configure.CircuitBreakerConfigurationProperties; +import io.github.resilience4j.common.CompositeCustomizer; import io.github.resilience4j.common.bulkhead.configuration.ThreadPoolBulkheadConfigurationProperties; import io.github.resilience4j.common.circuitbreaker.configuration.CircuitBreakerConfigCustomizer; -import io.github.resilience4j.common.circuitbreaker.configuration.CompositeCircuitBreakerCustomizer; +import io.github.resilience4j.common.ratelimiter.configuration.CompositeRateLimiterCustomizer; import io.github.resilience4j.common.retry.configuration.CompositeRetryCustomizer; import io.github.resilience4j.consumer.DefaultEventConsumerRegistry; import io.github.resilience4j.core.registry.CompositeRegistryEventConsumer; @@ -80,7 +81,7 @@ public void testCircuitBreakerCommonConfig() { assertThat(circuitBreakerConfig.rxJava2CircuitBreakerAspect()).isNotNull(); assertThat(circuitBreakerConfig.circuitBreakerRegistry(new DefaultEventConsumerRegistry<>(), new CompositeRegistryEventConsumer<>(emptyList()), - new CompositeCircuitBreakerCustomizer(Collections.singletonList(new TestCustomizer())))) + new CompositeCustomizer<>(Collections.singletonList(new TestCustomizer())))) .isNotNull(); assertThat(circuitBreakerConfig .circuitBreakerAspect(CircuitBreakerRegistry.ofDefaults(), Collections.emptyList(), @@ -112,7 +113,8 @@ public void testRateLimiterCommonConfig() { assertThat(rateLimiterConfigurationOnMissingBean .rateLimiterRegistry(new RateLimiterConfigurationProperties(), new DefaultEventConsumerRegistry<>(), - new CompositeRegistryEventConsumer<>(emptyList()))).isNotNull(); + new CompositeRegistryEventConsumer<>(emptyList()), + new CompositeRateLimiterCustomizer(Collections.emptyList()))).isNotNull(); assertThat(rateLimiterConfigurationOnMissingBean .rateLimiterAspect(new RateLimiterConfigurationProperties(), RateLimiterRegistry.ofDefaults(), Collections.emptyList(), diff --git a/resilience4j-spring-boot/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/CircuitBreakerConfigurationOnMissingBean.java b/resilience4j-spring-boot/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/CircuitBreakerConfigurationOnMissingBean.java index 00458f3a65..66db670daf 100644 --- a/resilience4j-spring-boot/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/CircuitBreakerConfigurationOnMissingBean.java +++ b/resilience4j-spring-boot/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/CircuitBreakerConfigurationOnMissingBean.java @@ -17,10 +17,10 @@ import io.github.resilience4j.circuitbreaker.configure.CircuitBreakerConfigurationProperties; import io.github.resilience4j.circuitbreaker.event.CircuitBreakerEvent; +import io.github.resilience4j.common.CompositeCustomizer; import io.github.resilience4j.common.IntegerToDurationConverter; import io.github.resilience4j.common.StringToDurationConverter; import io.github.resilience4j.common.circuitbreaker.configuration.CircuitBreakerConfigCustomizer; -import io.github.resilience4j.common.circuitbreaker.configuration.CompositeCircuitBreakerCustomizer; import io.github.resilience4j.consumer.EventConsumerRegistry; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -47,9 +47,9 @@ public EventConsumerRegistry eventConsumerRegistry() { @Bean @ConditionalOnMissingBean - public CompositeCircuitBreakerCustomizer circuitBreakerCustomizerFinder( + public CompositeCustomizer circuitBreakerCustomizerFinder( @Autowired(required = false) List customizers) { - return new CompositeCircuitBreakerCustomizer(customizers); + return new CompositeCustomizer<>(customizers); } } diff --git a/resilience4j-spring-boot/src/main/java/io/github/resilience4j/ratelimiter/autoconfigure/RateLimiterConfigurationOnMissingBean.java b/resilience4j-spring-boot/src/main/java/io/github/resilience4j/ratelimiter/autoconfigure/RateLimiterConfigurationOnMissingBean.java index bffa54c4bb..f8e4ea1519 100644 --- a/resilience4j-spring-boot/src/main/java/io/github/resilience4j/ratelimiter/autoconfigure/RateLimiterConfigurationOnMissingBean.java +++ b/resilience4j-spring-boot/src/main/java/io/github/resilience4j/ratelimiter/autoconfigure/RateLimiterConfigurationOnMissingBean.java @@ -17,12 +17,18 @@ import io.github.resilience4j.common.IntegerToDurationConverter; import io.github.resilience4j.common.StringToDurationConverter; +import io.github.resilience4j.common.ratelimiter.configuration.CompositeRateLimiterCustomizer; +import io.github.resilience4j.common.ratelimiter.configuration.RateLimiterConfigCustomizer; import io.github.resilience4j.consumer.EventConsumerRegistry; import io.github.resilience4j.ratelimiter.event.RateLimiterEvent; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import java.util.List; + @Configuration @Import({IntegerToDurationConverter.class, StringToDurationConverter.class}) public class RateLimiterConfigurationOnMissingBean extends @@ -32,4 +38,12 @@ public class RateLimiterConfigurationOnMissingBean extends public EventConsumerRegistry rateLimiterEventsConsumerRegistry() { return rateLimiterConfiguration.rateLimiterEventsConsumerRegistry(); } + + @Bean + @ConditionalOnMissingBean + public CompositeRateLimiterCustomizer compositeRateLimiterCustomizer( + @Autowired(required = false) + List configCustomizers) { + return new CompositeRateLimiterCustomizer(configCustomizers); + } } diff --git a/resilience4j-spring-boot2/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/CircuitBreakerConfigurationOnMissingBean.java b/resilience4j-spring-boot2/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/CircuitBreakerConfigurationOnMissingBean.java index 42bbec8ee4..4ac5da5d54 100644 --- a/resilience4j-spring-boot2/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/CircuitBreakerConfigurationOnMissingBean.java +++ b/resilience4j-spring-boot2/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/CircuitBreakerConfigurationOnMissingBean.java @@ -17,8 +17,8 @@ import io.github.resilience4j.circuitbreaker.configure.CircuitBreakerConfigurationProperties; import io.github.resilience4j.circuitbreaker.event.CircuitBreakerEvent; +import io.github.resilience4j.common.CompositeCustomizer; import io.github.resilience4j.common.circuitbreaker.configuration.CircuitBreakerConfigCustomizer; -import io.github.resilience4j.common.circuitbreaker.configuration.CompositeCircuitBreakerCustomizer; import io.github.resilience4j.consumer.EventConsumerRegistry; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; @@ -44,9 +44,9 @@ public EventConsumerRegistry eventConsumerRegistry() { @Bean @ConditionalOnMissingBean - public CompositeCircuitBreakerCustomizer circuitBreakerCustomizerFinder( + public CompositeCustomizer circuitBreakerCustomizerFinder( @Nullable List customizers) { - return new CompositeCircuitBreakerCustomizer(customizers); + return new CompositeCustomizer<>(customizers); } } diff --git a/resilience4j-spring-boot2/src/main/java/io/github/resilience4j/ratelimiter/autoconfigure/RateLimiterConfigurationOnMissingBean.java b/resilience4j-spring-boot2/src/main/java/io/github/resilience4j/ratelimiter/autoconfigure/RateLimiterConfigurationOnMissingBean.java index 3b4a9cda6c..bdbf9e33e5 100644 --- a/resilience4j-spring-boot2/src/main/java/io/github/resilience4j/ratelimiter/autoconfigure/RateLimiterConfigurationOnMissingBean.java +++ b/resilience4j-spring-boot2/src/main/java/io/github/resilience4j/ratelimiter/autoconfigure/RateLimiterConfigurationOnMissingBean.java @@ -15,11 +15,16 @@ */ package io.github.resilience4j.ratelimiter.autoconfigure; +import io.github.resilience4j.common.ratelimiter.configuration.CompositeRateLimiterCustomizer; +import io.github.resilience4j.common.ratelimiter.configuration.RateLimiterConfigCustomizer; import io.github.resilience4j.consumer.EventConsumerRegistry; import io.github.resilience4j.ratelimiter.event.RateLimiterEvent; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.lang.Nullable; + +import java.util.List; @Configuration public class RateLimiterConfigurationOnMissingBean extends @@ -30,4 +35,11 @@ public class RateLimiterConfigurationOnMissingBean extends public EventConsumerRegistry rateLimiterEventsConsumerRegistry() { return rateLimiterConfiguration.rateLimiterEventsConsumerRegistry(); } + + @Bean + @ConditionalOnMissingBean + public CompositeRateLimiterCustomizer compositeRateLimiterCustomizer(@Nullable + List configCustomizers) { + return new CompositeRateLimiterCustomizer(configCustomizers); + } } diff --git a/resilience4j-spring-boot2/src/test/java/io/github/resilience4j/ratelimiter/RateLimiterAutoConfigurationTest.java b/resilience4j-spring-boot2/src/test/java/io/github/resilience4j/ratelimiter/RateLimiterAutoConfigurationTest.java index 3b9aa85e67..888fb4c36b 100644 --- a/resilience4j-spring-boot2/src/test/java/io/github/resilience4j/ratelimiter/RateLimiterAutoConfigurationTest.java +++ b/resilience4j-spring-boot2/src/test/java/io/github/resilience4j/ratelimiter/RateLimiterAutoConfigurationTest.java @@ -109,8 +109,9 @@ public void testFeignClient() { ResponseEntity rateLimiterList = restTemplate .getForEntity("/actuator/ratelimiters", RateLimiterEndpointResponse.class); - assertThat(rateLimiterList.getBody().getRateLimiters()).hasSize(3) - .containsExactly("backendA", "backendB", "rateLimiterDummyFeignClient"); + assertThat(rateLimiterList.getBody().getRateLimiters()).hasSize(4) + .containsExactly("backendA", "backendB", "backendCustomizer", + "rateLimiterDummyFeignClient"); try { for (int i = 0; i < 11; i++) { @@ -173,8 +174,9 @@ public void testRateLimiterAutoConfiguration() throws IOException { ResponseEntity rateLimiterList = restTemplate .getForEntity("/actuator/ratelimiters", RateLimiterEndpointResponse.class); - assertThat(rateLimiterList.getBody().getRateLimiters()).hasSize(3) - .containsExactly("backendA", "backendB", "rateLimiterDummyFeignClient"); + assertThat(rateLimiterList.getBody().getRateLimiters()).hasSize(4) + .containsExactly("backendA", "backendB", "backendCustomizer", + "rateLimiterDummyFeignClient"); try { for (int i = 0; i < 11; i++) { @@ -198,5 +200,10 @@ public void testRateLimiterAutoConfiguration() throws IOException { .until(() -> rateLimiter.getMetrics().getAvailablePermissions() == 10); assertThat(rateLimiterAspect.getOrder()).isEqualTo(401); + + // test the customizer impact for specific instance + RateLimiter backendCustomizer = rateLimiterRegistry.rateLimiter("backendCustomizer"); + assertThat(backendCustomizer.getRateLimiterConfig().getLimitForPeriod()).isEqualTo(200); + } } diff --git a/resilience4j-spring-boot2/src/test/java/io/github/resilience4j/service/test/TestApplication.java b/resilience4j-spring-boot2/src/test/java/io/github/resilience4j/service/test/TestApplication.java index adc43e5c50..6e71f7f631 100644 --- a/resilience4j-spring-boot2/src/test/java/io/github/resilience4j/service/test/TestApplication.java +++ b/resilience4j-spring-boot2/src/test/java/io/github/resilience4j/service/test/TestApplication.java @@ -2,6 +2,8 @@ import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig; import io.github.resilience4j.common.circuitbreaker.configuration.CircuitBreakerConfigCustomizer; +import io.github.resilience4j.common.ratelimiter.configuration.RateLimiterConfigCustomizer; +import io.github.resilience4j.ratelimiter.RateLimiterConfig; import io.github.resilience4j.common.retry.configuration.RetryConfigCustomizer; import io.github.resilience4j.retry.RetryConfig; import org.springframework.boot.SpringApplication; @@ -36,6 +38,22 @@ public String name() { } + @Bean + public RateLimiterConfigCustomizer testRateLimiterCustomizer() { + return new RateLimiterConfigCustomizer() { + @Override + public void customize(RateLimiterConfig.Builder builder) { + builder.limitForPeriod(200); + } + + @Override + public String name() { + return "backendCustomizer"; + } + }; + + } + @Bean public RetryConfigCustomizer testRetryCustomizer() { return new RetryConfigCustomizer() { diff --git a/resilience4j-spring-boot2/src/test/resources/application.yaml b/resilience4j-spring-boot2/src/test/resources/application.yaml index 80ff3fddf6..9a15e5e9b7 100644 --- a/resilience4j-spring-boot2/src/test/resources/application.yaml +++ b/resilience4j-spring-boot2/src/test/resources/application.yaml @@ -109,6 +109,10 @@ resilience4j.ratelimiter: limitForPeriod: 100 limitRefreshPeriod: 500ms timeoutDuration: 3s + backendCustomizer: + limitForPeriod: 100 + limitRefreshPeriod: 500ms + timeoutDuration: 3s rateLimiterDummyFeignClient: baseConfig: default diff --git a/resilience4j-spring-cloud-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractRefreshScopedCircuitBreakerConfiguration.java b/resilience4j-spring-cloud-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractRefreshScopedCircuitBreakerConfiguration.java index 9845b37ebd..1359f64d3c 100644 --- a/resilience4j-spring-cloud-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractRefreshScopedCircuitBreakerConfiguration.java +++ b/resilience4j-spring-cloud-common/src/main/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractRefreshScopedCircuitBreakerConfiguration.java @@ -5,7 +5,8 @@ import io.github.resilience4j.circuitbreaker.configure.CircuitBreakerConfiguration; import io.github.resilience4j.circuitbreaker.configure.CircuitBreakerConfigurationProperties; import io.github.resilience4j.circuitbreaker.event.CircuitBreakerEvent; -import io.github.resilience4j.common.circuitbreaker.configuration.CompositeCircuitBreakerCustomizer; +import io.github.resilience4j.common.CompositeCustomizer; +import io.github.resilience4j.common.circuitbreaker.configuration.CircuitBreakerConfigCustomizer; import io.github.resilience4j.consumer.EventConsumerRegistry; import io.github.resilience4j.core.registry.RegistryEventConsumer; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -36,7 +37,7 @@ protected AbstractRefreshScopedCircuitBreakerConfiguration( public CircuitBreakerRegistry circuitBreakerRegistry( EventConsumerRegistry eventConsumerRegistry, RegistryEventConsumer circuitBreakerRegistryEventConsumer, - CompositeCircuitBreakerCustomizer compositeCircuitBreakerCustomizer) { + CompositeCustomizer compositeCircuitBreakerCustomizer) { return circuitBreakerConfiguration .circuitBreakerRegistry(eventConsumerRegistry, circuitBreakerRegistryEventConsumer, compositeCircuitBreakerCustomizer); diff --git a/resilience4j-spring-cloud-common/src/main/java/io/github/resilience4j/ratelimiter/autoconfigure/AbstractRefreshScopedRateLimiterConfiguration.java b/resilience4j-spring-cloud-common/src/main/java/io/github/resilience4j/ratelimiter/autoconfigure/AbstractRefreshScopedRateLimiterConfiguration.java index ca8ed263fc..6c20802918 100644 --- a/resilience4j-spring-cloud-common/src/main/java/io/github/resilience4j/ratelimiter/autoconfigure/AbstractRefreshScopedRateLimiterConfiguration.java +++ b/resilience4j-spring-cloud-common/src/main/java/io/github/resilience4j/ratelimiter/autoconfigure/AbstractRefreshScopedRateLimiterConfiguration.java @@ -1,5 +1,6 @@ package io.github.resilience4j.ratelimiter.autoconfigure; +import io.github.resilience4j.common.ratelimiter.configuration.CompositeRateLimiterCustomizer; import io.github.resilience4j.consumer.EventConsumerRegistry; import io.github.resilience4j.core.registry.RegistryEventConsumer; import io.github.resilience4j.ratelimiter.RateLimiter; @@ -32,10 +33,11 @@ protected AbstractRefreshScopedRateLimiterConfiguration() { public RateLimiterRegistry rateLimiterRegistry( RateLimiterConfigurationProperties rateLimiterProperties, EventConsumerRegistry rateLimiterEventsConsumerRegistry, - RegistryEventConsumer rateLimiterRegistryEventConsumer) { + RegistryEventConsumer rateLimiterRegistryEventConsumer, + CompositeRateLimiterCustomizer compositeRateLimiterCustomizer) { return rateLimiterConfiguration.rateLimiterRegistry( rateLimiterProperties, rateLimiterEventsConsumerRegistry, - rateLimiterRegistryEventConsumer); + rateLimiterRegistryEventConsumer, compositeRateLimiterCustomizer); } } diff --git a/resilience4j-spring-cloud-common/src/test/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractRefreshScopedCircuitBreakerConfigurationTest.java b/resilience4j-spring-cloud-common/src/test/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractRefreshScopedCircuitBreakerConfigurationTest.java index c04a1f243b..4f43007fe5 100644 --- a/resilience4j-spring-cloud-common/src/test/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractRefreshScopedCircuitBreakerConfigurationTest.java +++ b/resilience4j-spring-cloud-common/src/test/java/io/github/resilience4j/circuitbreaker/autoconfigure/AbstractRefreshScopedCircuitBreakerConfigurationTest.java @@ -17,7 +17,7 @@ package io.github.resilience4j.circuitbreaker.autoconfigure; import io.github.resilience4j.circuitbreaker.configure.CircuitBreakerConfigurationProperties; -import io.github.resilience4j.common.circuitbreaker.configuration.CompositeCircuitBreakerCustomizer; +import io.github.resilience4j.common.CompositeCustomizer; import io.github.resilience4j.consumer.DefaultEventConsumerRegistry; import io.github.resilience4j.core.registry.CompositeRegistryEventConsumer; import org.junit.Test; @@ -47,7 +47,7 @@ public void testCircuitBreakerCloudCommonConfig() { assertThat(circuitBreakerConfig.circuitBreakerRegistry( new DefaultEventConsumerRegistry<>(), new CompositeRegistryEventConsumer<>(emptyList()), - new CompositeCircuitBreakerCustomizer(Collections.emptyList()))) + new CompositeCustomizer<>(Collections.emptyList()))) .isNotNull(); } diff --git a/resilience4j-spring-cloud-common/src/test/java/io/github/resilience4j/ratelimiter/autoconfigure/AbstractRefreshScopedRateLimiterConfigurationTest.java b/resilience4j-spring-cloud-common/src/test/java/io/github/resilience4j/ratelimiter/autoconfigure/AbstractRefreshScopedRateLimiterConfigurationTest.java index 7186049bfe..ef6288f000 100644 --- a/resilience4j-spring-cloud-common/src/test/java/io/github/resilience4j/ratelimiter/autoconfigure/AbstractRefreshScopedRateLimiterConfigurationTest.java +++ b/resilience4j-spring-cloud-common/src/test/java/io/github/resilience4j/ratelimiter/autoconfigure/AbstractRefreshScopedRateLimiterConfigurationTest.java @@ -16,6 +16,7 @@ package io.github.resilience4j.ratelimiter.autoconfigure; +import io.github.resilience4j.common.ratelimiter.configuration.CompositeRateLimiterCustomizer; import io.github.resilience4j.consumer.DefaultEventConsumerRegistry; import io.github.resilience4j.core.registry.CompositeRegistryEventConsumer; import io.github.resilience4j.ratelimiter.configure.RateLimiterConfigurationProperties; @@ -25,6 +26,7 @@ import org.springframework.context.annotation.Bean; import java.util.Arrays; +import java.util.Collections; import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; @@ -44,7 +46,8 @@ public void testRateLimiterCloudCommonConfig() { assertThat(rateLimiterConfig.rateLimiterRegistry( new RateLimiterConfigurationProperties(), new DefaultEventConsumerRegistry<>(), - new CompositeRegistryEventConsumer<>(emptyList()))).isNotNull(); + new CompositeRegistryEventConsumer<>(emptyList()), new CompositeRateLimiterCustomizer( + Collections.emptyList()))).isNotNull(); } static class RateLimiterConfig extends AbstractRefreshScopedRateLimiterConfiguration { diff --git a/resilience4j-spring/src/main/java/io/github/resilience4j/circuitbreaker/configure/CircuitBreakerConfiguration.java b/resilience4j-spring/src/main/java/io/github/resilience4j/circuitbreaker/configure/CircuitBreakerConfiguration.java index 21790ffc78..8cf6ad1998 100644 --- a/resilience4j-spring/src/main/java/io/github/resilience4j/circuitbreaker/configure/CircuitBreakerConfiguration.java +++ b/resilience4j-spring/src/main/java/io/github/resilience4j/circuitbreaker/configure/CircuitBreakerConfiguration.java @@ -19,8 +19,8 @@ import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig; import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry; import io.github.resilience4j.circuitbreaker.event.CircuitBreakerEvent; +import io.github.resilience4j.common.CompositeCustomizer; import io.github.resilience4j.common.circuitbreaker.configuration.CircuitBreakerConfigCustomizer; -import io.github.resilience4j.common.circuitbreaker.configuration.CompositeCircuitBreakerCustomizer; import io.github.resilience4j.consumer.DefaultEventConsumerRegistry; import io.github.resilience4j.consumer.EventConsumerRegistry; import io.github.resilience4j.core.registry.CompositeRegistryEventConsumer; @@ -57,16 +57,16 @@ public CircuitBreakerConfiguration( } @Bean - public CompositeCircuitBreakerCustomizer circuitBreakerCustomizerFinder( + public CompositeCustomizer circuitBreakerCustomizerFinder( @Nullable List customizers) { - return new CompositeCircuitBreakerCustomizer(customizers); + return new CompositeCustomizer<>(customizers); } @Bean public CircuitBreakerRegistry circuitBreakerRegistry( EventConsumerRegistry eventConsumerRegistry, RegistryEventConsumer circuitBreakerRegistryEventConsumer, - CompositeCircuitBreakerCustomizer circuitBreakerCustomizerFinder) { + CompositeCustomizer circuitBreakerCustomizerFinder) { CircuitBreakerRegistry circuitBreakerRegistry = createCircuitBreakerRegistry( circuitBreakerProperties, circuitBreakerRegistryEventConsumer, @@ -129,7 +129,7 @@ public EventConsumerRegistry eventConsumerRegistry() { CircuitBreakerRegistry createCircuitBreakerRegistry( CircuitBreakerConfigurationProperties circuitBreakerProperties, RegistryEventConsumer circuitBreakerRegistryEventConsumer, - CompositeCircuitBreakerCustomizer customizerMap) { + CompositeCustomizer customizerMap) { Map configs = circuitBreakerProperties.getConfigs() .entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, @@ -148,7 +148,7 @@ CircuitBreakerRegistry createCircuitBreakerRegistry( * @param customizerMap */ void initCircuitBreakerRegistry(CircuitBreakerRegistry circuitBreakerRegistry, - CompositeCircuitBreakerCustomizer customizerMap) { + CompositeCustomizer customizerMap) { circuitBreakerProperties.getInstances().forEach( (name, properties) -> circuitBreakerRegistry.circuitBreaker(name, circuitBreakerProperties diff --git a/resilience4j-spring/src/main/java/io/github/resilience4j/ratelimiter/configure/RateLimiterConfiguration.java b/resilience4j-spring/src/main/java/io/github/resilience4j/ratelimiter/configure/RateLimiterConfiguration.java index fee851d50b..b15a2f40ca 100644 --- a/resilience4j-spring/src/main/java/io/github/resilience4j/ratelimiter/configure/RateLimiterConfiguration.java +++ b/resilience4j-spring/src/main/java/io/github/resilience4j/ratelimiter/configure/RateLimiterConfiguration.java @@ -16,6 +16,8 @@ package io.github.resilience4j.ratelimiter.configure; +import io.github.resilience4j.common.ratelimiter.configuration.CompositeRateLimiterCustomizer; +import io.github.resilience4j.common.ratelimiter.configuration.RateLimiterConfigCustomizer; import io.github.resilience4j.consumer.DefaultEventConsumerRegistry; import io.github.resilience4j.consumer.EventConsumerRegistry; import io.github.resilience4j.core.registry.CompositeRegistryEventConsumer; @@ -33,6 +35,7 @@ import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import org.springframework.lang.Nullable; import java.util.ArrayList; import java.util.List; @@ -47,19 +50,27 @@ @Configuration public class RateLimiterConfiguration { + @Bean + public CompositeRateLimiterCustomizer compositeRateLimiterCustomizer( + @Nullable List configCustomizers) { + return new CompositeRateLimiterCustomizer(configCustomizers); + } + @Bean public RateLimiterRegistry rateLimiterRegistry( RateLimiterConfigurationProperties rateLimiterProperties, EventConsumerRegistry rateLimiterEventsConsumerRegistry, - RegistryEventConsumer rateLimiterRegistryEventConsumer) { + RegistryEventConsumer rateLimiterRegistryEventConsumer, + CompositeRateLimiterCustomizer compositeRateLimiterCustomizer) { RateLimiterRegistry rateLimiterRegistry = createRateLimiterRegistry(rateLimiterProperties, - rateLimiterRegistryEventConsumer); + rateLimiterRegistryEventConsumer, compositeRateLimiterCustomizer); registerEventConsumer(rateLimiterRegistry, rateLimiterEventsConsumerRegistry, rateLimiterProperties); rateLimiterProperties.getInstances().forEach( (name, properties) -> rateLimiterRegistry - .rateLimiter(name, rateLimiterProperties.createRateLimiterConfig(properties)) + .rateLimiter(name, rateLimiterProperties + .createRateLimiterConfig(properties, compositeRateLimiterCustomizer, name)) ); return rateLimiterRegistry; } @@ -76,15 +87,18 @@ public RegistryEventConsumer rateLimiterRegistryEventConsumer( * Initializes a rate limiter registry. * * @param rateLimiterConfigurationProperties The rate limiter configuration properties. + * @param compositeRateLimiterCustomizer the composite rate limiter customizer delegate * @return a RateLimiterRegistry */ private RateLimiterRegistry createRateLimiterRegistry( RateLimiterConfigurationProperties rateLimiterConfigurationProperties, - RegistryEventConsumer rateLimiterRegistryEventConsumer) { + RegistryEventConsumer rateLimiterRegistryEventConsumer, + CompositeRateLimiterCustomizer compositeRateLimiterCustomizer) { Map configs = rateLimiterConfigurationProperties.getConfigs() .entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, entry -> rateLimiterConfigurationProperties - .createRateLimiterConfig(entry.getValue()))); + .createRateLimiterConfig(entry.getValue(), compositeRateLimiterCustomizer, + entry.getKey()))); return RateLimiterRegistry.of(configs, rateLimiterRegistryEventConsumer, io.vavr.collection.HashMap.ofAll(rateLimiterConfigurationProperties.getTags())); diff --git a/resilience4j-spring/src/test/java/io/github/resilience4j/circuitbreaker/configure/CircuitBreakerConfigurationTest.java b/resilience4j-spring/src/test/java/io/github/resilience4j/circuitbreaker/configure/CircuitBreakerConfigurationTest.java index 544e54fe4a..50620f2129 100644 --- a/resilience4j-spring/src/test/java/io/github/resilience4j/circuitbreaker/configure/CircuitBreakerConfigurationTest.java +++ b/resilience4j-spring/src/test/java/io/github/resilience4j/circuitbreaker/configure/CircuitBreakerConfigurationTest.java @@ -3,8 +3,9 @@ import io.github.resilience4j.circuitbreaker.CircuitBreaker; import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry; import io.github.resilience4j.circuitbreaker.event.CircuitBreakerEvent; +import io.github.resilience4j.common.CompositeCustomizer; +import io.github.resilience4j.common.circuitbreaker.configuration.CircuitBreakerConfigCustomizer; import io.github.resilience4j.common.circuitbreaker.configuration.CircuitBreakerConfigurationProperties.InstanceProperties; -import io.github.resilience4j.common.circuitbreaker.configuration.CompositeCircuitBreakerCustomizer; import io.github.resilience4j.consumer.DefaultEventConsumerRegistry; import io.github.resilience4j.core.ConfigurationNotFoundException; import io.github.resilience4j.core.registry.CompositeRegistryEventConsumer; @@ -224,8 +225,8 @@ public void testCreateCircuitBreakerRegistryWithUnknownConfig() { .hasMessage("Configuration with name 'unknownConfig' does not exist"); } - private CompositeCircuitBreakerCustomizer compositeCircuitBreakerCustomizerTestInstance() { - return new CompositeCircuitBreakerCustomizer(Collections.emptyList()); + private CompositeCustomizer compositeCircuitBreakerCustomizerTestInstance() { + return new CompositeCustomizer<>(Collections.emptyList()); } } \ No newline at end of file diff --git a/resilience4j-spring/src/test/java/io/github/resilience4j/ratelimiter/configure/RateLimiterConfigurationTest.java b/resilience4j-spring/src/test/java/io/github/resilience4j/ratelimiter/configure/RateLimiterConfigurationTest.java index c91647b178..bad009eccd 100644 --- a/resilience4j-spring/src/test/java/io/github/resilience4j/ratelimiter/configure/RateLimiterConfigurationTest.java +++ b/resilience4j-spring/src/test/java/io/github/resilience4j/ratelimiter/configure/RateLimiterConfigurationTest.java @@ -1,5 +1,6 @@ package io.github.resilience4j.ratelimiter.configure; +import io.github.resilience4j.common.ratelimiter.configuration.CompositeRateLimiterCustomizer; import io.github.resilience4j.consumer.DefaultEventConsumerRegistry; import io.github.resilience4j.core.ConfigurationNotFoundException; import io.github.resilience4j.core.registry.CompositeRegistryEventConsumer; @@ -11,6 +12,7 @@ import org.mockito.junit.MockitoJUnitRunner; import java.time.Duration; +import java.util.Collections; import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; @@ -39,7 +41,8 @@ public void testRateLimiterRegistry() { RateLimiterRegistry rateLimiterRegistry = rateLimiterConfiguration .rateLimiterRegistry(rateLimiterConfigurationProperties, eventConsumerRegistry, - new CompositeRegistryEventConsumer<>(emptyList())); + new CompositeRegistryEventConsumer<>(emptyList()), + compositeRateLimiterCustomizerTest()); assertThat(rateLimiterConfigurationProperties.getRateLimiterAspectOrder()).isEqualTo(300); assertThat(rateLimiterRegistry.getAllRateLimiters().size()).isEqualTo(2); @@ -90,7 +93,8 @@ public void testCreateRateLimiterRegistryWithSharedConfigs() { //When RateLimiterRegistry rateLimiterRegistry = rateLimiterConfiguration .rateLimiterRegistry(rateLimiterConfigurationProperties, eventConsumerRegistry, - new CompositeRegistryEventConsumer<>(emptyList())); + new CompositeRegistryEventConsumer<>(emptyList()), + compositeRateLimiterCustomizerTest()); //Then assertThat(rateLimiterRegistry.getAllRateLimiters().size()).isEqualTo(2); @@ -128,9 +132,14 @@ public void testCreateRateLimiterRegistryWithUnknownConfig() { assertThatThrownBy(() -> rateLimiterConfiguration .rateLimiterRegistry(rateLimiterConfigurationProperties, eventConsumerRegistry, - new CompositeRegistryEventConsumer<>(emptyList()))) + new CompositeRegistryEventConsumer<>(emptyList()), + compositeRateLimiterCustomizerTest())) .isInstanceOf(ConfigurationNotFoundException.class) .hasMessage("Configuration with name 'unknownConfig' does not exist"); } + public CompositeRateLimiterCustomizer compositeRateLimiterCustomizerTest() { + return new CompositeRateLimiterCustomizer(Collections.emptyList()); + } + } \ No newline at end of file