Skip to content

Allows the ability to configure bulkheads using config properties#228

Merged
ryanjbaxter merged 3 commits intospring-cloud:3.1.xfrom
ryanjbaxter:bulkhead-configuration-fix
Dec 17, 2024
Merged

Allows the ability to configure bulkheads using config properties#228
ryanjbaxter merged 3 commits intospring-cloud:3.1.xfrom
ryanjbaxter:bulkhead-configuration-fix

Conversation

@ryanjbaxter
Copy link
Copy Markdown
Contributor

Also addresses issue where semaphore bulkhead was used when threadpool config was supplied.

Fixes #224

Also addresses issue where semaphore bulkhead was used when threadpool config was supplied.

Fixes spring-cloud#224
@ryanjbaxter ryanjbaxter linked an issue Dec 12, 2024 that may be closed by this pull request
@ryanjbaxter
Copy link
Copy Markdown
Contributor Author

@OathMeadow this PR addresses the issues in #224. Let me know what you think.

builder.bulkheadConfig(bulkheadConfiguration.orElse(bulkheadRegistry.getDefaultConfig()));
builder
.threadPoolBulkheadConfig(threadPoolBulkheadConfig.orElse(threadPoolBulkheadRegistry.getDefaultConfig()));
return builder.build();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering what function the defaultConfiguration would serve.
Currently only used in addBulkheadCustomizer and addThreadPoolBulkheadCustomizer.

We could maybe handle this similair to what we do in Resilience4JCircuitBreakerFactory.

	private Resilience4JCircuitBreaker create(String id, String groupName,
			ExecutorService circuitBreakerExecutorService) {
		Resilience4JConfigBuilder.Resilience4JCircuitBreakerConfiguration defaultConfig = getConfigurations()
				.computeIfAbsent(id, defaultConfiguration);
		CircuitBreakerConfig circuitBreakerConfig = this.circuitBreakerRegistry.getConfiguration(id)
				.orElseGet(() -> this.circuitBreakerRegistry.getConfiguration(groupName)
						.orElseGet(defaultConfig::getCircuitBreakerConfig));
		TimeLimiterConfig timeLimiterConfig = this.timeLimiterRegistry.getConfiguration(id)
				.orElseGet(() -> this.timeLimiterRegistry.getConfiguration(groupName)
						.orElseGet(defaultConfig::getTimeLimiterConfig));
		if (resilience4JConfigurationProperties.isDisableThreadPool()) {
			return new Resilience4JCircuitBreaker(id, groupName, circuitBreakerConfig, timeLimiterConfig,
					circuitBreakerRegistry, timeLimiterRegistry, Optional.ofNullable(circuitBreakerCustomizers.get(id)),
					bulkheadProvider);
		}
		else {
			return new Resilience4JCircuitBreaker(id, groupName, circuitBreakerConfig, timeLimiterConfig,
					circuitBreakerRegistry, timeLimiterRegistry, circuitBreakerExecutorService,
					Optional.ofNullable(circuitBreakerCustomizers.get(id)), bulkheadProvider,
					this.resilience4JConfigurationProperties.isDisableTimeLimiter());
		}

	}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, we should be using the defaultConfiguration variable in the case where that was specifically set by the user.

/**
* @author Ryan Baxter
*/
public class BulkheadConfigurationTests {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should also add default config tests.

example: resilience4j.threadPoolBulkHead.configs.default.queueCapacity=30

*/
public class BulkheadConfigurationTests {

@Test
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to test these?
What is expected?

Resilience4jBulkheadProvider::configureDefault
Resilience4jBulkheadProvider::configure
Resilience4jBulkheadProvider::addBulkheadCustomizer
Resilience4jBulkheadProvider::addThreadPoolBulkheadCustomizer

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example:

Resilience4jBulkheadProvider::configureDefault vs resilience4j.threadPoolBulkHead.configs.default.queueCapacity=30

In my opinion, when Resilience4jBulkheadProvider::configureDefault is used, then it take precedence over property. Perhaps same with Resilience4jBulkheadProvider::configure ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resilience4jBulkheadProvider::configureDefault, Resilience4jBulkheadProvider::addBulkheadCustomizer, Resilience4jBulkheadProvider::addThreadPoolBulkheadCustomizer are used in Resilience4JBulkheadIntegrationTest and and Resilience4JBulkheadAndTimeLimiterIntegrationTest.

I agree on the configureDefault and I added some tests for that.

Copy link
Copy Markdown
Contributor Author

@ryanjbaxter ryanjbaxter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, made some changes based on your feedback

builder.bulkheadConfig(bulkheadConfiguration.orElse(bulkheadRegistry.getDefaultConfig()));
builder
.threadPoolBulkheadConfig(threadPoolBulkheadConfig.orElse(threadPoolBulkheadRegistry.getDefaultConfig()));
return builder.build();
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, we should be using the defaultConfiguration variable in the case where that was specifically set by the user.

*/
public class BulkheadConfigurationTests {

@Test
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resilience4jBulkheadProvider::configureDefault, Resilience4jBulkheadProvider::addBulkheadCustomizer, Resilience4jBulkheadProvider::addThreadPoolBulkheadCustomizer are used in Resilience4JBulkheadIntegrationTest and and Resilience4JBulkheadAndTimeLimiterIntegrationTest.

I agree on the configureDefault and I added some tests for that.


private Resilience4jBulkheadConfigurationBuilder.BulkheadConfiguration getConfiguration(String id) {
Resilience4jBulkheadConfigurationBuilder builder = new Resilience4jBulkheadConfigurationBuilder();
Resilience4jBulkheadConfigurationBuilder.BulkheadConfiguration defaultConfiguration = this.defaultConfiguration
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a minor suggestion really.
The method configureDefault(..) allows to set the variable defaultConfiguration to null.

@ryanjbaxter ryanjbaxter force-pushed the bulkhead-configuration-fix branch from 3a69848 to b5bfcf7 Compare December 17, 2024 14:52
@ryanjbaxter ryanjbaxter merged commit 9144b3a into spring-cloud:3.1.x Dec 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Confusing enableSemaphoreDefaultBulkhead property

3 participants