-
Notifications
You must be signed in to change notification settings - Fork 41.1k
Add support for Elasticsearch Sniffer #24340
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
Conversation
Added autoconfig support and tests for the elastic search sniffer.
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 for the PR, they are a number of things to reconsider. Can you please have a look?
@ConditionalOnClass(RestHighLevelClient.class) | ||
@ConditionalOnMissingBean(RestClient.class) | ||
@EnableConfigurationProperties(ElasticsearchSnifferProperties.class) | ||
public class ElasticsearchSnifferAutoConfiguration { |
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 don't think it should be a separate auto-configuration. Rather it should be part of what we already auto-configure.
*/ | ||
@Configuration(proxyBeanMethods = false) | ||
@ConditionalOnClass(RestHighLevelClient.class) | ||
@ConditionalOnMissingBean(RestClient.class) |
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.
The purpose of the sniffer is to work based on a RestClient
but this auto-configuration doesn't do anything if such bean is present?
static class SnifferBuilderConfiguration { | ||
|
||
@Bean | ||
SnifferBuilderCustomizer defaultSnifferBuilderCustomizer(ElasticsearchSnifferProperties properties) { |
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.
For simple use case like this one there is no need to create a customizer for what the auto-configuration does. We can smart small and configure the sniffer based on the properties only.
@Bean | ||
Sniffer elasticsearchSnifferBuilder(ElasticsearchSnifferProperties properties, | ||
RestClient elasticsearchRestClient) { | ||
return Sniffer.builder(elasticsearchRestClient).build(); |
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.
Spring Boot no longer exposes a RestClient
. Rather, it is created internally as part of ElasticsearchRestClientAutoConfiguration
which is where this code should go.
The documentation also states that order in which those are destroy is important:
It is important to close the Sniffer so that its background thread gets properly shutdown and all of its resources are released. The Sniffer object should have the same lifecycle as the RestClient and get closed right before the client:
/** | ||
* Sniffer interval millis | ||
*/ | ||
private Duration sniffIntervalMillis = Duration.ofMillis(1L); |
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.
A Duration
property should not have mills
(or any unit) in its name since users are free to chose a different unit if they want to.
Also, the default value is wrong, it should be 5 min.
/** | ||
* Sniffer failure delay millis. | ||
*/ | ||
private Duration sniffFailureDelayMillis = Duration.ofMillis(1L); |
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.
The default value is not 1ms but 1 minute.
* | ||
*/ | ||
@FunctionalInterface | ||
public interface SnifferBuilderCustomizer { |
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 don't need this for a first pass. Those who want to configure the NodesSniffer
can do so with their own Sniffer
instance.
* @author Asha Somayajula | ||
*/ | ||
@Testcontainers(disabledWithoutDocker = true) | ||
class ElasticsearchSnifferAutoConfigurationTests { |
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 should move to the main ElasticsearchRestClientAutoConfigurationTests
. A test should be added with a filtered class loader on the sniffer library to validate things are working as expected.
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 for the follow-up but some parts of my previous review were not processed. Can you please have a look again?
RestClient elasticSearchRestClient) { | ||
return Sniffer.builder(elasticSearchRestClient) | ||
.setSniffIntervalMillis( | ||
Math.toIntExact(properties.getSniffInterval().getSeconds() * 1000)) |
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 isn't necessary. The duration gives you a way to get the ms directly.
@@ -80,6 +83,17 @@ RestClientBuilder elasticsearchRestClientBuilder(ElasticsearchRestClientProperti | |||
return builder; | |||
} | |||
|
|||
@Bean | |||
Sniffer elasticsearchSnifferBuilder(ElasticsearchSnifferProperties properties, |
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 doesn't check that the sniffer library is on the classpath. If it isn't, this bean should not be defined at all. It's also missing a @ConditionalOnMissingBean
in case the user has created their own.
* | ||
*/ | ||
@ConfigurationProperties(prefix = "spring.elasticsearch.sniff") | ||
public class ElasticsearchSnifferProperties { |
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 should move to ElasticsearchRestClientProperties
. There is no reason for those two attributes to be in their own type since they relate to Elasticsearch's rest support anyway.
Assert.assertNotNull(sniffer); | ||
}); | ||
} | ||
|
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.
Two tests are missing here.
One that assert what happens when the library is not on the classpath, as I've indicated in my previous review.
One that assert that a custom Sniffer
instance is used rather creating one here. This custom instance should probably have a dependency on the high level client we auto-configure to make this a bit more realistic.
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 for the update again but the tests you've added don't pass. Can you please build the module and make sure the tests are working before submitting further changes?
If you want me to take over, I can also do that.
@Conditional(IsSnifferAvailableOnClasspathCondition.class) | ||
@ConditionalOnMissingBean(RestHighLevelClient.class) | ||
Sniffer elasticsearchSnifferBuilder(ElasticsearchRestClientProperties properties, | ||
RestClient elasticSearchRestClient) { |
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.
Have you run the test before pushing an update? As I've explained several times in this issue, we do not expose a RestClient so requiring a RestClient bean is never going to work.
@Bean | ||
@Conditional(IsSnifferAvailableOnClasspathCondition.class) | ||
@ConditionalOnMissingBean(RestHighLevelClient.class) | ||
Sniffer elasticsearchSnifferBuilder(ElasticsearchRestClientProperties properties, |
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.
The builder
in the name sounds unnecessary.
@@ -80,6 +84,19 @@ RestClientBuilder elasticsearchRestClientBuilder(ElasticsearchRestClientProperti | |||
return builder; | |||
} | |||
|
|||
@Bean | |||
@Conditional(IsSnifferAvailableOnClasspathCondition.class) |
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.
That's not how classpath checks work. Can you please have a look to @ConditionalOnClass
and how it's used in other parts of this codebase (in particular, it's not added on methods, check the Javadoc for more details).
/** | ||
* Sniffer interval | ||
*/ | ||
private Duration sniffInterval = Duration.ofMinutes(5L); |
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.
Those properties should be in a public static class Sniffer
inner class. Check other @ConfigurationProperties
for an example.
@@ -56,6 +56,14 @@ | |||
* Read timeout. | |||
*/ | |||
private Duration readTimeout = Duration.ofSeconds(30); | |||
/** | |||
* Sniffer interval |
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.
Configuration property description ends with a dot. Please consider reviewing the description to better explain what that does.
@@ -97,4 +105,19 @@ public void setReadTimeout(Duration readTimeout) { | |||
this.readTimeout = readTimeout; | |||
} | |||
|
|||
public Duration getSniffInterval() { | |||
return sniffInterval; |
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.
missing this.
. This sort of things can be easily spot if you ran the build locally before pushing your changes.
} | ||
|
||
public Duration getSniffFailureDelay() { | ||
return sniffFailureDelay; |
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.
Ditto.
import org.springframework.context.annotation.ConditionContext; | ||
import org.springframework.core.type.AnnotatedTypeMetadata; | ||
|
||
public class IsSnifferAvailableOnClasspathCondition implements Condition { |
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 should go away. @ConditionalOnClass
already does that.
this.contextRunner.run( | ||
(context) -> assertThat(context).doesNotHaveBean(RestClient.class) | ||
.hasSingleBean(RestHighLevelClient.class)); | ||
this.contextRunner.run( |
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.
A single test shouldn't run the context twice ideally.
|
||
@Test | ||
void configureWithCustomSetIntervalProperties() { | ||
this.contextRunner.withPropertyValues("spring.elasticsearch.rest.sniffInterval=15s, " + |
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.
15s,
is not a valid duration. Did you forget to complete this test maybe?
Thanks for the feedback. I believe all of the changes requested are in place now. |
Unfortunately, 4 of the 5 tests you've added are still failing for me. It might be because you don't have docker running locally and the tests are skipped for you (see Thank you very much for the follow-up and the feedback on the reviews. Unfortunately, there are quite a lot of pieces that still need more work and I've decided to take over. Please review 1fd17cf for more details. Thanks for the PR, in any case! |
Thanks for considering.
Regards,
Asha
…On Wed, Dec 23, 2020 at 10:15 AM Stéphane Nicoll ***@***.***> wrote:
I believe all of the changes requested are in place now.
Unfortunately, 4 of the 5 tests you've added are still failing for me. It
might be because you don't have docker running locally and the tests are
skipped for you (see @testcontainers(disabledWithoutDocker = true) at the
top of the test class).
Thank you very much for the follow-up and the feedback on the reviews.
Unfortunately, there are quite a lot of pieces that still need more work
and I've decided to take over. Please review 1fd17cf
<1fd17cf>
for more details. Thanks for the PR, in any case!
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#24340 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AIRAZGKMLHLFB4Q4JHAUJW3SWIJTTANCNFSM4UOVTK2Q>
.
|
Added autoconfig support and tests for the elastic search sniffer.