-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
GH-2800: Make it possible to route messages to custom DLT based on exceptions thrown #2929
Conversation
@breader124 Thanks for the PR. I am going to take a look reviewing the changes. One general comment. Could you add some docs snippets related to the change? This seems like a bigger change that deserves some notes in the reference docs. |
Sure, I was thinking about modifications in the reference docs as well. The only thing I'd like to wait for until I start working on it is the confirmation of the API part of changes. Having the API stable I'll propose docs changes |
Since this PR is large in terms of the changes, could you provide a brief overview of the changes in a few sentences? Please provide a flow of the changes, the APIs you added, etc. It doesn't have to be very elaborate, but brief. |
The main difference that I introduced is the possibility to configure the routing to the custom DLTs based on the exceptions thrown during the message processing. This configuration can be provided in 2 ways (and these are the only new APIs):
When the configuration is provided, then depending on the Lastly, when it comes to the actual routing part, I've modified the Besides all changes described above I also provided tests for the changed behaviour. |
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.
This sounds reasonable, but unfortunately it introduces some breaking changes to public API. To avoid immediate upgrade in the target projects we cannot accept this change for the current patch version.
We are fully OK to schedule this for the next 3.2
generation, but not earlier.
Therefore your PR will sit here for a while.
Thanks for understanding.
That's a great point, Artem. @ breader124 If you still want to go into the patch release, could you still make these changes without breaking an existing API? It might still be okay to add new API's as we have done in some other existing PR's. Update: It is better to postpone this PR for |
It's totally fine for me to wait for a while @artembilan, @sobychacko. I'll update the |
* @see org.springframework.kafka.retrytopic.ExceptionBasedDltRouting | ||
* @since 3.2.0 | ||
*/ | ||
public @interface ExceptionBasedDestinationDlt { |
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.
Maybe ExceptionBasedDltDestination
?
...afka/src/main/java/org/springframework/kafka/retrytopic/DefaultDestinationTopicResolver.java
Show resolved
Hide resolved
@breader124 I did a first pass at the PR. It looks good. One general question: The corresponding issue that was created by the SO thread , originally trying to route records from deserialization exceptions. Is that use case addressed by this PR? |
Yes, it's possible to configure the |
please, rebase your branch to the latest Then we will start looking into your change to incorporate it into a new version. Thanks |
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.
I also believe that this feature deserves some docs in the \spring-kafka\spring-kafka-docs\src\main\antora\modules\ROOT\pages\retrytopic\
dir.
But yeah, that can be done in the end when we agree with all the changes from the code perspective.
Thanks
@@ -188,13 +196,15 @@ public Properties(Properties sourceProperties, String suffix, Type type) { | |||
* @param shouldRetryOn the exception classifications. | |||
* @param timeout the timeout. | |||
* @param autoStartDltHandler whether or not to start the DLT handler. | |||
* @param usedForExceptions the exceptions which destination is intended for | |||
* @since 2.8 | |||
*/ | |||
public Properties(long delayMs, String suffix, Type type, |
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.
I suggest to have one more public ctor.
This way we won't have a breaking change in the point version.
* @return The {@link DestinationTopic} instance corresponding to the DLT. | ||
*/ | ||
@Nullable | ||
DestinationTopic getDltFor(String mainListenerId, String topicName); | ||
DestinationTopic getDltFor(String mainListenerId, String topicName, Exception exc); |
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.
Cannot we have another method to avoid a breaking change?
It also would be great to have it as a default
to avoid a immediate upgrade compilation problem.
We may have the current method deprecated then.
...ka/src/main/java/org/springframework/kafka/retrytopic/DestinationTopicPropertiesFactory.java
Show resolved
Hide resolved
...g-kafka/src/main/java/org/springframework/kafka/retrytopic/ExceptionBasedDltDestination.java
Show resolved
Hide resolved
* | ||
* @return the configured suffix extension | ||
*/ | ||
String suffix(); |
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.
I wonder if this is really required and can be just empty by default...
Also: no blank lines in the method Javadocs: https://github.com/spring-projects/spring-framework/wiki/Code-Style#javadoc-formatting
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.
From my point of view having the suffix
required makes this API harder to misuse by design. exceptions
is required, but when someone will be allowed to specify exceptions without the suffix
, then it means that the general purpose DLT will be used even for this exc. I'm not sure when it could be an intended usage
* @see ExceptionBasedDltDestination | ||
* @since 3.2.0 | ||
*/ | ||
public @interface ExceptionBasedDltRouting { |
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.
Why do we need this annotation if @RetryableTopic
could just have a property like that below?
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.
It's not needed, I'll delete it
* @since 3.2.0 | ||
*/ | ||
public RetryTopicConfigurationBuilder dltRoutingRules(Map<String, Set<Class<? extends Throwable>>> dltRoutingRules) { | ||
this.dltRoutingRules = dltRoutingRules; |
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.
This is not OK. Has to be a copy.
The point is to avoid internal mutation when that external map is edited.
Well, that dltRoutingRules
could be final and here you could just use putAll()
Still, rebased is required for this PR. Thanks |
Thanks for the review. I've just pushed the rebased code and will apply the changes you've suggested in the review over the weekend together with the docs changes suggestions |
1777968
to
c5dd055
Compare
@artembilan, @sobychacko, I've just rebased the code on top of the most recent |
spring-kafka/src/main/java/org/springframework/kafka/annotation/RetryableTopic.java
Show resolved
Hide resolved
...ka/src/main/java/org/springframework/kafka/annotation/RetryableTopicAnnotationProcessor.java
Show resolved
Hide resolved
@@ -96,6 +131,7 @@ public DestinationTopicPropertiesFactory(String retryTopicSuffix, String dltSuff | |||
this.sameIntervalTopicReuseStrategy = sameIntervalTopicReuseStrategy; | |||
this.timeout = timeout; | |||
this.destinationTopicSuffixes = new DestinationTopicSuffixes(retryTopicSuffix, dltSuffix); | |||
this.dltRoutingRules = dltRoutingRules; |
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.
This is not OK. Has to be a copy of the map.
This way we will avoid the problem when provided map is mutated somewhere outside.
Routing customization consists of the specification of the additional destinations. | ||
Destinations in turn consist of two settings: the `suffix` and `exceptions`. | ||
When the exception type specified in `exceptions` has been thrown, the DLT containing the `suffix` will be considered as the target topic for the message before the general purpose DLT is considered. | ||
Take a look at the examples: |
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.
I prefer to have an official neutral language in docs where it is depersonalized.
So, no phrases like you
, me
, take a look
etc.
But... That's my personal preferences and I know there are many like that throughout the doc.
Also: this need to me mentioned in the whats-new.adoc
@breader124 There was a recent change made via another PR that modified |
Sure, will do it and push tomorrow the latest |
@sobychacko, it's now rebased on top of the current |
@breader124 Thank you for this excellent PR. It is now merged upstream. |
This PR is related to #2800. It introduces changes making it easy for developers to route messages to different DLTs when the previously configured exception is thrown.