diff options
author | Jon Marius Venstad <jonmv@users.noreply.github.com> | 2021-05-11 14:19:01 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-11 14:19:01 +0200 |
commit | 016ed26d34ea0582e0e11ffc9ada76ff79a5d889 (patch) | |
tree | 33e4f4a39717e8deebc170a42656c2b18b662f4b | |
parent | 4ae244bc86782b3dc36257edcfabc2e38f510cf7 (diff) | |
parent | 7ac7e6e3c39fd80b24c38561949466e4fc00921a (diff) |
Merge pull request #17818 from vespa-engine/bjorncs/vespa-feed-client
Bjorncs/vespa feed client
5 files changed, 151 insertions, 1 deletions
diff --git a/vespa-feed-client/pom.xml b/vespa-feed-client/pom.xml index 32b44012107..d0b0066f07e 100644 --- a/vespa-feed-client/pom.xml +++ b/vespa-feed-client/pom.xml @@ -70,6 +70,27 @@ </compilerArgs> </configuration> </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <executions> + <execution> + <id>generate-simplified-vtag</id> + <phase>generate-sources</phase> + <goals> + <goal>exec</goal> + </goals> + <configuration> + <executable>src/main/sh/vespa-version-generator.sh</executable> + <arguments> + <argument>${project.basedir}/../dist/vtag.map</argument> + <argument>${project.build.directory}/generated-sources/vespa-version/com/yahoo/vespa/feed/client/Vespa.java</argument> + </arguments> + <sourceRoot>${project.build.directory}/generated-sources/vespa-version</sourceRoot> + </configuration> + </execution> + </executions> + </plugin> </plugins> </build> </project> diff --git a/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/FeedClient.java b/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/FeedClient.java index af652401044..2233b0a1a39 100644 --- a/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/FeedClient.java +++ b/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/FeedClient.java @@ -1,12 +1,13 @@ // Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.feed.client; +import java.io.Closeable; import java.util.concurrent.Future; /** * @author bjorncs */ -public interface FeedClient { +public interface FeedClient extends Closeable { Future<Result> put(String documentId, String documentJson, OperationParameters params, ResultCallback callback); Future<Result> remove(String documentId, OperationParameters params, ResultCallback callback); Future<Result> update(String documentId, String documentJson, OperationParameters params, ResultCallback callback); @@ -15,4 +16,5 @@ public interface FeedClient { void completed(Result result); void failed(FeedException e); } + } diff --git a/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/FeedClientBuilder.java b/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/FeedClientBuilder.java index e49d253a321..9e5f2a53a8d 100644 --- a/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/FeedClientBuilder.java +++ b/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/FeedClientBuilder.java @@ -1,14 +1,44 @@ // Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.feed.client; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; + /** + * Builder for creating a {@link FeedClient} instance. + * * @author bjorncs */ public class FeedClientBuilder { + SSLContext sslContext; + HostnameVerifier hostnameVerifier; + final Map<String, Supplier<String>> requestHeaders = new HashMap<>(); + URI endpoint; + Integer maxConnections; + public static FeedClientBuilder create() { return new FeedClientBuilder(); } private FeedClientBuilder() {} + public FeedClientBuilder setMaxConnection(int max) { this.maxConnections = max; return this; } + + public FeedClientBuilder setEndpoint(URI endpoint) { this.endpoint = endpoint; return this; } + + public FeedClientBuilder setSslContext(SSLContext context) { this.sslContext = context; return this; } + + public FeedClientBuilder setHostnameVerifier(HostnameVerifier verifier) { this.hostnameVerifier = verifier; return this; } + + public FeedClientBuilder addRequestHeader(String name, String value) { return addRequestHeader(name, () -> value); } + + public FeedClientBuilder addRequestHeader(String name, Supplier<String> valueSupplier) { + this.requestHeaders.put(name, valueSupplier); + return this; + } + public FeedClient build() { return new HttpFeedClient(this); } } diff --git a/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/HttpFeedClient.java b/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/HttpFeedClient.java index 6cf56ac9cdd..a7e39001117 100644 --- a/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/HttpFeedClient.java +++ b/vespa-feed-client/src/main/java/com/yahoo/vespa/feed/client/HttpFeedClient.java @@ -1,15 +1,85 @@ // Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa.feed.client; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient; +import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; +import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder; +import org.apache.hc.core5.http.message.BasicHeader; +import org.apache.hc.core5.http2.config.H2Config; +import org.apache.hc.core5.pool.PoolConcurrencyPolicy; +import org.apache.hc.core5.reactor.IOReactorConfig; +import org.apache.hc.core5.util.TimeValue; +import org.apache.hc.core5.util.Timeout; + +import java.io.IOException; +import java.net.URI; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.Future; +import java.util.function.Supplier; /** + * HTTP implementation of {@link FeedClient} + * * @author bjorncs */ class HttpFeedClient implements FeedClient { + private final CloseableHttpAsyncClient httpClient; + private final URI endpoint; + private final Map<String, Supplier<String>> requestHeaders; + HttpFeedClient(FeedClientBuilder builder) { + this.httpClient = createHttpClient(builder); + this.endpoint = getEndpoint(builder); + this.requestHeaders = new HashMap<>(builder.requestHeaders); + } + + private static CloseableHttpAsyncClient createHttpClient(FeedClientBuilder builder) { + HttpAsyncClientBuilder httpClientBuilder = HttpAsyncClientBuilder.create() + .setUserAgent(String.format("vespa-feed-client/%s", Vespa.VERSION)) + .setDefaultHeaders(Collections.singletonList(new BasicHeader("Vespa-Client-Version", Vespa.VERSION))) + .disableCookieManagement() + .disableRedirectHandling() + .disableConnectionState() + .setIOReactorConfig(IOReactorConfig.custom() + .setSoTimeout(Timeout.ofSeconds(10)) + .build()) + .setDefaultRequestConfig( + RequestConfig.custom() + .setConnectTimeout(Timeout.ofSeconds(10)) + .setConnectionRequestTimeout(Timeout.DISABLED) + .setResponseTimeout(Timeout.ofMinutes(5)) + .build()) + .setH2Config(H2Config.custom() + .setMaxConcurrentStreams(128) + .setPushEnabled(false) + .build()); + int maxConnections = builder.maxConnections != null ? builder.maxConnections : 4; + PoolingAsyncClientConnectionManagerBuilder connectionManagerBuilder = PoolingAsyncClientConnectionManagerBuilder.create() + .setConnectionTimeToLive(TimeValue.ofMinutes(10)) + .setMaxConnTotal(maxConnections) + .setMaxConnPerRoute(maxConnections) + .setPoolConcurrencyPolicy(PoolConcurrencyPolicy.LAX); + if (builder.sslContext != null) { + ClientTlsStrategyBuilder tlsStrategyBuilder = ClientTlsStrategyBuilder.create() + .setSslContext(builder.sslContext); + if (builder.hostnameVerifier != null) { + tlsStrategyBuilder.setHostnameVerifier(builder.hostnameVerifier); + } + connectionManagerBuilder.setTlsStrategy(tlsStrategyBuilder.build()); + } + httpClientBuilder.setConnectionManager(connectionManagerBuilder.build()); + return httpClientBuilder.build(); + } + + private static URI getEndpoint(FeedClientBuilder builder) { + if (builder.endpoint == null) throw new IllegalArgumentException("Endpoint must be specified"); + return builder.endpoint; } @Override @@ -26,4 +96,7 @@ class HttpFeedClient implements FeedClient { public Future<Result> update(String documentId, String documentJson, OperationParameters params, ResultCallback callback) { return null; } + + @Override public void close() throws IOException { this.httpClient.close(); } + } diff --git a/vespa-feed-client/src/main/sh/vespa-version-generator.sh b/vespa-feed-client/src/main/sh/vespa-version-generator.sh new file mode 100755 index 00000000000..d8f5878e2c5 --- /dev/null +++ b/vespa-feed-client/src/main/sh/vespa-version-generator.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +# Extracts the current version number (V_TAG_COMPONENT) from vtag.map and outputs this into a Java class. +# This replaces vespajlib/../VersionTagger.java as this module cannot depend on that, nor the dependencies +# of the resulting class. +# +# Author: bjorncs + +source=$1 +destination=$2 +destinationDir=$(dirname $destination) + +mkdir -p $destinationDir + +versionNumber=$(cat $source | grep V_TAG_COMPONENT | awk '{print $2}' ) + +cat > $destination <<- END +package com.yahoo.vespa.feed.client; + +class Vespa { + static final String VERSION = "$versionNumber"; +} +END |