Skip to content

Commit

Permalink
Add configuration property quarkus.hibernate-search-orm.elasticsearch…
Browse files Browse the repository at this point in the history
  • Loading branch information
yrodiere committed Aug 21, 2023
1 parent f47224c commit 1a1a0de
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package io.quarkus.hibernate.search.orm.elasticsearch.test.search.shard_failure;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;

import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.KeywordField;

@Entity
@Indexed
public class MyEntity1 {

@Id
@GeneratedValue
private Long id;

@KeywordField
private String text;

public MyEntity1() {
}

public MyEntity1(String text) {
this.text = text;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getText() {
return text;
}

public void setText(String text) {
this.text = text;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package io.quarkus.hibernate.search.orm.elasticsearch.test.search.shard_failure;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;

import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.KeywordField;

@Entity
@Indexed
public class MyEntity2 {

@Id
@GeneratedValue
private Long id;

@KeywordField
private String text;

public MyEntity2() {
}

public MyEntity2(String text) {
this.text = text;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getText() {
return text;
}

public void setText(String text) {
this.text = text;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package io.quarkus.hibernate.search.orm.elasticsearch.test.search.shard_failure;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.List;

import jakarta.inject.Inject;

import org.hibernate.search.mapper.orm.session.SearchSession;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.hibernate.search.orm.elasticsearch.test.util.TransactionUtils;
import io.quarkus.narayana.jta.QuarkusTransaction;
import io.quarkus.test.QuarkusUnitTest;

public class ShardFailureIgnoreDefaultTest {

@RegisterExtension
static QuarkusUnitTest runner = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addClass(TransactionUtils.class)
.addClass(MyEntity1.class)
.addClass(MyEntity2.class)
.addAsResource("hsearch-4915/index2.json"))
.withConfigurationResource("application.properties")
// Override the type of the keyword field to integer, to create an error in one shard only.
.overrideConfigKey(
"quarkus.hibernate-search-orm.elasticsearch.indexes.\"MyEntity2\".schema-management.mapping-file",
"hsearch-4915/index2.json");

@Inject
SearchSession session;

@Test
public void testShardFailureIgnored() {
QuarkusTransaction.joiningExisting().run(() -> {
session.toEntityManager().persist(new MyEntity1("42"));
session.toEntityManager().persist(new MyEntity2("42"));
});
QuarkusTransaction.joiningExisting().run(() -> {
assertThat(session.search(List.of(MyEntity1.class, MyEntity2.class))
.where(f -> f.wildcard().field("text").matching("4*"))
.fetchHits(20))
// MyEntity2 fails because "text" is an integer field there
// We expect that index (shard) to be ignored
.hasSize(1);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.quarkus.hibernate.search.orm.elasticsearch.test.search.shard_failure;

import static org.assertj.core.api.Assertions.assertThatThrownBy;

import java.util.List;

import jakarta.inject.Inject;

import org.hibernate.search.mapper.orm.session.SearchSession;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.hibernate.search.orm.elasticsearch.test.util.TransactionUtils;
import io.quarkus.narayana.jta.QuarkusTransaction;
import io.quarkus.test.QuarkusUnitTest;

public class ShardFailureIgnoreFalseTest {

@RegisterExtension
static QuarkusUnitTest runner = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addClass(TransactionUtils.class)
.addClass(MyEntity1.class)
.addClass(MyEntity2.class)
.addAsResource("hsearch-4915/index2.json"))
.withConfigurationResource("application.properties")
// Request that shard failures cause an exception instead of being ignored
.overrideConfigKey("quarkus.hibernate-search-orm.elasticsearch.query.shard-failure.ignore", "false")
// Override the type of the keyword field to integer, to create an error in one shard only.
.overrideConfigKey(
"quarkus.hibernate-search-orm.elasticsearch.indexes.\"MyEntity2\".schema-management.mapping-file",
"hsearch-4915/index2.json");

@Inject
SearchSession session;

@Test
public void testShardFailureIgnored() {
QuarkusTransaction.joiningExisting().run(() -> {
session.toEntityManager().persist(new MyEntity1("42"));
session.toEntityManager().persist(new MyEntity2("42"));
});
QuarkusTransaction.joiningExisting().run(() -> {
assertThatThrownBy(() -> session.search(List.of(MyEntity1.class, MyEntity2.class))
.where(f -> f.wildcard().field("text").matching("4*"))
.fetchHits(20))
// MyEntity2 fails because "text" is an integer field there
// We expect an exception
.hasMessageContaining("Elasticsearch request failed",
"\"type\": \"query_shard_exception\"");
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"properties": {
"text": {
"type": "integer"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,8 @@ private void contributeBackendRuntimeProperties(BiConsumer<String, Object> prope
elasticsearchBackendConfig.threadPool().size());
addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.VERSION_CHECK_ENABLED,
elasticsearchBackendConfig.versionCheck());
addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.QUERY_SHARD_FAILURE_IGNORE,
elasticsearchBackendConfig.query().shardFailure().ignore());

addBackendConfig(propertyCollector, backendName, ElasticsearchBackendSettings.DISCOVERY_ENABLED,
elasticsearchBackendConfig.discovery().enabled());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ interface ElasticsearchBackendRuntimeConfig {
*/
ThreadPoolConfig threadPool();

/**
* Configuration for search queries to this backend.
*/
ElasticsearchQueryConfig query();

/**
* Whether Hibernate Search should check the version of the Elasticsearch cluster on startup.
*
Expand Down Expand Up @@ -505,6 +510,26 @@ interface ThreadPoolConfig {
OptionalInt size();
}

@ConfigGroup
interface ElasticsearchQueryConfig {
/**
* Configuration for the behavior on shard failure.
*/
ElasticsearchQueryShardFailureConfig shardFailure();
}

@ConfigGroup
interface ElasticsearchQueryShardFailureConfig {
/**
* Whether partial shard failures are ignored (`true`)
* or lead to Hibernate Search throwing an exception (`false`).
* <p>
* Will default to `false` in Hibernate Search 7.
*/
@WithDefault("true")
boolean ignore();
}

// We can't set actual default values in this section,
// otherwise "quarkus.hibernate-search-orm.elasticsearch.index-defaults" will be ignored.
@ConfigGroup
Expand Down

0 comments on commit 1a1a0de

Please sign in to comment.