From 99ae6dac5321a741d93ff5187fafb94c295a6928 Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Mon, 11 Apr 2016 18:23:27 +0200 Subject: [PATCH] Customize Couchbase's socket connect timeout Our Windows build is failing currently because the couchbase server does not handle a socket connection within a second (the default). This commit adds a property to customize this option and set it to 10 sec in the sample. While investigating this issue, it turns out that while `CouchbaseConfiguration` is public, it is not really possible to extend it in user's configuration. This commit fixes this problem and add a test that demonstrates how it can be used. Closes gh-5657 --- .../couchbase/CouchbaseAutoConfiguration.java | 16 +++--- .../couchbase/CouchbaseProperties.java | 13 +++++ .../CouchbaseAutoConfigurationTests.java | 56 ++++++++++++++++++- .../appendix-application-properties.adoc | 1 + .../src/main/resources/application.properties | 2 + 5 files changed, 77 insertions(+), 11 deletions(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/couchbase/CouchbaseAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/couchbase/CouchbaseAutoConfiguration.java index c569fab30b..47c0bbf8a3 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/couchbase/CouchbaseAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/couchbase/CouchbaseAutoConfiguration.java @@ -21,7 +21,6 @@ import com.couchbase.client.java.Cluster; import com.couchbase.client.java.CouchbaseBucket; import com.couchbase.client.java.CouchbaseCluster; import com.couchbase.client.java.cluster.ClusterInfo; -import com.couchbase.client.java.env.CouchbaseEnvironment; import com.couchbase.client.java.env.DefaultCouchbaseEnvironment; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -51,7 +50,7 @@ import org.springframework.data.couchbase.config.CouchbaseConfigurer; public class CouchbaseAutoConfiguration { @Configuration - @ConditionalOnMissingBean(CouchbaseConfigurer.class) + @ConditionalOnMissingBean({CouchbaseConfigurer.class, CouchbaseConfiguration.class}) public static class CouchbaseConfiguration { private final CouchbaseProperties properties; @@ -62,8 +61,8 @@ public class CouchbaseAutoConfiguration { @Bean @Primary - public CouchbaseEnvironment couchbaseEnvironment() throws Exception { - return createEnvironment(this.properties); + public DefaultCouchbaseEnvironment couchbaseEnvironment() throws Exception { + return initializeEnvironmentBuilder(this.properties).build(); } @Bean @@ -90,11 +89,11 @@ public class CouchbaseAutoConfiguration { } /** - * Create a {@link CouchbaseEnvironment} based on the specified settings. + * Initialize an environment builder based on the specified settings. * @param properties the couchbase properties to use - * @return a {@link CouchbaseEnvironment} + * @return a {@link DefaultCouchbaseEnvironment.Builder} */ - protected CouchbaseEnvironment createEnvironment(CouchbaseProperties properties) { + protected DefaultCouchbaseEnvironment.Builder initializeEnvironmentBuilder(CouchbaseProperties properties) { CouchbaseProperties.Endpoints endpoints = properties.getEnv().getEndpoints(); CouchbaseProperties.Timeouts timeouts = properties.getEnv().getTimeouts(); DefaultCouchbaseEnvironment.Builder builder = DefaultCouchbaseEnvironment @@ -103,6 +102,7 @@ public class CouchbaseAutoConfiguration { .kvTimeout(timeouts.getKeyValue()) .queryEndpoints(endpoints.getQuery()) .queryTimeout(timeouts.getQuery()).viewEndpoints(endpoints.getView()) + .socketConnectTimeout(timeouts.getSocketConnect()) .viewTimeout(timeouts.getView()); CouchbaseProperties.Ssl ssl = properties.getEnv().getSsl(); if (ssl.getEnabled()) { @@ -114,7 +114,7 @@ public class CouchbaseAutoConfiguration { builder.sslKeystorePassword(ssl.getKeyStorePassword()); } } - return builder.build(); + return builder; } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/couchbase/CouchbaseProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/couchbase/CouchbaseProperties.java index 7451657d63..481f40d3fb 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/couchbase/CouchbaseProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/couchbase/CouchbaseProperties.java @@ -217,6 +217,11 @@ public class CouchbaseProperties { */ private long query = 7500; + /** + * Socket connect connections timeout in milliseconds. + */ + private int socketConnect = 1000; + /** * Regular and geospatial view operations timeout in milliseconds. */ @@ -246,6 +251,14 @@ public class CouchbaseProperties { this.query = query; } + public int getSocketConnect() { + return this.socketConnect; + } + + public void setSocketConnect(int socketConnect) { + this.socketConnect = socketConnect; + } + public long getView() { return this.view; } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/couchbase/CouchbaseAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/couchbase/CouchbaseAutoConfigurationTests.java index 9fab0a1fc8..34a68a22a4 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/couchbase/CouchbaseAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/couchbase/CouchbaseAutoConfigurationTests.java @@ -18,6 +18,7 @@ package org.springframework.boot.autoconfigure.couchbase; import com.couchbase.client.java.Bucket; import com.couchbase.client.java.Cluster; +import com.couchbase.client.java.CouchbaseBucket; import com.couchbase.client.java.cluster.ClusterInfo; import com.couchbase.client.java.env.CouchbaseEnvironment; import com.couchbase.client.java.env.DefaultCouchbaseEnvironment; @@ -25,7 +26,13 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration.CouchbaseConfiguration; +import org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; /** * Tests for {@link CouchbaseAutoConfiguration} @@ -85,11 +92,13 @@ public class CouchbaseAutoConfigurationTests "spring.couchbase.env.timeouts.connect=100", "spring.couchbase.env.timeouts.keyValue=200", "spring.couchbase.env.timeouts.query=300", - "spring.couchbase.env.timeouts.view=400"); + "spring.couchbase.env.timeouts.socket-connect=400", + "spring.couchbase.env.timeouts.view=500"); assertThat(env.connectTimeout()).isEqualTo(100); assertThat(env.kvTimeout()).isEqualTo(200); assertThat(env.queryTimeout()).isEqualTo(300); - assertThat(env.viewTimeout()).isEqualTo(400); + assertThat(env.socketConnectTimeout()).isEqualTo(400); + assertThat(env.viewTimeout()).isEqualTo(500); } @Test @@ -113,12 +122,53 @@ public class CouchbaseAutoConfigurationTests assertThat(env.sslKeystorePassword()).isNull(); } + @Test + public void customizeEnvWithCustomCouchbaseConfiguration() { + load(CustomCouchbaseConfiguration.class, "spring.couchbase.bootstrap-hosts=localhost", + "spring.couchbase.env.timeouts.connect=100"); + assertThat(this.context.getBeansOfType(CouchbaseConfiguration.class)).hasSize(1); + DefaultCouchbaseEnvironment env = this.context.getBean(DefaultCouchbaseEnvironment.class); + assertThat(env.socketConnectTimeout()).isEqualTo(5000); + assertThat(env.connectTimeout()).isEqualTo(2000); + } + private DefaultCouchbaseEnvironment customizeEnv(String... environment) throws Exception { load(CouchbaseTestConfigurer.class, environment); CouchbaseProperties properties = this.context.getBean(CouchbaseProperties.class); - return (DefaultCouchbaseEnvironment) new CouchbaseAutoConfiguration.CouchbaseConfiguration( + return new CouchbaseConfiguration( properties).couchbaseEnvironment(); } + @Configuration + @Import(CouchbaseDataAutoConfiguration.class) + static class CustomCouchbaseConfiguration extends CouchbaseConfiguration { + + CustomCouchbaseConfiguration(CouchbaseProperties properties) { + super(properties); + } + + @Override + protected DefaultCouchbaseEnvironment.Builder initializeEnvironmentBuilder(CouchbaseProperties properties) { + return super.initializeEnvironmentBuilder(properties) + .socketConnectTimeout(5000).connectTimeout(2000); + } + + @Override + public Cluster couchbaseCluster() throws Exception { + return mock(Cluster.class); + } + + @Override + public ClusterInfo couchbaseClusterInfo() { + return mock(ClusterInfo.class); + } + + @Override + public Bucket couchbaseClient() { + return mock(CouchbaseBucket.class); + } + + } + } diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 24cecd3d1d..6a1fc35c80 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -505,6 +505,7 @@ content into your application; rather pick only the properties that you need. spring.couchbase.env.timeouts.connect=5000 # Bucket connections timeout in milliseconds. spring.couchbase.env.timeouts.key-value=2500 # Blocking operations performed on a specific key timeout in milliseconds. spring.couchbase.env.timeouts.query=7500 # N1QL query operations timeout in milliseconds. + spring.couchbase.env.timeouts.socket-connect=1000 # Socket connect connections timeout in milliseconds. spring.couchbase.env.timeouts.view=7500 # Regular and geospatial view operations timeout in milliseconds. # DAO ({sc-spring-boot-autoconfigure}/dao/PersistenceExceptionTranslationAutoConfiguration.{sc-ext}[PersistenceExceptionTranslationAutoConfiguration]) diff --git a/spring-boot-samples/spring-boot-sample-data-couchbase/src/main/resources/application.properties b/spring-boot-samples/spring-boot-sample-data-couchbase/src/main/resources/application.properties index d27b4120e2..e1679cc372 100644 --- a/spring-boot-samples/spring-boot-sample-data-couchbase/src/main/resources/application.properties +++ b/spring-boot-samples/spring-boot-sample-data-couchbase/src/main/resources/application.properties @@ -1,4 +1,6 @@ spring.couchbase.bootstrap-hosts=localhost + spring.couchbase.env.timeouts.connect=10000 +spring.couchbase.env.timeouts.socket-connect=10000 spring.data.couchbase.auto-index=true