Skip to content

Commit 0a3e799

Browse files
committed
Merge pull request #41335 from travisriegler
* gh-41335: Polish "Group Kafka back-off properties" Group Kafka back-off properties Closes gh-41335
2 parents d07fe47 + 8707399 commit 0a3e799

File tree

3 files changed

+134
-38
lines changed

3 files changed

+134
-38
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/kafka/KafkaAutoConfiguration.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -32,7 +32,7 @@
3232
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
3333
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
3434
import org.springframework.boot.autoconfigure.kafka.KafkaProperties.Jaas;
35-
import org.springframework.boot.autoconfigure.kafka.KafkaProperties.Retry.Topic;
35+
import org.springframework.boot.autoconfigure.kafka.KafkaProperties.Retry.Topic.Backoff;
3636
import org.springframework.boot.context.properties.EnableConfigurationProperties;
3737
import org.springframework.boot.context.properties.PropertyMapper;
3838
import org.springframework.boot.ssl.SslBundles;
@@ -186,7 +186,7 @@ public RetryTopicConfiguration kafkaRetryTopicConfiguration(KafkaTemplate<?, ?>
186186
.useSingleTopicForSameIntervals()
187187
.suffixTopicsWithIndexValues()
188188
.doNotAutoCreateRetryTopics();
189-
setBackOffPolicy(builder, retryTopic);
189+
setBackOffPolicy(builder, retryTopic.getBackoff());
190190
return builder.create(kafkaTemplate);
191191
}
192192

@@ -214,15 +214,15 @@ private void applyKafkaConnectionDetailsForAdmin(Map<String, Object> properties,
214214
}
215215
}
216216

217-
private static void setBackOffPolicy(RetryTopicConfigurationBuilder builder, Topic retryTopic) {
218-
long delay = (retryTopic.getDelay() != null) ? retryTopic.getDelay().toMillis() : 0;
217+
private static void setBackOffPolicy(RetryTopicConfigurationBuilder builder, Backoff retryTopicBackoff) {
218+
long delay = (retryTopicBackoff.getDelay() != null) ? retryTopicBackoff.getDelay().toMillis() : 0;
219219
if (delay > 0) {
220220
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
221221
BackOffPolicyBuilder backOffPolicy = BackOffPolicyBuilder.newBuilder();
222222
map.from(delay).to(backOffPolicy::delay);
223-
map.from(retryTopic.getMaxDelay()).as(Duration::toMillis).to(backOffPolicy::maxDelay);
224-
map.from(retryTopic.getMultiplier()).to(backOffPolicy::multiplier);
225-
map.from(retryTopic.isRandomBackOff()).to(backOffPolicy::random);
223+
map.from(retryTopicBackoff.getMaxDelay()).as(Duration::toMillis).to(backOffPolicy::maxDelay);
224+
map.from(retryTopicBackoff.getMultiplier()).to(backOffPolicy::multiplier);
225+
map.from(retryTopicBackoff.isRandom()).to(backOffPolicy::random);
226226
builder.customBackoff((SleepingBackOffPolicy<?>) backOffPolicy.build());
227227
}
228228
else {

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/kafka/KafkaProperties.java

Lines changed: 86 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.apache.kafka.common.serialization.StringSerializer;
3535

3636
import org.springframework.boot.context.properties.ConfigurationProperties;
37+
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
3738
import org.springframework.boot.context.properties.PropertyMapper;
3839
import org.springframework.boot.context.properties.source.MutuallyExclusiveConfigurationPropertiesException;
3940
import org.springframework.boot.convert.DurationUnit;
@@ -1547,28 +1548,6 @@ public static class Topic {
15471548
*/
15481549
private int attempts = 3;
15491550

1550-
/**
1551-
* Canonical backoff period. Used as an initial value in the exponential case,
1552-
* and as a minimum value in the uniform case.
1553-
*/
1554-
private Duration delay = Duration.ofSeconds(1);
1555-
1556-
/**
1557-
* Multiplier to use for generating the next backoff delay.
1558-
*/
1559-
private double multiplier = 0.0;
1560-
1561-
/**
1562-
* Maximum wait between retries. If less than the delay then the default of 30
1563-
* seconds is applied.
1564-
*/
1565-
private Duration maxDelay = Duration.ZERO;
1566-
1567-
/**
1568-
* Whether to have the backoff delays.
1569-
*/
1570-
private boolean randomBackOff = false;
1571-
15721551
public boolean isEnabled() {
15731552
return this.enabled;
15741553
}
@@ -1585,36 +1564,113 @@ public void setAttempts(int attempts) {
15851564
this.attempts = attempts;
15861565
}
15871566

1567+
@DeprecatedConfigurationProperty(replacement = "spring.kafka.retry.topic.backoff.delay", since = "3.4.0")
1568+
@Deprecated(since = "3.4.0", forRemoval = true)
15881569
public Duration getDelay() {
1589-
return this.delay;
1570+
return getBackoff().getDelay();
15901571
}
15911572

1573+
@Deprecated(since = "3.4.0", forRemoval = true)
15921574
public void setDelay(Duration delay) {
1593-
this.delay = delay;
1575+
getBackoff().setDelay(delay);
15941576
}
15951577

1578+
@DeprecatedConfigurationProperty(replacement = "spring.kafka.retry.topic.backoff.multiplier",
1579+
since = "3.4.0")
1580+
@Deprecated(since = "3.4.0", forRemoval = true)
15961581
public double getMultiplier() {
1597-
return this.multiplier;
1582+
return getBackoff().getMultiplier();
15981583
}
15991584

1585+
@Deprecated(since = "3.4.0", forRemoval = true)
16001586
public void setMultiplier(double multiplier) {
1601-
this.multiplier = multiplier;
1587+
getBackoff().setMultiplier(multiplier);
16021588
}
16031589

1590+
@DeprecatedConfigurationProperty(replacement = "spring.kafka.retry.topic.backoff.maxDelay", since = "3.4.0")
1591+
@Deprecated(since = "3.4.0", forRemoval = true)
16041592
public Duration getMaxDelay() {
1605-
return this.maxDelay;
1593+
return getBackoff().getMaxDelay();
16061594
}
16071595

1596+
@Deprecated(since = "3.4.0", forRemoval = true)
16081597
public void setMaxDelay(Duration maxDelay) {
1609-
this.maxDelay = maxDelay;
1598+
getBackoff().setMaxDelay(maxDelay);
16101599
}
16111600

1601+
@DeprecatedConfigurationProperty(replacement = "spring.kafka.retry.topic.backoff.random", since = "3.4.0")
1602+
@Deprecated(since = "3.4.0", forRemoval = true)
16121603
public boolean isRandomBackOff() {
1613-
return this.randomBackOff;
1604+
return getBackoff().isRandom();
16141605
}
16151606

1607+
@Deprecated(since = "3.4.0", forRemoval = true)
16161608
public void setRandomBackOff(boolean randomBackOff) {
1617-
this.randomBackOff = randomBackOff;
1609+
getBackoff().setRandom(randomBackOff);
1610+
}
1611+
1612+
private final Backoff backoff = new Backoff();
1613+
1614+
public Backoff getBackoff() {
1615+
return this.backoff;
1616+
}
1617+
1618+
public static class Backoff {
1619+
1620+
/**
1621+
* Canonical backoff period. Used as an initial value in the exponential
1622+
* case, and as a minimum value in the uniform case.
1623+
*/
1624+
private Duration delay = Duration.ofSeconds(1);
1625+
1626+
/**
1627+
* Multiplier to use for generating the next backoff delay.
1628+
*/
1629+
private double multiplier = 0.0;
1630+
1631+
/**
1632+
* Maximum wait between retries. If less than the delay then the default
1633+
* of 30 seconds is applied.
1634+
*/
1635+
private Duration maxDelay = Duration.ZERO;
1636+
1637+
/**
1638+
* Whether to have the backoff delays.
1639+
*/
1640+
private boolean random = false;
1641+
1642+
public Duration getDelay() {
1643+
return this.delay;
1644+
}
1645+
1646+
public void setDelay(Duration delay) {
1647+
this.delay = delay;
1648+
}
1649+
1650+
public double getMultiplier() {
1651+
return this.multiplier;
1652+
}
1653+
1654+
public void setMultiplier(double multiplier) {
1655+
this.multiplier = multiplier;
1656+
}
1657+
1658+
public Duration getMaxDelay() {
1659+
return this.maxDelay;
1660+
}
1661+
1662+
public void setMaxDelay(Duration maxDelay) {
1663+
this.maxDelay = maxDelay;
1664+
}
1665+
1666+
public boolean isRandom() {
1667+
return this.random;
1668+
}
1669+
1670+
public void setRandom(boolean random) {
1671+
this.random = random;
1672+
}
1673+
16181674
}
16191675

16201676
}

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/kafka/KafkaAutoConfigurationTests.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,22 @@ void retryTopicConfigurationIsNotEnabledByDefault() {
442442

443443
@Test
444444
void retryTopicConfigurationWithExponentialBackOff() {
445+
this.contextRunner.withPropertyValues("spring.application.name=my-test-app",
446+
"spring.kafka.bootstrap-servers=localhost:9092,localhost:9093", "spring.kafka.retry.topic.enabled=true",
447+
"spring.kafka.retry.topic.attempts=5", "spring.kafka.retry.topic.backoff.delay=100ms",
448+
"spring.kafka.retry.topic.backoff.multiplier=2", "spring.kafka.retry.topic.backoff.max-delay=300ms")
449+
.run((context) -> {
450+
RetryTopicConfiguration configuration = context.getBean(RetryTopicConfiguration.class);
451+
assertThat(configuration.getDestinationTopicProperties()).hasSize(5)
452+
.extracting(DestinationTopic.Properties::delay, DestinationTopic.Properties::suffix)
453+
.containsExactly(tuple(0L, ""), tuple(100L, "-retry-0"), tuple(200L, "-retry-1"),
454+
tuple(300L, "-retry-2"), tuple(0L, "-dlt"));
455+
});
456+
}
457+
458+
@Test
459+
@Deprecated(since = "3.4.0", forRemoval = true)
460+
void retryTopicConfigurationWithExponentialBackOffUsingDeprecatedProperties() {
445461
this.contextRunner.withPropertyValues("spring.application.name=my-test-app",
446462
"spring.kafka.bootstrap-servers=localhost:9092,localhost:9093", "spring.kafka.retry.topic.enabled=true",
447463
"spring.kafka.retry.topic.attempts=5", "spring.kafka.retry.topic.delay=100ms",
@@ -471,6 +487,18 @@ void retryTopicConfigurationWithDefaultProperties() {
471487

472488
@Test
473489
void retryTopicConfigurationWithFixedBackOff() {
490+
this.contextRunner.withPropertyValues("spring.application.name=my-test-app",
491+
"spring.kafka.bootstrap-servers=localhost:9092,localhost:9093", "spring.kafka.retry.topic.enabled=true",
492+
"spring.kafka.retry.topic.attempts=4", "spring.kafka.retry.topic.backoff.delay=2s")
493+
.run(assertRetryTopicConfiguration(
494+
(configuration) -> assertThat(configuration.getDestinationTopicProperties()).hasSize(3)
495+
.extracting(DestinationTopic.Properties::delay)
496+
.containsExactly(0L, 2000L, 0L)));
497+
}
498+
499+
@Test
500+
@Deprecated(since = "3.4.0", forRemoval = true)
501+
void retryTopicConfigurationWithFixedBackOffUsingDeprecatedProperties() {
474502
this.contextRunner.withPropertyValues("spring.application.name=my-test-app",
475503
"spring.kafka.bootstrap-servers=localhost:9092,localhost:9093", "spring.kafka.retry.topic.enabled=true",
476504
"spring.kafka.retry.topic.attempts=4", "spring.kafka.retry.topic.delay=2s")
@@ -482,6 +510,18 @@ void retryTopicConfigurationWithFixedBackOff() {
482510

483511
@Test
484512
void retryTopicConfigurationWithNoBackOff() {
513+
this.contextRunner.withPropertyValues("spring.application.name=my-test-app",
514+
"spring.kafka.bootstrap-servers=localhost:9092,localhost:9093", "spring.kafka.retry.topic.enabled=true",
515+
"spring.kafka.retry.topic.attempts=4", "spring.kafka.retry.topic.backoff.delay=0")
516+
.run(assertRetryTopicConfiguration(
517+
(configuration) -> assertThat(configuration.getDestinationTopicProperties()).hasSize(3)
518+
.extracting(DestinationTopic.Properties::delay)
519+
.containsExactly(0L, 0L, 0L)));
520+
}
521+
522+
@Test
523+
@Deprecated(since = "3.4.0", forRemoval = true)
524+
void retryTopicConfigurationWithNoBackOffUsingDeprecatedProperties() {
485525
this.contextRunner.withPropertyValues("spring.application.name=my-test-app",
486526
"spring.kafka.bootstrap-servers=localhost:9092,localhost:9093", "spring.kafka.retry.topic.enabled=true",
487527
"spring.kafka.retry.topic.attempts=4", "spring.kafka.retry.topic.delay=0")

0 commit comments

Comments
 (0)