This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 9da2d23406496d77344a1fad18112f35ac2c9565
Author: Benoit Tellier <[email protected]>
AuthorDate: Sun Nov 28 15:13:38 2021 +0700

    JAMES-3676 Allow configuring S3 driver read, write and connection timeout
---
 .../modules/ROOT/pages/configure/blobstore.adoc    |  9 ++++
 .../aws/S3BlobStoreConfiguration.java              | 56 ++++++++++++++++++++--
 .../S3BlobStoreConfigurationReader.java            | 15 ++++++
 src/site/xdoc/server/config-blobstore.xml          |  9 ++++
 4 files changed, 86 insertions(+), 3 deletions(-)

diff --git 
a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/blobstore.adoc 
b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/blobstore.adoc
index d8e58c2..66bdd4f 100644
--- 
a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/blobstore.adoc
+++ 
b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/blobstore.adoc
@@ -139,6 +139,15 @@ Maximum size of stored objects expressed in bytes.
 
 | objectstorage.s3.truststore.algorithm
 | optional: Use this specific trust store algorithm; default SunX509
+
+| objectstorage.s3.read.timeout
+| optional: HTTP read timeout. duration, default value being second. Leaving 
it empty relies on S3 driver defaults.
+
+| objectstorage.s3.write.timeout
+| optional: HTTP write timeout. duration, default value being second. Leaving 
it empty relies on S3 driver defaults.
+
+| objectstorage.s3.connection.timeout
+| optional: HTTP connection timeout. duration, default value being second. 
Leaving it empty relies on S3 driver defaults.
 |===
 
 ==== Buckets Configuration
diff --git 
a/server/blob/blob-s3/src/main/java/org/apache/james/blob/objectstorage/aws/S3BlobStoreConfiguration.java
 
b/server/blob/blob-s3/src/main/java/org/apache/james/blob/objectstorage/aws/S3BlobStoreConfiguration.java
index a456d4a..7af3064 100644
--- 
a/server/blob/blob-s3/src/main/java/org/apache/james/blob/objectstorage/aws/S3BlobStoreConfiguration.java
+++ 
b/server/blob/blob-s3/src/main/java/org/apache/james/blob/objectstorage/aws/S3BlobStoreConfiguration.java
@@ -19,6 +19,7 @@
 
 package org.apache.james.blob.objectstorage.aws;
 
+import java.time.Duration;
 import java.util.Objects;
 import java.util.Optional;
 
@@ -52,6 +53,9 @@ public class S3BlobStoreConfiguration {
             private Optional<BucketName> defaultBucketName;
             private Optional<String> bucketPrefix;
             private Optional<Integer> httpConcurrency;
+            private Optional<Duration> readTimeout;
+            private Optional<Duration> writeTimeout;
+            private Optional<Duration> connectionTimeout;
             private Region region;
 
             public ReadyToBuild(AwsS3AuthConfiguration 
specificAuthConfiguration, Region region) {
@@ -60,6 +64,9 @@ public class S3BlobStoreConfiguration {
                 this.defaultBucketName = Optional.empty();
                 this.bucketPrefix = Optional.empty();
                 this.httpConcurrency = Optional.empty();
+                this.readTimeout = Optional.empty();
+                this.writeTimeout = Optional.empty();
+                this.connectionTimeout = Optional.empty();
             }
 
             public ReadyToBuild defaultBucketName(Optional<BucketName> 
defaultBucketName) {
@@ -77,6 +84,21 @@ public class S3BlobStoreConfiguration {
                 return this;
             }
 
+            public ReadyToBuild writeTimeout(Optional<Duration> writeTimeout) {
+                this.writeTimeout = writeTimeout;
+                return this;
+            }
+
+            public ReadyToBuild connectionTimeout(Optional<Duration> 
connectionTimeout) {
+                this.connectionTimeout = connectionTimeout;
+                return this;
+            }
+
+            public ReadyToBuild readTimeout(Optional<Duration> readTimeout) {
+                this.readTimeout = readTimeout;
+                return this;
+            }
+
             public ReadyToBuild bucketPrefix(String bucketPrefix) {
                 this.bucketPrefix = Optional.ofNullable(bucketPrefix);
                 return this;
@@ -88,7 +110,7 @@ public class S3BlobStoreConfiguration {
             }
 
             public S3BlobStoreConfiguration build() {
-                return new S3BlobStoreConfiguration(bucketPrefix, 
defaultBucketName, region, specificAuthConfiguration, 
httpConcurrency.orElse(DEFAULT_HTTP_CONCURRENCY));
+                return new S3BlobStoreConfiguration(bucketPrefix, 
defaultBucketName, region, specificAuthConfiguration, 
httpConcurrency.orElse(DEFAULT_HTTP_CONCURRENCY), readTimeout, writeTimeout, 
connectionTimeout);
             }
         }
 
@@ -101,18 +123,27 @@ public class S3BlobStoreConfiguration {
     private final Optional<BucketName> namespace;
     private final Optional<String> bucketPrefix;
     private final int httpConcurrency;
+    private Optional<Duration> readTimeout;
+    private Optional<Duration> writeTimeout;
+    private Optional<Duration> connectionTimeout;
 
     @VisibleForTesting
     S3BlobStoreConfiguration(Optional<String> bucketPrefix,
                              Optional<BucketName> namespace,
                              Region region,
                              AwsS3AuthConfiguration specificAuthConfiguration,
-                             int httpConcurrency) {
+                             int httpConcurrency,
+                             Optional<Duration> readTimeout,
+                             Optional<Duration> writeTimeout,
+                             Optional<Duration> connectionTimeout) {
         this.bucketPrefix = bucketPrefix;
         this.namespace = namespace;
         this.region = region;
         this.specificAuthConfiguration = specificAuthConfiguration;
         this.httpConcurrency = httpConcurrency;
+        this.readTimeout = readTimeout;
+        this.writeTimeout = writeTimeout;
+        this.connectionTimeout = connectionTimeout;
     }
 
     public Optional<BucketName> getNamespace() {
@@ -135,6 +166,18 @@ public class S3BlobStoreConfiguration {
         return region;
     }
 
+    public Optional<Duration> getReadTimeout() {
+        return readTimeout;
+    }
+
+    public Optional<Duration> getWriteTimeout() {
+        return writeTimeout;
+    }
+
+    public Optional<Duration> getConnectionTimeout() {
+        return connectionTimeout;
+    }
+
     @Override
     public final boolean equals(Object o) {
         if (o instanceof S3BlobStoreConfiguration) {
@@ -144,6 +187,9 @@ public class S3BlobStoreConfiguration {
                 && Objects.equals(this.bucketPrefix, that.bucketPrefix)
                 && Objects.equals(this.region, that.region)
                 && Objects.equals(this.httpConcurrency, that.httpConcurrency)
+                && Objects.equals(this.readTimeout, that.readTimeout)
+                && Objects.equals(this.writeTimeout, that.writeTimeout)
+                && Objects.equals(this.connectionTimeout, 
that.connectionTimeout)
                 && Objects.equals(this.specificAuthConfiguration, 
that.specificAuthConfiguration);
         }
         return false;
@@ -151,7 +197,8 @@ public class S3BlobStoreConfiguration {
 
     @Override
     public final int hashCode() {
-        return Objects.hash(namespace, bucketPrefix, httpConcurrency, 
specificAuthConfiguration);
+        return Objects.hash(namespace, bucketPrefix, httpConcurrency, 
specificAuthConfiguration,
+            readTimeout, writeTimeout, connectionTimeout);
     }
 
     @Override
@@ -162,6 +209,9 @@ public class S3BlobStoreConfiguration {
             .add("bucketPrefix", bucketPrefix)
             .add("region", region)
             .add("specificAuthConfiguration", specificAuthConfiguration)
+            .add("readTimeout", readTimeout)
+            .add("writeTimeout", writeTimeout)
+            .add("connectionTimeout", connectionTimeout)
             .toString();
     }
 }
diff --git 
a/server/container/guice/blob/s3/src/main/java/org/apache/james/modules/objectstorage/S3BlobStoreConfigurationReader.java
 
b/server/container/guice/blob/s3/src/main/java/org/apache/james/modules/objectstorage/S3BlobStoreConfigurationReader.java
index 44b74f6..9a3bded 100644
--- 
a/server/container/guice/blob/s3/src/main/java/org/apache/james/modules/objectstorage/S3BlobStoreConfigurationReader.java
+++ 
b/server/container/guice/blob/s3/src/main/java/org/apache/james/modules/objectstorage/S3BlobStoreConfigurationReader.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.modules.objectstorage;
 
+import java.time.Duration;
+import java.time.temporal.ChronoUnit;
 import java.util.Optional;
 
 import org.apache.commons.configuration2.Configuration;
@@ -27,6 +29,7 @@ import org.apache.james.blob.api.BucketName;
 import org.apache.james.blob.objectstorage.aws.Region;
 import org.apache.james.blob.objectstorage.aws.S3BlobStoreConfiguration;
 import org.apache.james.modules.objectstorage.aws.s3.AwsS3ConfigurationReader;
+import org.apache.james.util.DurationParser;
 
 public class S3BlobStoreConfigurationReader {
 
@@ -34,6 +37,9 @@ public class S3BlobStoreConfigurationReader {
     private static final String OBJECTSTORAGE_BUCKET_PREFIX = 
"objectstorage.bucketPrefix";
     private static final String OBJECTSTORAGE_S3_REGION = 
"objectstorage.s3.region";
     private static final String OBJECTSTORAGE_S3_HTTP_CONCURRENCY = 
"objectstorage.s3.http.concurrency";
+    private static final String OBJECTSTORAGE_S3_READ_TIMEOUT = 
"objectstorage.s3.read.timeout";
+    private static final String OBJECTSTORAGE_S3_WRITE_TIMEOUT = 
"objectstorage.s3.write.timeout";
+    private static final String OBJECTSTORAGE_S3_CONNECTION_TIMEOUT = 
"objectstorage.s3.connection.timeout";
 
     public static S3BlobStoreConfiguration from(Configuration configuration) 
throws ConfigurationException {
         Optional<Integer> httpConcurrency = 
Optional.ofNullable(configuration.getInteger(OBJECTSTORAGE_S3_HTTP_CONCURRENCY, 
null));
@@ -42,6 +48,12 @@ public class S3BlobStoreConfigurationReader {
         Region region = 
Optional.ofNullable(configuration.getString(OBJECTSTORAGE_S3_REGION, null))
             .map(Region::of)
             .orElseThrow(() -> new ConfigurationException("require a region (" 
+ OBJECTSTORAGE_S3_REGION + " key)"));
+        Optional<Duration> readTimeout = 
Optional.ofNullable(configuration.getString(OBJECTSTORAGE_S3_READ_TIMEOUT, 
null))
+            .map(s -> DurationParser.parse(s, ChronoUnit.SECONDS));
+        Optional<Duration> writeTimeout = 
Optional.ofNullable(configuration.getString(OBJECTSTORAGE_S3_WRITE_TIMEOUT, 
null))
+            .map(s -> DurationParser.parse(s, ChronoUnit.SECONDS));
+        Optional<Duration> connectionTimeout = 
Optional.ofNullable(configuration.getString(OBJECTSTORAGE_S3_CONNECTION_TIMEOUT,
 null))
+            .map(s -> DurationParser.parse(s, ChronoUnit.SECONDS));
 
         return S3BlobStoreConfiguration.builder()
             .authConfiguration(AwsS3ConfigurationReader.from(configuration))
@@ -49,6 +61,9 @@ public class S3BlobStoreConfigurationReader {
             .defaultBucketName(namespace.map(BucketName::of))
             .bucketPrefix(bucketPrefix)
             .httpConcurrency(httpConcurrency)
+            .readTimeout(readTimeout)
+            .writeTimeout(writeTimeout)
+            .connectionTimeout(connectionTimeout)
             .build();
     }
 
diff --git a/src/site/xdoc/server/config-blobstore.xml 
b/src/site/xdoc/server/config-blobstore.xml
index c4f12c1..4f25e2e 100644
--- a/src/site/xdoc/server/config-blobstore.xml
+++ b/src/site/xdoc/server/config-blobstore.xml
@@ -179,6 +179,15 @@ generate salt with : openssl rand -hex 16
 
                         
<dt><strong>objectstorage.s3.truststore.algorithm</strong></dt>
                         <dd><i>optional:</i> Use this specific trust store 
algorithm; default SunX509</dd>
+
+                        <dt><strong>objectstorage.s3.read.timeout</strong></dt>
+                        <dd><i>optional:</i> HTTP read timeout. duration, 
default value being second. Leaving it empty relies on S3 driver defaults.</dd>
+
+                        
<dt><strong>objectstorage.s3.write.timeout</strong></dt>
+                        <dd><i>optional:</i> HTTP write timeout. duration, 
default value being second. Leaving it empty relies on S3 driver defaults.</dd>
+
+                        
<dt><strong>objectstorage.s3.connection.timeout</strong></dt>
+                        <dd><i>optional:</i> HTTP connection timeout. 
duration, default value being second. Leaving it empty relies on S3 driver 
defaults.</dd>
                     </dl>
                 </subsection>
             </subsection>

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to