Skip to content

Commit 4b0b75c

Browse files
committed
Fix for #548: add timeout options for all OkHttp client settings to options
1 parent ac12c4c commit 4b0b75c

3 files changed

Lines changed: 135 additions & 0 deletions

File tree

src/main/java/com/google/genai/ApiClient.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ private OkHttpClient createHttpClient(
223223
builder.connectTimeout(Duration.ofMillis(0));
224224
builder.readTimeout(Duration.ofMillis(0));
225225
builder.writeTimeout(Duration.ofMillis(0));
226+
builder.callTimeout(Duration.ofMillis(0));
226227

227228
timeout.ifPresent(connectTimeout -> builder.connectTimeout(Duration.ofMillis(connectTimeout)));
228229

@@ -232,6 +233,11 @@ private OkHttpClient createHttpClient(
232233
options.maxConnections().ifPresent(dispatcher::setMaxRequests);
233234
options.maxConnectionsPerHost().ifPresent(dispatcher::setMaxRequestsPerHost);
234235
builder.dispatcher(dispatcher);
236+
237+
// Apply timeout configurations from ClientOptions
238+
options.readTimeout().ifPresent(rt -> builder.readTimeout(Duration.ofMillis(rt)));
239+
options.writeTimeout().ifPresent(wt -> builder.writeTimeout(Duration.ofMillis(wt)));
240+
options.callTimeout().ifPresent(ct -> builder.callTimeout(Duration.ofMillis(ct)));
235241
});
236242

237243
return builder.build();

src/main/java/com/google/genai/types/ClientOptions.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ public abstract class ClientOptions extends JsonSerializable {
3737
@JsonProperty("maxConnectionsPerHost")
3838
public abstract Optional<Integer> maxConnectionsPerHost();
3939

40+
/** Read timeout in milliseconds. */
41+
@JsonProperty("readTimeout")
42+
public abstract Optional<Integer> readTimeout();
43+
44+
/** Write timeout in milliseconds. */
45+
@JsonProperty("writeTimeout")
46+
public abstract Optional<Integer> writeTimeout();
47+
48+
/** Call timeout in milliseconds. */
49+
@JsonProperty("callTimeout")
50+
public abstract Optional<Integer> callTimeout();
51+
4052
/** Instantiates a builder for ClientOptions. */
4153
@ExcludeFromGeneratedCoverageReport
4254
public static Builder builder() {
@@ -71,6 +83,30 @@ private static Builder create() {
7183
@JsonProperty("maxConnectionsPerHost")
7284
public abstract Builder maxConnectionsPerHost(Integer maxConnectionsPerHost);
7385

86+
/**
87+
* Setter for readTimeout.
88+
*
89+
* <p>readTimeout: Read timeout in milliseconds.
90+
*/
91+
@JsonProperty("readTimeout")
92+
public abstract Builder readTimeout(Integer readTimeout);
93+
94+
/**
95+
* Setter for writeTimeout.
96+
*
97+
* <p>writeTimeout: Write timeout in milliseconds.
98+
*/
99+
@JsonProperty("writeTimeout")
100+
public abstract Builder writeTimeout(Integer writeTimeout);
101+
102+
/**
103+
* Setter for callTimeout.
104+
*
105+
* <p>callTimeout: Call timeout in milliseconds.
106+
*/
107+
@JsonProperty("callTimeout")
108+
public abstract Builder callTimeout(Integer callTimeout);
109+
74110
public abstract ClientOptions build();
75111
}
76112

src/test/java/com/google/genai/HttpApiClientTest.java

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,99 @@ public void testHttpClientMldevDefaultClientOptions() throws Exception {
10131013
assertFalse(client.vertexAI());
10141014
}
10151015

1016+
@Test
1017+
public void testHttpClientMldevWithTimeoutSettings() throws Exception {
1018+
ClientOptions clientOptions =
1019+
ClientOptions.builder()
1020+
.readTimeout(5000)
1021+
.writeTimeout(10000)
1022+
.callTimeout(15000)
1023+
.build();
1024+
HttpApiClient client =
1025+
new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.of(clientOptions));
1026+
1027+
OkHttpClient httpClient = client.httpClient();
1028+
1029+
assertEquals(API_KEY, client.apiKey());
1030+
assertFalse(client.vertexAI());
1031+
assertEquals(5000, httpClient.readTimeoutMillis());
1032+
assertEquals(10000, httpClient.writeTimeoutMillis());
1033+
assertEquals(15000, httpClient.callTimeoutMillis());
1034+
}
1035+
1036+
@Test
1037+
public void testHttpClientVertexWithTimeoutSettings() throws Exception {
1038+
ClientOptions clientOptions =
1039+
ClientOptions.builder()
1040+
.readTimeout(3000)
1041+
.writeTimeout(6000)
1042+
.callTimeout(9000)
1043+
.build();
1044+
HttpApiClient client =
1045+
new HttpApiClient(
1046+
Optional.empty(),
1047+
Optional.of(PROJECT),
1048+
Optional.of(LOCATION),
1049+
Optional.of(CREDENTIALS),
1050+
Optional.empty(),
1051+
Optional.of(clientOptions));
1052+
1053+
OkHttpClient httpClient = client.httpClient();
1054+
1055+
assertEquals(PROJECT, client.project());
1056+
assertEquals(LOCATION, client.location());
1057+
assertTrue(client.vertexAI());
1058+
assertEquals(3000, httpClient.readTimeoutMillis());
1059+
assertEquals(6000, httpClient.writeTimeoutMillis());
1060+
assertEquals(9000, httpClient.callTimeoutMillis());
1061+
}
1062+
1063+
@Test
1064+
public void testHttpClientWithPartialTimeoutSettings() throws Exception {
1065+
ClientOptions clientOptions =
1066+
ClientOptions.builder()
1067+
.readTimeout(5000)
1068+
.build();
1069+
HttpApiClient client =
1070+
new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.of(clientOptions));
1071+
1072+
OkHttpClient httpClient = client.httpClient();
1073+
1074+
assertEquals(API_KEY, client.apiKey());
1075+
assertFalse(client.vertexAI());
1076+
assertEquals(5000, httpClient.readTimeoutMillis());
1077+
// When not set, timeouts should remain at default 0 (no timeout)
1078+
assertEquals(0, httpClient.writeTimeoutMillis());
1079+
assertEquals(0, httpClient.callTimeoutMillis());
1080+
}
1081+
1082+
@Test
1083+
public void testHttpClientWithAllClientOptionsIncludingTimeouts() throws Exception {
1084+
ClientOptions clientOptions =
1085+
ClientOptions.builder()
1086+
.maxConnections(32)
1087+
.maxConnectionsPerHost(8)
1088+
.readTimeout(2000)
1089+
.writeTimeout(4000)
1090+
.callTimeout(8000)
1091+
.build();
1092+
HttpApiClient client =
1093+
new HttpApiClient(Optional.of(API_KEY), Optional.empty(), Optional.of(clientOptions));
1094+
1095+
OkHttpClient httpClient = client.httpClient();
1096+
Dispatcher dispatcher = httpClient.dispatcher();
1097+
1098+
assertEquals(API_KEY, client.apiKey());
1099+
assertFalse(client.vertexAI());
1100+
// Test dispatcher settings
1101+
assertEquals(32, dispatcher.getMaxRequests());
1102+
assertEquals(8, dispatcher.getMaxRequestsPerHost());
1103+
// Test timeout settings
1104+
assertEquals(2000, httpClient.readTimeoutMillis());
1105+
assertEquals(4000, httpClient.writeTimeoutMillis());
1106+
assertEquals(8000, httpClient.callTimeoutMillis());
1107+
}
1108+
10161109
@Test
10171110
public void testHttpClientWithCustomCredentials() throws Exception {
10181111
HttpApiClient client =

0 commit comments

Comments
 (0)