diff --git a/CHANGELOG.md b/CHANGELOG.md index fb4dd19fe0..9f17e3f5eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,8 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) - Fix failure when deserialing response for tasks API ([#463](https://github.com/opensearch-project/opensearch-java/pull/463)) - Fix failure when deserializing boolean types for enums ([#463](https://github.com/opensearch-project/opensearch-java/pull/482)) - Fix missing minScore, postFilter, searchAfter, sort, trackScores in the MultisearchBody ([#516](https://github.com/opensearch-project/opensearch-java/pull/516)) +- Fix missing translog sync interval option in index settings ([#518](https://github.com/opensearch-project/opensearch-java/pull/518)) + ### Security ## [2.4.0] - 04/11/2023 diff --git a/java-client/src/main/java/org/opensearch/client/opensearch/indices/IndexSettings.java b/java-client/src/main/java/org/opensearch/client/opensearch/indices/IndexSettings.java index bae7d418cb..d732096e1e 100644 --- a/java-client/src/main/java/org/opensearch/client/opensearch/indices/IndexSettings.java +++ b/java-client/src/main/java/org/opensearch/client/opensearch/indices/IndexSettings.java @@ -198,12 +198,18 @@ public class IndexSettings implements JsonpSerializable { @Nullable private final Integer maxSlicesPerScroll; + @Nullable + private final Translog translog; + @Nullable private final String translogDurability; @Nullable private final String translogFlushThresholdSize; + @Nullable + private final Time translogSyncInterval; + @Nullable private final Boolean queryStringLenient; @@ -274,8 +280,10 @@ private IndexSettings(Builder builder) { this.verifiedBeforeClose = builder.verifiedBeforeClose; this.format = builder.format; this.maxSlicesPerScroll = builder.maxSlicesPerScroll; + this.translog = builder.translog; this.translogDurability = builder.translogDurability; this.translogFlushThresholdSize = builder.translogFlushThresholdSize; + this.translogSyncInterval = builder.translogSyncInterval; this.queryStringLenient = builder.queryStringLenient; this.priority = builder.priority; this.topMetricsMaxSize = builder.topMetricsMaxSize; @@ -672,6 +680,14 @@ public final Integer maxSlicesPerScroll() { return this.maxSlicesPerScroll; } + /** + * API name: {@code translog} + */ + @Nullable + public final Translog translog() { + return this.translog; + } + /** * API name: {@code translog.durability} */ @@ -688,6 +704,14 @@ public final String translogFlushThresholdSize() { return this.translogFlushThresholdSize; } + /** + * API name: {@code translog.sync_interval} + */ + @Nullable + public final Time translogSyncInterval() { + return this.translogSyncInterval; + } + /** * API name: {@code query_string.lenient} */ @@ -991,6 +1015,11 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { generator.writeKey("max_slices_per_scroll"); generator.write(this.maxSlicesPerScroll); + } + if (this.translog != null) { + generator.writeKey("translog"); + this.translog.serialize(generator, mapper); + } if (this.translogDurability != null) { generator.writeKey("translog.durability"); @@ -1001,6 +1030,11 @@ protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { generator.writeKey("translog.flush_threshold_size"); generator.write(this.translogFlushThresholdSize); + } + if (this.translogSyncInterval != null) { + generator.writeKey("translog.sync_interval"); + this.translogSyncInterval.serialize(generator, mapper); + } if (this.queryStringLenient != null) { generator.writeKey("query_string.lenient"); @@ -1186,12 +1220,18 @@ public static class Builder extends ObjectBuilderBase implements ObjectBuilder<I @Nullable private Integer maxSlicesPerScroll; + @Nullable + private Translog translog; + @Nullable private String translogDurability; @Nullable private String translogFlushThresholdSize; + @Nullable + private Time translogSyncInterval; + @Nullable private Boolean queryStringLenient; @@ -1676,6 +1716,14 @@ public final Builder maxSlicesPerScroll(@Nullable Integer value) { return this; } + /** + * API name: {@code translog} + */ + public final Builder translog(@Nullable Translog value) { + this.translog = value; + return this; + } + /** * API name: {@code translog.durability} */ @@ -1692,6 +1740,14 @@ public final Builder translogFlushThresholdSize(@Nullable String value) { return this; } + /** + * API name: {@code translog.sync_interval} + */ + public final Builder translogSyncInterval(@Nullable Time value) { + this.translogSyncInterval = value; + return this; + } + /** * API name: {@code query_string.lenient} */ @@ -1863,10 +1919,13 @@ protected static void setupIndexSettingsDeserializer(ObjectDeserializer<IndexSet op.add(Builder::format, JsonpDeserializer.stringDeserializer(), "format", "index.format"); op.add(Builder::maxSlicesPerScroll, JsonpDeserializer.integerDeserializer(), "max_slices_per_scroll", "index.max_slices_per_scroll"); + op.add(Builder::translog, Translog._DESERIALIZER, "translog", "index.translog"); op.add(Builder::translogDurability, JsonpDeserializer.stringDeserializer(), "translog.durability", "index.translog.durability"); op.add(Builder::translogFlushThresholdSize, JsonpDeserializer.stringDeserializer(), "translog.flush_threshold_size", "index.translog.flush_threshold_size"); + op.add(Builder::translogSyncInterval, Time._DESERIALIZER, + "translog.sync_interval", "index.translog.sync_interval"); op.add(Builder::queryStringLenient, JsonpDeserializer.booleanDeserializer(), "query_string.lenient", "index.query_string.lenient"); op.add(Builder::priority, JsonpDeserializer.stringDeserializer(), "priority", "index.priority"); diff --git a/java-client/src/main/java/org/opensearch/client/opensearch/indices/Translog.java b/java-client/src/main/java/org/opensearch/client/opensearch/indices/Translog.java new file mode 100644 index 0000000000..bc45c503e2 --- /dev/null +++ b/java-client/src/main/java/org/opensearch/client/opensearch/indices/Translog.java @@ -0,0 +1,170 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.client.opensearch.indices; + +import jakarta.json.stream.JsonGenerator; +import org.opensearch.client.json.JsonpDeserializable; +import org.opensearch.client.json.JsonpDeserializer; +import org.opensearch.client.json.JsonpMapper; +import org.opensearch.client.json.JsonpSerializable; +import org.opensearch.client.json.ObjectBuilderDeserializer; +import org.opensearch.client.json.ObjectDeserializer; +import org.opensearch.client.opensearch._types.Time; +import org.opensearch.client.util.ObjectBuilder; +import org.opensearch.client.util.ObjectBuilderBase; + +import javax.annotation.Nullable; +import java.util.function.Function; + + +@JsonpDeserializable +public class Translog implements JsonpSerializable { + + @Nullable + private final String durability; + + @Nullable + private final String flushThresholdSize; + + @Nullable + private final Time syncInterval; + + private Translog(Builder builder) { + + this.durability = builder.durability; + this.flushThresholdSize = builder.flushThresholdSize; + this.syncInterval = builder.syncInterval; + + } + + public static Translog of(Function<Builder, ObjectBuilder<Translog>> fn) { + return fn.apply(new Builder()).build(); + } + + /** + * API name: {@code durability} + */ + @Nullable + public final String durability() { + return this.durability; + } + + /** + * API name: {@code flush_threshold_size} + */ + @Nullable + public final String flushThresholdSize() { + return this.flushThresholdSize; + } + + /** + * API name: {@code sync_interval} + */ + @Nullable + public final Time syncInterval() { + return this.syncInterval; + } + + /** + * Serialize this object to JSON. + */ + public void serialize(JsonGenerator generator, JsonpMapper mapper) { + generator.writeStartObject(); + serializeInternal(generator, mapper); + generator.writeEnd(); + } + + protected void serializeInternal(JsonGenerator generator, JsonpMapper mapper) { + + if (this.durability != null) { + generator.writeKey("durability"); + generator.write(this.durability); + + } + if (this.flushThresholdSize != null) { + generator.writeKey("flush_threshold_size"); + generator.write(this.flushThresholdSize); + + } + if (this.syncInterval != null) { + generator.writeKey("sync_interval"); + this.syncInterval.serialize(generator, mapper); + + } + + } + + // --------------------------------------------------------------------------------------------- + + /** + * Builder for {@link Translog}. + */ + public static class Builder extends ObjectBuilderBase implements ObjectBuilder<Translog> { + + @Nullable + private String durability; + + @Nullable + private String flushThresholdSize; + + @Nullable + private Time syncInterval; + + /** + * API name: {@code durability} + */ + public final Translog.Builder durability(@Nullable String value) { + this.durability = value; + return this; + } + + /** + * API name: {@code flush_threshold_size} + */ + public final Translog.Builder flushThresholdSize(@Nullable String value) { + this.flushThresholdSize = value; + return this; + } + + /** + * API name: {@code sync_interval} + */ + public final Translog.Builder syncInterval(@Nullable Time value) { + this.syncInterval = value; + return this; + } + + /** + * Builds a {@link Translog}. + * + * @throws NullPointerException + * if some of the required fields are null. + */ + public Translog build() { + _checkSingleUse(); + + return new Translog(this); + } + } + + /** + * Json deserializer for {@link Translog} + */ + public static final JsonpDeserializer<Translog> _DESERIALIZER = ObjectBuilderDeserializer.lazy(Builder::new, + Translog::setupTranslogDeserializer); + + protected static void setupTranslogDeserializer(ObjectDeserializer<Translog.Builder> op) { + + op.add(Translog.Builder::durability, JsonpDeserializer.stringDeserializer(), "durability"); + op.add(Translog.Builder::flushThresholdSize, JsonpDeserializer.stringDeserializer(), "flush_threshold_size"); + op.add(Translog.Builder::syncInterval, Time._DESERIALIZER, "sync_interval"); + + } + +} diff --git a/java-client/src/test/java/org/opensearch/client/opensearch/experiments/ParsingTests.java b/java-client/src/test/java/org/opensearch/client/opensearch/experiments/ParsingTests.java index 6bbf1917a8..0c64d4a7a2 100644 --- a/java-client/src/test/java/org/opensearch/client/opensearch/experiments/ParsingTests.java +++ b/java-client/src/test/java/org/opensearch/client/opensearch/experiments/ParsingTests.java @@ -32,20 +32,22 @@ package org.opensearch.client.opensearch.experiments; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; + import jakarta.json.spi.JsonProvider; -import jakarta.json.stream.JsonGenerator; -import jakarta.json.stream.JsonParser; import jakarta.json.stream.JsonParsingException; import org.junit.Assert; import org.junit.Test; +import org.opensearch.client.json.JsonpDeserializer; +import org.opensearch.client.json.JsonpSerializable; import org.opensearch.client.json.jsonb.JsonbJsonpMapper; +import org.opensearch.client.opensearch._types.Time; import org.opensearch.client.opensearch.experiments.api.FooRequest; +import org.opensearch.client.opensearch.indices.IndexSettings; import org.opensearch.client.opensearch.indices.IndexSettingsMapping; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; - public class ParsingTests extends Assert { @Test @@ -53,8 +55,6 @@ public void testFoo() throws Exception { try { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - FooRequest foo = FooRequest.builder() .name("z") .value(1) @@ -64,19 +64,10 @@ public void testFoo() throws Exception { ) .build(); - JsonProvider provider = JsonProvider.provider(); - JsonGenerator generator = provider.createGenerator(baos); - foo.serialize(generator, new JsonbJsonpMapper()); - - generator.close(); - String str = baos.toString(); - + String str = serialize(foo); assertEquals("{\"name\":\"z\",\"value\":1,\"indices\":[\"a\",\"b\",\"c\"],\"bar\":{\"name\":\"Raise the bar\"}}", str); - JsonParser parser = provider.createParser(new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8))); - - FooRequest foo2 = FooRequest.parser().deserialize(parser, new JsonbJsonpMapper()); - + FooRequest foo2 = deserialize(str, FooRequest.parser()); assertEquals(foo.name(), foo2.name()); assertEquals(foo.value(), foo2.value()); assertNull(foo2.size()); @@ -88,11 +79,31 @@ public void testFoo() throws Exception { } @Test - public void testIndexSettingsMappingParsing() { + public void testIndexSettingsSyncIntervalTimeParsing() { try { - var baos = new ByteArrayOutputStream(); + var indexSettings = IndexSettings.of(_1 -> _1.translogSyncInterval(Time.of(_2 -> _2.time("10s")))); + + var str = serialize(indexSettings); + assertEquals("{\"translog.sync_interval\":\"10s\"}", str); + + IndexSettings deserialized = deserialize(str, IndexSettings._DESERIALIZER); + assertEquals(indexSettings.translogSyncInterval().time(), deserialized.translogSyncInterval().time()); + + var responseStr = "{\"translog\":{\"sync_interval\":\"10s\"}}"; + IndexSettings responseDeserialized = deserialize(responseStr, IndexSettings._DESERIALIZER); + assertEquals(indexSettings.translogSyncInterval().time(), responseDeserialized.translog().syncInterval().time()); + + } catch (JsonParsingException je) { + throw new JsonParsingException(je.getMessage() + " at " + je.getLocation(), je, je.getLocation()); + } + } + + @Test + public void testIndexSettingsMappingParsing() { + + try { var mapping = IndexSettingsMapping.of(b -> b .totalFields(d -> d.limit(1L)) @@ -101,20 +112,11 @@ public void testIndexSettingsMappingParsing() { .nestedObjects(d -> d.limit(4L)) .fieldNameLength(d -> d.limit(5L))); - var provider = JsonProvider.provider(); - var generator = provider.createGenerator(baos); - mapping.serialize(generator, new JsonbJsonpMapper()); - - generator.close(); - var str = baos.toString(); - + var str = serialize(mapping); assertEquals("{\"total_fields\":{\"limit\":1},\"depth\":{\"limit\":2},\"nested_fields\":{\"limit\":3}," + "\"nested_objects\":{\"limit\":4},\"field_name_length\":{\"limit\":5}}", str); - var parser = provider.createParser(new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8))); - - var deserialized = IndexSettingsMapping._DESERIALIZER.deserialize(parser, new JsonbJsonpMapper()); - + var deserialized = deserialize(str, IndexSettingsMapping._DESERIALIZER); assertEquals(mapping.totalFields().limit(), deserialized.totalFields().limit()); assertEquals(mapping.depth().limit(), deserialized.depth().limit()); assertEquals(mapping.nestedFields().limit(), deserialized.nestedFields().limit()); @@ -124,4 +126,22 @@ public void testIndexSettingsMappingParsing() { throw new JsonParsingException(je.getMessage() + " at " + je.getLocation(), je, je.getLocation()); } } + + private <T extends JsonpSerializable> T deserialize(String serializedValue, JsonpDeserializer<T> deserializer) { + var provider = JsonProvider.provider(); + var parser = provider.createParser(new ByteArrayInputStream(serializedValue.getBytes(StandardCharsets.UTF_8))); + + return deserializer.deserialize(parser, new JsonbJsonpMapper()); + } + + private String serialize(JsonpSerializable object) { + var baos = new ByteArrayOutputStream(); + var provider = JsonProvider.provider(); + + var generator = provider.createGenerator(baos); + object.serialize(generator, new JsonbJsonpMapper()); + generator.close(); + + return baos.toString(); + } } diff --git a/java-client/src/test/java/org/opensearch/client/opensearch/integTest/AbstractRequestIT.java b/java-client/src/test/java/org/opensearch/client/opensearch/integTest/AbstractRequestIT.java index 0435cb9f72..376ab63986 100644 --- a/java-client/src/test/java/org/opensearch/client/opensearch/integTest/AbstractRequestIT.java +++ b/java-client/src/test/java/org/opensearch/client/opensearch/integTest/AbstractRequestIT.java @@ -114,10 +114,11 @@ public void testIndexCreation() throws Exception { } @Test - public void testIndexSettingsMapping() throws Exception { + public void testIndexSettings() throws Exception { var createResponse = javaClient().indices() .create(r -> r.index("test-settings") .settings(s -> s + .translogSyncInterval(Time.of(t -> t.time("10s"))) .mapping(m -> m .fieldNameLength(f -> f.limit(300L)) .totalFields(f -> f.limit(30L)) @@ -133,6 +134,9 @@ public void testIndexSettingsMapping() throws Exception { assertNotNull(createdIndexSettings); assertNotNull(createdIndexSettings.settings()); assertNotNull(createdIndexSettings.settings().index()); + assertNotNull(createdIndexSettings.settings().index().translog()); + assertNotNull(createdIndexSettings.settings().index().translog().syncInterval()); + assertEquals("10s", createdIndexSettings.settings().index().translog().syncInterval().time()); var createdMappingSettings = createdIndexSettings.settings().index().mapping(); assertNotNull(createdMappingSettings); assertNotNull(createdMappingSettings.fieldNameLength()); @@ -149,6 +153,7 @@ public void testIndexSettingsMapping() throws Exception { var putSettingsResponse = javaClient().indices().putSettings(r -> r .index("test-settings") .settings(s -> s + .translogSyncInterval(Time.of(t -> t.time("5s"))) .mapping(m -> m .fieldNameLength(f -> f.limit(400L)) .totalFields(f -> f.limit(130L)) @@ -163,6 +168,9 @@ public void testIndexSettingsMapping() throws Exception { assertNotNull(updatedIndexSettings); assertNotNull(updatedIndexSettings.settings()); assertNotNull(updatedIndexSettings.settings().index()); + assertNotNull(updatedIndexSettings.settings().index().translog()); + assertNotNull(updatedIndexSettings.settings().index().translog().syncInterval()); + assertEquals("5s", updatedIndexSettings.settings().index().translog().syncInterval().time()); var updatedMappingSettings = updatedIndexSettings.settings().index().mapping(); assertNotNull(updatedMappingSettings); assertNotNull(updatedMappingSettings.fieldNameLength());