This is an automated email from the ASF dual-hosted git repository.
davidradl pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/flink-connector-http.git
The following commit(s) were added to refs/heads/main by this push:
new 8b98b78 [FLINK-40072][connector-http] Read request.timeout as the
declared Duration option (#52)
8b98b78 is described below
commit 8b98b78137655c970e4e16d597b48c8168552001
Author: Bharath Reddy Gunapati
<[email protected]>
AuthorDate: Mon Jul 20 18:13:08 2026 +0530
[FLINK-40072][connector-http] Read request.timeout as the declared Duration
option (#52)
* [FLINK-40072][connector-http] Read request.timeout as the declared
Duration option
request.timeout is declared as a ConfigOption<Duration> for both the lookup
source (SOURCE_LOOKUP_REQUEST_TIMEOUT) and the sink (SINK_REQUEST_TIMEOUT)
with a
default of 30s, and the docs describe it as a Flink Duration. However, the
runtime
never read the declared option: it parsed the raw config string with
Integer.parseInt(...), so any Duration-formatted value such as '30s' threw
NumberFormatException at query time. The failure is deferred because the
http.*
namespace is skipped by FactoryUtil#validateExcept(...), so CREATE TABLE
succeeds
and only the first request crashes.
This wires the runtime to the declared options:
- Lookup: RequestFactoryBase reads SOURCE_LOOKUP_REQUEST_TIMEOUT from
ReadableConfig as a Duration and applies it directly.
- Sink: AbstractRequestSubmitter parses the value with
TimeUtils.parseDuration(...);
PerRequestSubmitter and BatchRequestSubmitter use the Duration directly.
- Removes the now-unused integer-seconds field and
DEFAULT_REQUEST_TIMEOUT_SECONDS
constant; the default comes from the option (Duration.ofSeconds(30)).
- Updates docs to describe the value as a Flink Duration ('30s', '1min').
Behavioral note: values are now parsed with standard Flink Duration
semantics
(consistent with the sibling connection.timeout option). Unit-suffixed
values now
work; a bare number such as '30' now means 30ms rather than 30s, so bare
integers
must be rewritten with a unit (e.g. '30s'). The defect was introduced by
FLINK-39364 (#31).
Tests: end-to-end lookup join with '30s' (HttpLookupTableSourceITCaseTest),
Duration parsing (BodyBasedRequestFactoryTest, BatchRequestSubmitterTest),
and
sink option acceptance (HttpDynamicTableSinkFactoryTest).
* [FLINK-40072][connector-http] Address review feedback on request.timeout
PR
Clarify sink Properties vs ReadableConfig asymmetry, tighten test assertions
and comments per maintainer review, and fix requestTimeoutOptionTest to
handle
successful INSERT without failing on a null throwable.
* [FLINK-40072][connector-http] Address review feedback on request.timeout
PR
---
docs/content.zh/docs/connectors/datastream/http.md | 2 +-
docs/content/docs/connectors/datastream/http.md | 2 +-
.../sink/httpclient/AbstractRequestSubmitter.java | 19 +++++---
.../sink/httpclient/BatchRequestSubmitter.java | 3 +-
.../http/sink/httpclient/PerRequestSubmitter.java | 3 +-
.../http/table/lookup/RequestFactoryBase.java | 31 ++++++-------
.../sink/httpclient/BatchRequestSubmitterTest.java | 32 +++++++++++++
.../table/lookup/BodyBasedRequestFactoryTest.java | 54 ++++++++++++++++++++++
.../lookup/HttpLookupTableSourceITCaseTest.java | 44 +++++++++++++++++-
.../sink/HttpDynamicTableSinkFactoryTest.java | 15 ++++--
10 files changed, 169 insertions(+), 36 deletions(-)
diff --git a/docs/content.zh/docs/connectors/datastream/http.md
b/docs/content.zh/docs/connectors/datastream/http.md
index e1e6cfa..c3a959d 100644
--- a/docs/content.zh/docs/connectors/datastream/http.md
+++ b/docs/content.zh/docs/connectors/datastream/http.md
@@ -68,7 +68,7 @@ These options are specified on the builder using the
setProperty method.
| flink.connector.http.security.cert.client | optional | Path
to trusted certificate that should be used by connector's HTTP client for mTLS
communication.
|
| flink.connector.http.security.key.client | optional | Path
to trusted private key that should be used by connector's HTTP client for mTLS
communication.
|
| flink.connector.http.security.cert.server.allowSelfSigned | optional |
Accept untrusted certificates for TLS communication.
|
-| flink.connector.http.sink.request.timeout | optional | Sets
HTTP request timeout in seconds. If not specified, the default value of 30
seconds will be used.
|
+| flink.connector.http.sink.request.timeout | optional | Sets
HTTP request timeout for the HTTP sink as a Duration (e.g. `30s`, `1min`). If
not specified, the default value of `30s` will be used.
|
| flink.connector.http.sink.writer.thread-pool.size | optional | Sets
the size of pool thread for HTTP Sink request processing. Increasing this value
would mean that more concurrent requests can be processed in the same time. If
not specified, the default value of 1 thread will be used. |
| flink.connector.http.sink.writer.request.mode | optional | Sets
the Http Sink request submission mode. Two modes are available: `single` and
`batch`. Defaults to `batch` if not specified. |
| flink.connector.http.sink.request.batch.size | optional |
Applicable only for `flink.connector.http.sink.writer.request.mode = batch`.
Sets number of individual events/requests that will be submitted as one HTTP
request by HTTP sink. The default value is 500 which is same as HTTP Sink
`maxBatchSize` |
diff --git a/docs/content/docs/connectors/datastream/http.md
b/docs/content/docs/connectors/datastream/http.md
index e1e6cfa..c3a959d 100644
--- a/docs/content/docs/connectors/datastream/http.md
+++ b/docs/content/docs/connectors/datastream/http.md
@@ -68,7 +68,7 @@ These options are specified on the builder using the
setProperty method.
| flink.connector.http.security.cert.client | optional | Path
to trusted certificate that should be used by connector's HTTP client for mTLS
communication.
|
| flink.connector.http.security.key.client | optional | Path
to trusted private key that should be used by connector's HTTP client for mTLS
communication.
|
| flink.connector.http.security.cert.server.allowSelfSigned | optional |
Accept untrusted certificates for TLS communication.
|
-| flink.connector.http.sink.request.timeout | optional | Sets
HTTP request timeout in seconds. If not specified, the default value of 30
seconds will be used.
|
+| flink.connector.http.sink.request.timeout | optional | Sets
HTTP request timeout for the HTTP sink as a Duration (e.g. `30s`, `1min`). If
not specified, the default value of `30s` will be used.
|
| flink.connector.http.sink.writer.thread-pool.size | optional | Sets
the size of pool thread for HTTP Sink request processing. Increasing this value
would mean that more concurrent requests can be processed in the same time. If
not specified, the default value of 1 thread will be used. |
| flink.connector.http.sink.writer.request.mode | optional | Sets
the Http Sink request submission mode. Two modes are available: `single` and
`batch`. Defaults to `batch` if not specified. |
| flink.connector.http.sink.request.batch.size | optional |
Applicable only for `flink.connector.http.sink.writer.request.mode = batch`.
Sets number of individual events/requests that will be submitted as one HTTP
request by HTTP sink. The default value is 500 which is same as HTTP Sink
`maxBatchSize` |
diff --git
a/flink-connector-http/src/main/java/org/apache/flink/connector/http/sink/httpclient/AbstractRequestSubmitter.java
b/flink-connector-http/src/main/java/org/apache/flink/connector/http/sink/httpclient/AbstractRequestSubmitter.java
index 10f9906..7f167e6 100644
---
a/flink-connector-http/src/main/java/org/apache/flink/connector/http/sink/httpclient/AbstractRequestSubmitter.java
+++
b/flink-connector-http/src/main/java/org/apache/flink/connector/http/sink/httpclient/AbstractRequestSubmitter.java
@@ -19,9 +19,11 @@ package org.apache.flink.connector.http.sink.httpclient;
import org.apache.flink.connector.http.config.HttpConnectorConfigConstants;
import org.apache.flink.connector.http.utils.ThreadUtils;
+import org.apache.flink.util.TimeUtils;
import org.apache.flink.util.concurrent.ExecutorThreadFactory;
import java.net.http.HttpClient;
+import java.time.Duration;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -31,12 +33,12 @@ public abstract class AbstractRequestSubmitter implements
RequestSubmitter {
protected static final int HTTP_CLIENT_PUBLISHING_THREAD_POOL_SIZE = 1;
- protected static final String DEFAULT_REQUEST_TIMEOUT_SECONDS = "30";
+ protected static final Duration DEFAULT_REQUEST_TIMEOUT =
Duration.ofSeconds(30);
/** Thread pool to handle HTTP response from HTTP client. */
protected final ExecutorService publishingThreadPool;
- protected final int httpRequestTimeOutSeconds;
+ protected final Duration httpRequestTimeout;
protected final String[] headersAndValues;
@@ -53,11 +55,14 @@ public abstract class AbstractRequestSubmitter implements
RequestSubmitter {
"http-sink-client-response-worker",
ThreadUtils.LOGGING_EXCEPTION_HANDLER));
- this.httpRequestTimeOutSeconds =
- Integer.parseInt(
- properties.getProperty(
-
HttpConnectorConfigConstants.SINK_HTTP_TIMEOUT_SECONDS,
- DEFAULT_REQUEST_TIMEOUT_SECONDS));
+ // Sink submitters are wired with Properties today; reading
SINK_REQUEST_TIMEOUT from
+ // ReadableConfig will be handled in a follow-up sink
config-unification PR.
+ String requestTimeout =
+
properties.getProperty(HttpConnectorConfigConstants.SINK_HTTP_TIMEOUT_SECONDS);
+ this.httpRequestTimeout =
+ requestTimeout == null
+ ? DEFAULT_REQUEST_TIMEOUT
+ : TimeUtils.parseDuration(requestTimeout);
this.httpClient = httpClient;
}
diff --git
a/flink-connector-http/src/main/java/org/apache/flink/connector/http/sink/httpclient/BatchRequestSubmitter.java
b/flink-connector-http/src/main/java/org/apache/flink/connector/http/sink/httpclient/BatchRequestSubmitter.java
index 6733ba2..b573b0c 100644
---
a/flink-connector-http/src/main/java/org/apache/flink/connector/http/sink/httpclient/BatchRequestSubmitter.java
+++
b/flink-connector-http/src/main/java/org/apache/flink/connector/http/sink/httpclient/BatchRequestSubmitter.java
@@ -31,7 +31,6 @@ import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpRequest.Builder;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
-import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -138,7 +137,7 @@ public class BatchRequestSubmitter extends
AbstractRequestSubmitter {
java.net.http.HttpRequest.newBuilder()
.uri(endpointUri)
.version(Version.HTTP_1_1)
-
.timeout(Duration.ofSeconds(httpRequestTimeOutSeconds))
+ .timeout(httpRequestTimeout)
.method(method, publisher);
if (headersAndValues.length != 0) {
diff --git
a/flink-connector-http/src/main/java/org/apache/flink/connector/http/sink/httpclient/PerRequestSubmitter.java
b/flink-connector-http/src/main/java/org/apache/flink/connector/http/sink/httpclient/PerRequestSubmitter.java
index aee85c9..3ab5f6e 100644
---
a/flink-connector-http/src/main/java/org/apache/flink/connector/http/sink/httpclient/PerRequestSubmitter.java
+++
b/flink-connector-http/src/main/java/org/apache/flink/connector/http/sink/httpclient/PerRequestSubmitter.java
@@ -27,7 +27,6 @@ import java.net.http.HttpClient.Version;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpRequest.Builder;
import java.net.http.HttpResponse;
-import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
@@ -79,7 +78,7 @@ public class PerRequestSubmitter extends
AbstractRequestSubmitter {
java.net.http.HttpRequest.newBuilder()
.uri(endpointUri)
.version(Version.HTTP_1_1)
- .timeout(Duration.ofSeconds(httpRequestTimeOutSeconds))
+ .timeout(httpRequestTimeout)
.method(
requestEntry.method,
BodyPublishers.ofByteArray(requestEntry.element));
diff --git
a/flink-connector-http/src/main/java/org/apache/flink/connector/http/table/lookup/RequestFactoryBase.java
b/flink-connector-http/src/main/java/org/apache/flink/connector/http/table/lookup/RequestFactoryBase.java
index 7d115c6..a0807f1 100644
---
a/flink-connector-http/src/main/java/org/apache/flink/connector/http/table/lookup/RequestFactoryBase.java
+++
b/flink-connector-http/src/main/java/org/apache/flink/connector/http/table/lookup/RequestFactoryBase.java
@@ -44,14 +44,12 @@ import static
org.apache.flink.connector.http.config.HttpConnectorConfigConstant
@Slf4j
public abstract class RequestFactoryBase implements HttpRequestFactory {
- public static final String DEFAULT_REQUEST_TIMEOUT_SECONDS = "30";
-
/** Base url used for {@link HttpRequest} for example
"http://localhost:8080". */
protected final String baseUrl;
protected final LookupQueryCreator lookupQueryCreator;
- protected final int httpRequestTimeOutSeconds;
+ protected final Duration httpRequestTimeout;
/** HTTP headers that should be used for {@link HttpRequest} created by
factory. */
private final String[] headersAndValues;
@@ -80,18 +78,17 @@ public abstract class RequestFactoryBase implements
HttpRequestFactory {
this.headersAndValues =
HttpHeaderUtils.toHeaderAndValueArray(headerMap);
- this.httpRequestTimeOutSeconds =
- Integer.parseInt(
- options.getProperties()
- .getProperty(
-
HttpConnectorConfigConstants.LOOKUP_HTTP_TIMEOUT_SECONDS,
- DEFAULT_REQUEST_TIMEOUT_SECONDS));
-
- String httpVersionFromConfig = null;
- if (options.getReadableConfig() != null) {
- httpVersionFromConfig =
-
options.getReadableConfig().get(HttpLookupConnectorOptions.LOOKUP_HTTP_VERSION);
- }
+ var readableConfig = options.getReadableConfig();
+ this.httpRequestTimeout =
+ readableConfig != null
+ ? readableConfig.get(
+
HttpLookupConnectorOptions.SOURCE_LOOKUP_REQUEST_TIMEOUT)
+ :
HttpLookupConnectorOptions.SOURCE_LOOKUP_REQUEST_TIMEOUT.defaultValue();
+
+ String httpVersionFromConfig =
+ readableConfig != null
+ ?
readableConfig.get(HttpLookupConnectorOptions.LOOKUP_HTTP_VERSION)
+ : null;
if (httpVersionFromConfig == null) {
httpVersion = null;
} else {
@@ -122,9 +119,7 @@ public abstract class RequestFactoryBase implements
HttpRequestFactory {
* @return {@link Builder} for given lookupQuery.
*/
protected Builder setUpRequestMethod(LookupQueryInfo lookupQuery) {
- HttpRequest.Builder builder =
- HttpRequest.newBuilder()
-
.timeout(Duration.ofSeconds(this.httpRequestTimeOutSeconds));
+ HttpRequest.Builder builder =
HttpRequest.newBuilder().timeout(this.httpRequestTimeout);
return httpVersion == null ? builder : builder.version(httpVersion);
}
diff --git
a/flink-connector-http/src/test/java/org/apache/flink/connector/http/sink/httpclient/BatchRequestSubmitterTest.java
b/flink-connector-http/src/test/java/org/apache/flink/connector/http/sink/httpclient/BatchRequestSubmitterTest.java
index 12705ac..76fad07 100644
---
a/flink-connector-http/src/test/java/org/apache/flink/connector/http/sink/httpclient/BatchRequestSubmitterTest.java
+++
b/flink-connector-http/src/test/java/org/apache/flink/connector/http/sink/httpclient/BatchRequestSubmitterTest.java
@@ -21,6 +21,7 @@ package org.apache.flink.connector.http.sink.httpclient;
import org.apache.flink.connector.http.config.HttpConnectorConfigConstants;
import org.apache.flink.connector.http.sink.HttpSinkRequestEntry;
+import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
@@ -30,6 +31,7 @@ import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.net.http.HttpClient;
+import java.time.Duration;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CompletableFuture;
@@ -37,6 +39,7 @@ import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -71,6 +74,35 @@ class BatchRequestSubmitterTest {
verify(mockHttpClient,
times(expectedNumberOfBatchRequests)).sendAsync(any(), any());
}
+ /**
+ * The sink shares the same latent defect as FLINK-39364 (#31): {@code
+ * http.sink.request.timeout} was declared as a {@code durationType()}
option but read with
+ * {@code Integer.parseInt(...)}, so a unit-suffixed value like {@code
"45s"} threw {@link
+ * NumberFormatException}. It must now be parsed as a real {@link
Duration}.
+ */
+ @Test
+ public void requestTimeoutWithUnitIsParsedAsDuration() {
+ Properties properties = new Properties();
+
properties.setProperty(HttpConnectorConfigConstants.SINK_HTTP_BATCH_REQUEST_SIZE,
"50");
+
properties.setProperty(HttpConnectorConfigConstants.SINK_HTTP_TIMEOUT_SECONDS,
"45s");
+
+ BatchRequestSubmitter submitter =
+ new BatchRequestSubmitter(properties, new String[0],
mockHttpClient);
+
+
assertThat(submitter.httpRequestTimeout).isEqualTo(Duration.ofSeconds(45));
+ }
+
+ @Test
+ public void requestTimeoutDefaultsToThirtySeconds() {
+ Properties properties = new Properties();
+
properties.setProperty(HttpConnectorConfigConstants.SINK_HTTP_BATCH_REQUEST_SIZE,
"50");
+
+ BatchRequestSubmitter submitter =
+ new BatchRequestSubmitter(properties, new String[0],
mockHttpClient);
+
+
assertThat(submitter.httpRequestTimeout).isEqualTo(Duration.ofSeconds(30));
+ }
+
private static Stream<Arguments> httpRequestMethods() {
return Stream.of(
Arguments.of(List.of("PUT", "PUT", "PUT", "PUT", "POST"), 2),
diff --git
a/flink-connector-http/src/test/java/org/apache/flink/connector/http/table/lookup/BodyBasedRequestFactoryTest.java
b/flink-connector-http/src/test/java/org/apache/flink/connector/http/table/lookup/BodyBasedRequestFactoryTest.java
index 5e0d973..aba0cfd 100644
---
a/flink-connector-http/src/test/java/org/apache/flink/connector/http/table/lookup/BodyBasedRequestFactoryTest.java
+++
b/flink-connector-http/src/test/java/org/apache/flink/connector/http/table/lookup/BodyBasedRequestFactoryTest.java
@@ -20,11 +20,13 @@ package org.apache.flink.connector.http.table.lookup;
import org.apache.flink.configuration.Configuration;
+import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import java.net.URI;
import java.net.http.HttpClient;
+import java.time.Duration;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
@@ -34,6 +36,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import static
org.apache.flink.connector.http.table.lookup.HttpLookupConnectorOptions.LOOKUP_HTTP_VERSION;
+import static
org.apache.flink.connector.http.table.lookup.HttpLookupConnectorOptions.SOURCE_LOOKUP_REQUEST_TIMEOUT;
import static org.assertj.core.api.Assertions.assertThat;
/** Test for {@link BodyBasedRequestFactory}. */
@@ -76,6 +79,57 @@ public class BodyBasedRequestFactoryTest {
}
}
+ /**
+ * FLINK-39364 (#31) declared {@code http.source.lookup.request.timeout}
as a {@code
+ * durationType()} option, but the runtime kept reading it with {@code
Integer.parseInt(...)}. A
+ * unit-suffixed value such as {@code "30s"} therefore threw {@link
NumberFormatException} when
+ * the request was built. This asserts the value is now parsed as a real
{@link Duration}.
+ */
+ @Test
+ void requestTimeoutWithSecondUnitIsParsedAsDuration() {
+ assertThat(factoryWithRequestTimeout("30s").httpRequestTimeout)
+ .isEqualTo(Duration.ofSeconds(30));
+ }
+
+ @Test
+ void requestTimeoutSupportsMinuteUnit() {
+ assertThat(factoryWithRequestTimeout("1 min").httpRequestTimeout)
+ .isEqualTo(Duration.ofMinutes(1));
+ }
+
+ @Test
+ void requestTimeoutDefaultsToThirtySeconds() {
+ // Empty Configuration: key unset, so readableConfig.get(...) returns
the option default.
+ RequestFactoryBase factory =
+ new BodyBasedRequestFactory("GET", null, null,
lookupConfig(new Configuration()));
+
assertThat(factory.httpRequestTimeout).isEqualTo(Duration.ofSeconds(30));
+ }
+
+ /**
+ * Documents the intended behavioural change versus the old int-seconds
read: a bare number now
+ * follows the standard Flink {@link Duration} convention and is
interpreted as milliseconds.
+ */
+ @Test
+ void bareNumberIsInterpretedAsMillisecondsPerFlinkDurationConvention() {
+ assertThat(factoryWithRequestTimeout("30").httpRequestTimeout)
+ .isEqualTo(Duration.ofMillis(30));
+ }
+
+ private static RequestFactoryBase factoryWithRequestTimeout(String value) {
+ Configuration configuration =
+
Configuration.fromMap(Map.of(SOURCE_LOOKUP_REQUEST_TIMEOUT.key(), value));
+ return new BodyBasedRequestFactory("GET", null, null,
lookupConfig(configuration));
+ }
+
+ private static HttpLookupConfig lookupConfig(Configuration configuration) {
+ return HttpLookupConfig.builder()
+ .lookupMethod("GET")
+ .url("http://service")
+ .useAsync(false)
+ .readableConfig(configuration)
+ .build();
+ }
+
private static class TestSpec {
Map<String, String> bodyBasedUrlQueryParams;
diff --git
a/flink-connector-http/src/test/java/org/apache/flink/connector/http/table/lookup/HttpLookupTableSourceITCaseTest.java
b/flink-connector-http/src/test/java/org/apache/flink/connector/http/table/lookup/HttpLookupTableSourceITCaseTest.java
index 5497f1d..a2036e4 100644
---
a/flink-connector-http/src/test/java/org/apache/flink/connector/http/table/lookup/HttpLookupTableSourceITCaseTest.java
+++
b/flink-connector-http/src/test/java/org/apache/flink/connector/http/table/lookup/HttpLookupTableSourceITCaseTest.java
@@ -977,7 +977,9 @@ class HttpLookupTableSourceITCaseTest {
+ "'http.source.lookup.query-creator' =
'http-generic-json-url',"
+ "'http.request.body-template' =
'{\"customerId\":\"1\"}',"
+ "'lookup.cache' = 'NONE',"
- + "'http.source.lookup.request.timeout' = '30',"
+ // Dormant fixture: use Duration syntax ('30s');
active coverage is
+ // testHttpLookupJoinWithDurationRequestTimeout.
+ + "'http.source.lookup.request.timeout' = '30s',"
+ "'http.source.lookup.request.thread-pool.size' =
'8',"
+ "'http.source.lookup.response.thread-pool.size' =
'4'"
+ ")";
@@ -1075,6 +1077,46 @@ class HttpLookupTableSourceITCaseTest {
}
}
+ /**
+ * Regression test for FLINK-40072 (defect introduced by FLINK-39364 /
#31): a lookup table
+ * declared with a Duration-typed request timeout such as {@code '30s'}
must work end to end.
+ * Before the runtime was wired to the {@code
SOURCE_LOOKUP_REQUEST_TIMEOUT} ConfigOption, this
+ * DDL passed validation (the {@code http.} namespace is skipped by {@code
validateExcept}) but
+ * the lookup crashed at query time with {@code NumberFormatException}
from {@code
+ * Integer.parseInt("30s")}.
+ */
+ @Test
+ void testHttpLookupJoinWithDurationRequestTimeout() throws Exception {
+ setupServerStub(wireMockServer);
+
+ String lookupTable =
+ "CREATE TABLE Customers ("
+ + "id STRING,"
+ + "id2 STRING,"
+ + "msg STRING,"
+ + "uuid STRING,"
+ + "details ROW<"
+ + "isActive BOOLEAN,"
+ + "nestedDetails ROW<"
+ + "balance STRING"
+ + ">"
+ + ">"
+ + ") WITH ("
+ + "'format' = 'json',"
+ + "'connector' = 'http',"
+ + "'lookup-method' = 'GET',"
+ + "'url' = 'http://localhost:"
+ + serverPort
+ + "/client',"
+ + "'http.source.lookup.header.Content-Type' =
'application/json',"
+ + "'http.source.lookup.request.timeout' = '30s'"
+ + ")";
+
+ SortedSet<Row> rows = testLookupJoin(lookupTable, 4);
+
+ assertEnrichedRows(rows);
+ }
+
private LookupCache getCache() {
Map<String, LookupCacheManager.RefCountedCache> managedCaches =
LookupCacheManager.getInstance().getManagedCaches();
diff --git
a/flink-connector-http/src/test/java/org/apache/flink/connector/http/table/sink/HttpDynamicTableSinkFactoryTest.java
b/flink-connector-http/src/test/java/org/apache/flink/connector/http/table/sink/HttpDynamicTableSinkFactoryTest.java
index b6569e4..ae2caab 100644
---
a/flink-connector-http/src/test/java/org/apache/flink/connector/http/table/sink/HttpDynamicTableSinkFactoryTest.java
+++
b/flink-connector-http/src/test/java/org/apache/flink/connector/http/table/sink/HttpDynamicTableSinkFactoryTest.java
@@ -25,7 +25,9 @@ import
org.apache.flink.table.api.bridge.java.StreamTableEnvironment;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.Assertions.catchThrowable;
/**
* Unfortunately it seems that Flink is lazy with connector instantiation, so
one has to call INSERT
@@ -125,9 +127,14 @@ public class HttpDynamicTableSinkFactoryTest {
"http://localhost/",
HttpDynamicSinkConnectorOptions.SINK_REQUEST_TIMEOUT.key());
tEnv.executeSql(withRequestTimeout);
- // Should not throw ValidationException for the option itself
- // (a RuntimeException for actual HTTP calls is fine in test)
- assertThatThrownBy(() -> tEnv.executeSql("INSERT INTO httpTimeout
VALUES (1)").await())
-
.isNotInstanceOf(org.apache.flink.table.api.ValidationException.class);
+ // The duration-typed option must be recognized at DDL time; INSERT
may fail at runtime
+ // (e.g. no HTTP server) but must not raise ValidationException.
+ Throwable insertFailure =
+ catchThrowable(() -> tEnv.executeSql("INSERT INTO httpTimeout
VALUES (1)").await());
+ if (insertFailure != null) {
+ assertThat(insertFailure)
+ .as("request.timeout must be a recognized option")
+ .isNotInstanceOf(ValidationException.class);
+ }
}
}