-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Replace Spring Retry usage to core retry #4059
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
base: main
Are you sure you want to change the base?
Conversation
I've just noticed the samples are broken, |
383748c
to
31d2055
Compare
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.
Thanks, Stephane!
I'm approving this change since all my feedback is minor, and we can address it on merge as subsequent commit.
We also would need to add your name to all the affected classes.
But a whats-new.adoc
deserves respective paragraph to explain such a breaking change.
Let's hear from @sobychacko yet!
spring-kafka-docs/src/main/antora/modules/ROOT/pages/kafka/serdes.adoc
Outdated
Show resolved
Hide resolved
spring-kafka/src/main/java/org/springframework/kafka/annotation/BackOffFactory.java
Show resolved
Hide resolved
spring-kafka/src/main/java/org/springframework/kafka/annotation/BackOffFactory.java
Outdated
Show resolved
Hide resolved
spring-kafka/src/main/java/org/springframework/kafka/support/ExceptionMatcher.java
Show resolved
Hide resolved
spring-kafka/src/main/java/org/springframework/kafka/support/ExceptionMatcher.java
Outdated
Show resolved
Hide resolved
@@ -107,6 +107,8 @@ void shouldSetNoBackoffPolicy() { | |||
} | |||
|
|||
@Test | |||
@Deprecated | |||
@SuppressWarnings("removal") |
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 think we should remove the test for deprecated API even now.
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 kept it as the deprecated code would be dead code and deprecating it doesn't mean nobody would call it. The test makes sure something else does not break it. Or do you mean removing the code and the test?
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.
Sure! That is just personal preference.
When I see a deprecation warning I assume that code is not supported anymore.
So, I migrate to a new API as soon as possible.
On the other hand, we don't do changes into deprecated code, therefore we may assume that behavior is the same as it was before deprecation.
Hence, removing tests for deprecated API does not change the status quo of that API: even if someone still calls, it really was covered by test before.
I may change my mind, though, if that is really found useful and helpful in other projects to keep those tests just for sake of upstream API heal check.
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 of course ultimately up to you. I think my point is that not modifying the code and calling it as part of a test are two different things.
The code may not change but what it instruments might. And without the test you won't spot the difference in behaviour.
For something like this one, it doesn't seem very important though.
...rc/test/java/org/springframework/kafka/streams/KafkaStreamsInteractiveQueryServiceTests.java
Outdated
Show resolved
Hide resolved
This commit replaces Spring Retry by the core retry support introduced in Spring Framework 7. This is a breaking change mostly in configuration that is detailed below. The main feature in Spring Kafka is BackOffValuesGenerator that generates the required BackOff values upfront. These are then managed by the listener infrastructure and Spring Retry is no longer involved. Moving this code from BackOffPolicy to BackOff dramatically simplifies that class as Spring Framework's core API naturally provides this information without the need of an extra infrastructure. From a configuration standpoint, Spring Kafka relies quite heavily on Spring Retry's `@Backoff`. As there is no equivalent, the annotation has been moved to Spring Kafka proper with the following improvements: * Harmonized name (`@BackOff` instead of `@Backoff`). * Revisited Javadoc. * Support for expression evaluation and `java.util.Duration` format. The creation of a `BackOff` instance from the annotation is now isolated in `BackOffFactory` and the relevant tests have been added. `RetryTopicConfigurationBuilder` is mostly backward-compatible but `uniformRandomBackoff` has been deprecated as we feel that its name does not convey what it actually does. `RetryingDeserializer` no longer offer a `RecoveryCallback` but an equivalent function that takes `RetryException` as an input. This contains the exceptions thrown as well as the number of retry attempts. The use of BinaryExceptionClassifier has been replaced by the newly introduced `ExceptionMatcher` that is a copy of the original algorithm with a polished API. With the migration done, we believe that further improvements can be made here: `@BackOff` oddly looks like Spring Framework's `@Retryable`. As a matter of a fact, the `maxAttempts` and `includes`/`excludes` from `@RetryableTopic` are touching the same concepts. One option would be to open up `@Retryable` so that it can be used in more case. Another area of improvement is that harmonization of BackOff as a term. It is named "Backoff" in several places, including in `@RetryableTopic`, and it would be nice if the concept had the same syntax everywhere. With Spring Retry being completely removed, this commit also removes the dependency and any further references to it. Signed-off-by: Stéphane Nicoll <[email protected]>
Signed-off-by: Stéphane Nicoll <[email protected]>
31d2055
to
ec94299
Compare
Thanks for the review Artem. I've addressed some of that in ec94299 - The only thing I am not sure is about the test testing the deprecated method, see above for more details. |
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.
@snicoll The PR looks good - this is a great effort. As we previously discussed, replacing Spring Retry with the built-in retry efforts in SF 7 seems like the right approach here. The migration feels solid overall from what I can gather. I like the new isolated approach of As expected, this is a significant breaking change for the downstream users, especially on configs, annotation switches, or Regarding the deprecation of Overall, this is cool stuff. The main thing I can think of is the migration docs with quick before/after examples, which will certainly help with a smooth user experience. Once things are merged and settled down, we certainly need to spend some cycles ensuring that there is no regression or gotchas from dropping Spring Retry altogether. Thank you! |
No. Doing so would reintroduce the problems we're trying to solve here. Trying to accommodate to slight variations in projects in the core would recreate Spring Retry in the long run. But here, that's not what I meant. Have you looked at So here, I am rather advocating whether there's an interest to streamline things in Spring Kafka to adapt to the new annotation in framework, rather than keeping a custom one. That's more efforts that I didn't want to engage in this PR as it could be rather significant. It would require some javadoc change in framework as now it's quite specific to method invocation.
Spring Boot has migration guides for new majors. IMO, the only thing that needs explaining is:
The rest isn't so bad IMO. The replacement of the calback by a Function is actually adding values. Same for replacing from Spring Retry's callback to a dedicated callback in Spring Kafka.
Can we please consider renaming the field on the annotation? It's still
The justification isn't in the javadoc but the name doesn't make sense based on what it does. As for an alternative, just look at the body of the method, it's configuring the jitter which is only using Spring Framework's API and a bit of math :) We didn't know if this feature is often used. If it is, then I suggest to reintroduce it and use the opportunity to fix the name. You can then have a new method with a more meaningful name being the replacement of the deprecated method. Thanks for the review! |
Indeed, this sounds like a good idea. This is something we can evaluate to see the impact once we merge this PR. Good with the migration guidelines in Boot. We can monitor on the Spring Kafka side to see if there is any feedback from the community side, but that is certainly down the road.
Sure, I think we can look into it post merge?
I don't know how widely this method is used, but the feature of retryable topics via non-blocking retries is pretty popular and may be utilized by many people, so I was just commenting from a public API perspective. I suggest we keep it deprecated and monitor for any potential impacts down the line. Once again, thanks for this effort! |
* @param minInterval the minimum interval. | ||
* @param maxInterval the maximum interval. | ||
* @return the builder. | ||
* @deprecated as of 4.0 with no replacement |
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.
Well, looking into the UniformRandomBackOffPolicy
in Spring Retry, it feels similar to the ExponentialRandomBackOffPolicy
, but without a multiplier
.
I would say it should be safe to state this one is deprecated in favor of exponentialBackoff()
since we don't carry out UniformRandomBackOffPolicy
abstraction anymore.
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.
sounds good then.
There might be a misunderstanding here. I mentioned Spring Boot has migration guides in major releases. However, we do not intend to document the changes in Spring Boot as it belongs here. We could, however, link to your migration guide from ours. Does that make sense? |
This commit replaces Spring Retry by the core retry support introduced in Spring Framework 7. This is a breaking change mostly in configuration that is detailed below.
The main feature in Spring Kafka is BackOffValuesGenerator that generates the required BackOff values upfront. These are then managed by the listener infrastructure and Spring Retry is no longer involved.
Moving this code from BackOffPolicy to BackOff dramatically simplifies that class as Spring Framework's core API naturally provides this information without the need of an extra infrastructure.
From a configuration standpoint, Spring Kafka relies quite heavily on Spring Retry's
@Backoff
. As there is no equivalent, the annotation has been moved to Spring Kafka proper with the following improvements:@BackOff
instead of@Backoff
).java.util.Duration
format.The creation of a
BackOff
instance from the annotation is now isolated inBackOffFactory
and the relevant tests have been added.RetryTopicConfigurationBuilder
is mostly backward-compatible butuniformRandomBackoff
has been deprecated as we feel that its name does not convey what it actually does.RetryingDeserializer
no longer offer aRecoveryCallback
but an equivalent function that takesRetryException
as an input. This contains the exceptions thrown as well as the number of retry attempts.The use of BinaryExceptionClassifier has been replaced by the newly introduced
ExceptionMatcher
that is a copy of the original algorithm with a polished API.With the migration done, we believe that further improvements can be made here:
@BackOff
oddly looks like Spring Framework's@Retryable
. As a matter of a fact, themaxAttempts
andincludes
/excludes
from@RetryableTopic
are touching the same concepts. One option would be to open up@Retryable
so that it can be used in more case.Another area of improvement is that harmonization of BackOff as a term. It is named "Backoff" in several places, including in
@RetryableTopic
, and it would be nice if the concept had the same syntax everywhere.With Spring Retry being completely removed, this commit also removes the dependency and any further references to it.