Skip to content

Commit 06b1a47

Browse files
committed
HSEARCH-5464 OpenSearch client
1 parent a900d4a commit 06b1a47

File tree

40 files changed

+4264
-47
lines changed

40 files changed

+4264
-47
lines changed

backend/elasticsearch-client/common/src/main/java/org/hibernate/search/backend/elasticsearch/client/common/logging/spi/ElasticsearchClientCommonLog.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,6 @@ public interface ElasticsearchClientCommonLog
4747
* here to the next value.
4848
*/
4949
@LogMessage(level = TRACE)
50-
@Message(id = ID_OFFSET + 1, value = "")
50+
@Message(id = ID_OFFSET + 2, value = "")
5151
void nextLoggerIdForConvenience();
5252
}

backend/elasticsearch-client/common/src/main/java/org/hibernate/search/backend/elasticsearch/client/common/logging/spi/ElasticsearchClientConfigurationLog.java

Lines changed: 6 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,22 @@
55
package org.hibernate.search.backend.elasticsearch.client.common.logging.spi;
66

77
import static org.hibernate.search.backend.elasticsearch.client.common.logging.spi.ElasticsearchClientCommonLog.ID_BACKEND_OFFSET;
8+
import static org.hibernate.search.backend.elasticsearch.client.common.logging.spi.ElasticsearchClientCommonLog.ID_OFFSET;
89
import static org.hibernate.search.backend.elasticsearch.client.common.logging.spi.ElasticsearchClientCommonLog.ID_OFFSET_LEGACY_ES;
9-
import static org.jboss.logging.Logger.Level.DEBUG;
1010

1111
import java.lang.invoke.MethodHandles;
1212
import java.util.List;
13-
import java.util.Set;
1413

15-
import org.hibernate.search.engine.environment.bean.BeanHolder;
1614
import org.hibernate.search.util.common.SearchException;
1715
import org.hibernate.search.util.common.logging.CategorizedLogger;
1816
import org.hibernate.search.util.common.logging.impl.LoggerFactory;
1917
import org.hibernate.search.util.common.logging.impl.MessageConstants;
20-
import org.hibernate.search.util.common.reporting.EventContext;
2118

2219
import org.jboss.logging.Logger;
2320
import org.jboss.logging.annotations.Cause;
2421
import org.jboss.logging.annotations.LogMessage;
2522
import org.jboss.logging.annotations.Message;
2623
import org.jboss.logging.annotations.MessageLogger;
27-
import org.jboss.logging.annotations.Param;
2824

2925
@CategorizedLogger(
3026
category = ElasticsearchClientConfigurationLog.CATEGORY_NAME,
@@ -57,37 +53,12 @@ public interface ElasticsearchClientConfigurationLog {
5753
// -----------------------------------
5854
// New messages from Search 6 onwards
5955
// -----------------------------------
60-
@Message(id = ID_BACKEND_OFFSET + 15, value = "Invalid multi-tenancy strategy name: '%1$s'."
61-
+ " Valid names are: %2$s.")
62-
SearchException invalidMultiTenancyStrategyName(String invalidRepresentation, List<String> validRepresentations);
63-
64-
@Message(id = ID_BACKEND_OFFSET + 16,
65-
value = "Invalid tenant identifiers: '%1$s'."
66-
+ " No tenant identifier is expected, because multi-tenancy is disabled for this backend.")
67-
SearchException tenantIdProvidedButMultiTenancyDisabled(Set<String> tenantIds, @Param EventContext context);
68-
69-
@Message(id = ID_BACKEND_OFFSET + 17,
70-
value = "Missing tenant identifier."
71-
+ " A tenant identifier is expected, because multi-tenancy is enabled for this backend.")
72-
SearchException multiTenancyEnabledButNoTenantIdProvided(@Param EventContext context);
73-
74-
@Message(id = ID_BACKEND_OFFSET + 58, value = "Invalid Elasticsearch distribution name: '%1$s'."
75-
+ " Valid names are: %2$s.")
76-
SearchException invalidElasticsearchDistributionName(String invalidRepresentation, List<String> validRepresentations);
7756

7857
@Message(id = ID_BACKEND_OFFSET + 89, value = "Invalid host/port: '%1$s'."
7958
+ " The host/port string must use the format 'host:port', for example 'mycompany.com:9200'"
8059
+ " The URI scheme ('http://', 'https://') must not be included.")
8160
SearchException invalidHostAndPort(String hostAndPort, @Cause Exception e);
8261

83-
@Message(id = ID_BACKEND_OFFSET + 91, value = "Invalid name for the type-name mapping strategy: '%1$s'."
84-
+ " Valid names are: %2$s.")
85-
SearchException invalidTypeNameMappingStrategyName(String invalidRepresentation, List<String> validRepresentations);
86-
87-
@Message(id = ID_BACKEND_OFFSET + 121, value = "Invalid dynamic type: '%1$s'."
88-
+ " Valid values are: %2$s.")
89-
SearchException invalidDynamicType(String invalidRepresentation, List<String> validRepresentations);
90-
9162
@Message(id = ID_BACKEND_OFFSET + 126, value = "Invalid target hosts configuration:"
9263
+ " both the 'uris' property and the 'protocol' property are set."
9364
+ " Uris: '%1$s'. Protocol: '%2$s'."
@@ -115,18 +86,11 @@ public interface ElasticsearchClientConfigurationLog {
11586
value = "Invalid target hosts configuration: the list of URIs must not be empty.")
11687
SearchException emptyListOfUris();
11788

118-
@Message(id = ID_BACKEND_OFFSET + 148,
119-
value = "Invalid backend configuration: mapping requires multi-tenancy"
120-
+ " but no multi-tenancy strategy is set.")
121-
SearchException multiTenancyRequiredButExplicitlyDisabledByBackend();
89+
// -----------------------------------
90+
// New messages from Search 8.2 onwards
91+
// -----------------------------------
12292

123-
@Message(id = ID_BACKEND_OFFSET + 149,
124-
value = "Invalid backend configuration: mapping requires single-tenancy"
125-
+ " but multi-tenancy strategy is set.")
126-
SearchException multiTenancyNotRequiredButExplicitlyEnabledByTheBackend();
93+
@Message(id = ID_OFFSET + 1, value = "Invalid uri: '%1$s'. Reason: %2$s")
94+
SearchException invalidUri(String uri, String reason, @Cause Exception e);
12795

128-
@LogMessage(level = DEBUG)
129-
@Message(id = ID_BACKEND_OFFSET + 192,
130-
value = "Elasticsearch backend will use client factory '%s'. Context: %s")
131-
void backendClientFactory(BeanHolder<?> clientFactoryHolder, String eventContext);
13296
}

backend/elasticsearch-client/elasticsearch-rest-client/src/test/java/org/hibernate/search/backend/elasticsearch/client/elasticsearch/lowlevel/impl/GsonHttpEntityTest.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22
* SPDX-License-Identifier: Apache-2.0
33
* Copyright Red Hat Inc. and Hibernate Authors
44
*/
5-
package org.hibernate.search.backend.elasticsearch.client.elasticsearch.lowlevel.impl;/*
6-
* SPDX-License-Identifier: Apache-2.0
7-
* Copyright Red Hat Inc. and Hibernate Authors
8-
*/
5+
package org.hibernate.search.backend.elasticsearch.client.elasticsearch.lowlevel.impl;
96

107
import static org.assertj.core.api.Assertions.assertThat;
118
import static org.junit.jupiter.api.Assumptions.assumeTrue;
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
SPDX-License-Identifier: Apache-2.0
4+
Copyright Red Hat Inc. and Hibernate Authors
5+
-->
6+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
7+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
8+
<modelVersion>4.0.0</modelVersion>
9+
<parent>
10+
<groupId>org.hibernate.search</groupId>
11+
<artifactId>hibernate-search-parent-public</artifactId>
12+
<version>8.2.0-SNAPSHOT</version>
13+
<relativePath>../../../build/parents/public</relativePath>
14+
</parent>
15+
<artifactId>hibernate-search-backend-elasticsearch-client-opensearch-rest</artifactId>
16+
17+
<name>Hibernate Search Backend - Elasticsearch client based on the low-level OpenSearch client</name>
18+
<description>Hibernate Search Elasticsearch client based on the low-level OpenSearch client</description>
19+
20+
<properties>
21+
<!-- This is a publicly distributed module that should be published: -->
22+
<deploy.skip>false</deploy.skip>
23+
<java.module.name>org.hibernate.search.backend.elasticsearch.client.opensearch.lowlevel</java.module.name>
24+
</properties>
25+
26+
<dependencies>
27+
<dependency>
28+
<groupId>org.hibernate.search</groupId>
29+
<artifactId>hibernate-search-engine</artifactId>
30+
</dependency>
31+
<dependency>
32+
<groupId>org.hibernate.search</groupId>
33+
<artifactId>hibernate-search-backend-elasticsearch-client-common</artifactId>
34+
</dependency>
35+
<dependency>
36+
<groupId>org.opensearch.client</groupId>
37+
<artifactId>opensearch-rest-client</artifactId>
38+
</dependency>
39+
<dependency>
40+
<groupId>org.opensearch.client</groupId>
41+
<artifactId>opensearch-rest-client-sniffer</artifactId>
42+
</dependency>
43+
<dependency>
44+
<groupId>org.jboss.logging</groupId>
45+
<artifactId>jboss-logging</artifactId>
46+
</dependency>
47+
<dependency>
48+
<groupId>org.jboss.logging</groupId>
49+
<artifactId>jboss-logging-annotations</artifactId>
50+
</dependency>
51+
<dependency>
52+
<groupId>com.google.code.gson</groupId>
53+
<artifactId>gson</artifactId>
54+
</dependency>
55+
56+
<!-- We only depend on Jackson indirectly through the Elasticsearch client sniffer,
57+
but Dependabot apparently ignores dependency management,
58+
so we need this explicit dependency to have Dependabot update versions. -->
59+
<dependency>
60+
<groupId>com.fasterxml.jackson.core</groupId>
61+
<artifactId>jackson-core</artifactId>
62+
</dependency>
63+
64+
<!-- Test -->
65+
<dependency>
66+
<groupId>org.hibernate.search</groupId>
67+
<artifactId>hibernate-search-util-internal-test-common</artifactId>
68+
<scope>test</scope>
69+
</dependency>
70+
</dependencies>
71+
72+
<build>
73+
<plugins>
74+
<plugin>
75+
<groupId>org.moditect</groupId>
76+
<artifactId>moditect-maven-plugin</artifactId>
77+
</plugin>
78+
</plugins>
79+
</build>
80+
</project>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.search.backend.elasticsearch.client.elasticsearch.lowlevel;
6+
7+
8+
import org.hibernate.search.engine.cfg.ConfigurationPropertySource;
9+
import org.hibernate.search.engine.environment.bean.BeanResolver;
10+
11+
import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder;
12+
13+
14+
/**
15+
* The context passed to {@link ElasticsearchHttpClientConfigurer}.
16+
*/
17+
public interface ElasticsearchHttpClientConfigurationContext {
18+
19+
/**
20+
* @return A {@link BeanResolver}.
21+
*/
22+
BeanResolver beanResolver();
23+
24+
/**
25+
* @return A configuration property source, appropriately masked so that the factory
26+
* doesn't need to care about Hibernate Search prefixes (hibernate.search.*, etc.). All the properties
27+
* can be accessed at the root.
28+
* <strong>CAUTION:</strong> the property key "type" is reserved for use by the engine.
29+
*/
30+
ConfigurationPropertySource configurationPropertySource();
31+
32+
/**
33+
* @return An Apache HTTP client builder, to set the configuration.
34+
* @see <a href="http://hc.apache.org/httpcomponents-client-ga/">the Apache HTTP Client documentation</a>
35+
*/
36+
HttpAsyncClientBuilder clientBuilder();
37+
38+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.search.backend.elasticsearch.client.elasticsearch.lowlevel.impl;
6+
7+
import java.io.IOException;
8+
import java.nio.ByteBuffer;
9+
import java.util.List;
10+
11+
import org.apache.hc.core5.http.Header;
12+
import org.apache.hc.core5.http.nio.ContentEncoder;
13+
import org.apache.hc.core5.http.nio.DataStreamChannel;
14+
15+
16+
final class ByteBufferDataStreamChannel implements ContentEncoder, DataStreamChannel {
17+
private final ByteBuffer buffer;
18+
private boolean complete = false;
19+
20+
ByteBufferDataStreamChannel(ByteBuffer buffer) {
21+
this.buffer = buffer;
22+
if ( !buffer.hasArray() ) {
23+
throw new IllegalArgumentException( getClass().getName() + " requires a ByteBuffer backed by an array." );
24+
}
25+
}
26+
27+
@Override
28+
public void requestOutput() {
29+
30+
}
31+
32+
@Override
33+
public int write(ByteBuffer src) {
34+
int toWrite = Math.min( src.remaining(), buffer.remaining() );
35+
src.get( buffer.array(), buffer.arrayOffset() + buffer.position(), toWrite );
36+
buffer.position( buffer.position() + toWrite );
37+
return toWrite;
38+
}
39+
40+
@Override
41+
public void endStream() throws IOException {
42+
complete = true;
43+
}
44+
45+
@Override
46+
public void endStream(List<? extends Header> trailers) throws IOException {
47+
complete = true;
48+
}
49+
50+
@Override
51+
public void complete(List<? extends Header> trailers) throws IOException {
52+
complete = true;
53+
}
54+
55+
@Override
56+
public boolean isCompleted() {
57+
return complete;
58+
}
59+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.search.backend.elasticsearch.client.elasticsearch.lowlevel.impl;
6+
7+
8+
import java.util.concurrent.TimeUnit;
9+
10+
import org.apache.hc.client5.http.ConnectionKeepAliveStrategy;
11+
import org.apache.hc.client5.http.impl.DefaultConnectionKeepAliveStrategy;
12+
import org.apache.hc.core5.http.HttpResponse;
13+
import org.apache.hc.core5.http.protocol.HttpContext;
14+
import org.apache.hc.core5.util.TimeValue;
15+
16+
final class CustomConnectionKeepAliveStrategy implements ConnectionKeepAliveStrategy {
17+
18+
private final TimeValue maxKeepAlive;
19+
private final long maxKeepAliveMilliseconds;
20+
21+
CustomConnectionKeepAliveStrategy(long maxKeepAlive) {
22+
this.maxKeepAlive = TimeValue.of( maxKeepAlive, TimeUnit.MILLISECONDS );
23+
this.maxKeepAliveMilliseconds = maxKeepAlive;
24+
}
25+
26+
@Override
27+
public TimeValue getKeepAliveDuration(HttpResponse response, HttpContext context) {
28+
// get a keep alive from a request header if one is present
29+
TimeValue keepAliveDuration = DefaultConnectionKeepAliveStrategy.INSTANCE.getKeepAliveDuration( response, context );
30+
long keepAliveDurationMilliseconds = keepAliveDuration.toMilliseconds();
31+
// if the keep alive timeout from a request is less than configured one - let's honor it:
32+
if ( keepAliveDurationMilliseconds > 0 && keepAliveDurationMilliseconds < maxKeepAliveMilliseconds ) {
33+
return keepAliveDuration;
34+
}
35+
return maxKeepAlive;
36+
}
37+
}

0 commit comments

Comments
 (0)