-
Notifications
You must be signed in to change notification settings - Fork 1.6k
GH-2116: Add blocking retries to RT #2124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
7998944
85cab3f
a7e069b
29ced81
ce9656b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,7 +42,7 @@ | |
import org.springframework.kafka.listener.adapter.KafkaBackoffAwareMessageListenerAdapter; | ||
import org.springframework.kafka.support.TopicPartitionOffset; | ||
import org.springframework.util.Assert; | ||
import org.springframework.util.backoff.FixedBackOff; | ||
import org.springframework.util.backoff.BackOff; | ||
|
||
/** | ||
* | ||
|
@@ -81,6 +81,8 @@ public class ListenerContainerFactoryConfigurer { | |
|
||
private static final long LOWEST_BACKOFF_THRESHOLD = 1500L; | ||
|
||
private BackOff providedBlockingBackOff = null; | ||
|
||
private Consumer<ConcurrentMessageListenerContainer<?, ?>> containerCustomizer = container -> { | ||
}; | ||
|
||
|
@@ -158,6 +160,20 @@ public KafkaListenerContainerFactory<?> decorateFactoryWithoutSettingContainerPr | |
return new RetryTopicListenerContainerFactoryDecorator(factory, configuration, false); | ||
} | ||
|
||
/** | ||
* Set a {@link BackOff} to be used with blocking retries. | ||
* You can specify the exceptions to be retried using the method | ||
* {@link org.springframework.kafka.listener.ExceptionClassifier#addRetryableExceptions(Class[])} | ||
* By default, no exceptions are retried via blocking. | ||
* @param blockingBackOff the BackOff policy to be used by blocking retries. | ||
* @since 2.8.4 | ||
* @see DefaultErrorHandler | ||
*/ | ||
public void setBlockingRetriesBackOff(BackOff blockingBackOff) { | ||
Assert.notNull(blockingBackOff, "The provided BackOff cannot be null"); | ||
this.providedBlockingBackOff = blockingBackOff; | ||
} | ||
|
||
private ConcurrentKafkaListenerContainerFactory<?, ?> doConfigure( | ||
ConcurrentKafkaListenerContainerFactory<?, ?> containerFactory, Configuration configuration, | ||
boolean isSetContainerProperties) { | ||
|
@@ -193,14 +209,20 @@ public void setErrorHandlerCustomizer(Consumer<CommonErrorHandler> errorHandlerC | |
|
||
protected CommonErrorHandler createErrorHandler(DeadLetterPublishingRecoverer deadLetterPublishingRecoverer, | ||
Configuration configuration) { | ||
DefaultErrorHandler errorHandler = new DefaultErrorHandler(deadLetterPublishingRecoverer, | ||
new FixedBackOff(0, 0)); | ||
DefaultErrorHandler errorHandler = createDefaultErrorHandlerInstance(deadLetterPublishingRecoverer); | ||
errorHandler.defaultFalse(); | ||
errorHandler.setCommitRecovered(true); | ||
errorHandler.setLogLevel(KafkaException.Level.DEBUG); | ||
this.errorHandlerCustomizer.accept(errorHandler); | ||
return errorHandler; | ||
} | ||
|
||
protected DefaultErrorHandler createDefaultErrorHandlerInstance(DeadLetterPublishingRecoverer deadLetterPublishingRecoverer) { | ||
return this.providedBlockingBackOff != null | ||
? new DefaultErrorHandler(deadLetterPublishingRecoverer, this.providedBlockingBackOff) | ||
: new DefaultErrorHandler(deadLetterPublishingRecoverer); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't right; the default fixed back off is (0, 9), we need (0, 0). Why not just set the field to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, considering all exceptions will return false when classified by default, it doesn't really matter what's the backoff policy - we can just leave the default one and then the user would have only to add the retryable exceptions, which would then make the default or provided back off kick in. Anyway, we can set the no ops back off too, no worries. Either way I think the other classes modifications to pass the consumer to DLPR are still needed, since we might go that route for exception classifications that return false. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh; Ok; makes sense to leave it. |
||
} | ||
|
||
protected void setupBackoffAwareMessageListenerAdapter(ConcurrentMessageListenerContainer<?, ?> container, | ||
Configuration configuration, boolean isSetContainerProperties) { | ||
AcknowledgingConsumerAwareMessageListener<?, ?> listener = checkAndCast(container.getContainerProperties() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add something like "If the backoff execution returns STOP (retries are exhausted), the record will then go to the next retry topic (if present)."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think the aggregated behavior of blocking and non-blocking can be better documented in general. I'll see what I can come up with.