diff --git a/google-http-client/src/main/java/com/google/api/client/http/HttpRequest.java b/google-http-client/src/main/java/com/google/api/client/http/HttpRequest.java index 312702b9a..2e70e0260 100644 --- a/google-http-client/src/main/java/com/google/api/client/http/HttpRequest.java +++ b/google-http-client/src/main/java/com/google/api/client/http/HttpRequest.java @@ -32,6 +32,7 @@ import java.util.Properties; import java.util.concurrent.Callable; import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; @@ -153,6 +154,12 @@ public final class HttpRequest { /** Timeout in milliseconds to set POST/PUT data or {@code 0} for an infinite timeout. */ private int writeTimeout = 0; + /** + * Custom executor used to handle write timeouts, enabled by {@link #writeTimeout}. + * By default, a new thread is created per each request. + */ + private ExecutorService writeTimeoutExecutor; + /** HTTP unsuccessful (non-2XX) response handler or {@code null} for none. */ private HttpUnsuccessfulResponseHandler unsuccessfulResponseHandler; @@ -490,6 +497,17 @@ public HttpRequest setWriteTimeout(int writeTimeout) { } /** + * Sets custom executor used to handle write timeouts, enabled by {@link #setWriteTimeout(int)}. + * By default, a new thread is created per each request. + * + * @since 1.40.2 + */ + public HttpRequest setWriteTimeoutExecutor(ExecutorService writeTimeoutExecutor) { + this.writeTimeoutExecutor = writeTimeoutExecutor; + return this; + } + + /** * Returns the HTTP request headers. * * @since 1.5 @@ -1003,6 +1021,7 @@ public HttpResponse execute() throws IOException { // execute lowLevelHttpRequest.setTimeout(connectTimeout, readTimeout); lowLevelHttpRequest.setWriteTimeout(writeTimeout); + lowLevelHttpRequest.setWriteTimeoutExecutor(writeTimeoutExecutor); // switch tracing scope to current span @SuppressWarnings("MustBeClosedChecker") diff --git a/google-http-client/src/main/java/com/google/api/client/http/LowLevelHttpRequest.java b/google-http-client/src/main/java/com/google/api/client/http/LowLevelHttpRequest.java index b13e2a040..68f262396 100644 --- a/google-http-client/src/main/java/com/google/api/client/http/LowLevelHttpRequest.java +++ b/google-http-client/src/main/java/com/google/api/client/http/LowLevelHttpRequest.java @@ -16,6 +16,7 @@ import com.google.api.client.util.StreamingContent; import java.io.IOException; +import java.util.concurrent.ExecutorService; /** * Low-level HTTP request. @@ -158,6 +159,16 @@ public void setTimeout(int connectTimeout, int readTimeout) throws IOException { */ public void setWriteTimeout(int writeTimeout) throws IOException {} + /** + * Sets custom timeout executor for POST/PUT requests. + * + *
Default implementation uses a new thread per each {@link #execute()} call.
+ *
+ * @param writeTimeoutExecutor custom timeout executor to use
+ * @since 1.40.2
+ */
+ public void setWriteTimeoutExecutor(ExecutorService writeTimeoutExecutor) {}
+
/** Executes the request and returns a low-level HTTP response object. */
public abstract LowLevelHttpResponse execute() throws IOException;
}
diff --git a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpRequest.java b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpRequest.java
index fa201b06f..162dc9c9c 100644
--- a/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpRequest.java
+++ b/google-http-client/src/main/java/com/google/api/client/http/javanet/NetHttpRequest.java
@@ -36,6 +36,7 @@ final class NetHttpRequest extends LowLevelHttpRequest {
private final HttpURLConnection connection;
private int writeTimeout;
+ private ExecutorService writeTimeoutExecutor;
/** @param connection HTTP URL connection */
NetHttpRequest(HttpURLConnection connection) {
@@ -65,6 +66,11 @@ public void setWriteTimeout(int writeTimeout) throws IOException {
this.writeTimeout = writeTimeout;
}
+ @Override
+ public void setWriteTimeoutExecutor(ExecutorService writeTimeoutExecutor) {
+ this.writeTimeoutExecutor = writeTimeoutExecutor;
+ }
+
interface OutputWriter {
void write(OutputStream outputStream, StreamingContent content) throws IOException;
}
@@ -184,9 +190,13 @@ public Boolean call() throws IOException {
}
};
- final ExecutorService executor = Executors.newSingleThreadExecutor();
+ final boolean externalWriteTimeoutExecutor = writeTimeoutExecutor != null;
+ final ExecutorService executor = externalWriteTimeoutExecutor ? writeTimeoutExecutor : Executors.newSingleThreadExecutor();
final Future