diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponse.java index b0ec0968f8d1d..7b344a4c25a1b 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponse.java @@ -13,12 +13,11 @@ import org.elasticsearch.action.support.master.IsAcknowledgedSupplier; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.routing.allocation.RoutingExplanations; -import org.elasticsearch.common.collect.Iterators; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.logging.DeprecationCategory; import org.elasticsearch.common.logging.DeprecationLogger; -import org.elasticsearch.common.xcontent.ChunkedToXContentHelper; +import org.elasticsearch.common.xcontent.ChunkedToXContent; import org.elasticsearch.common.xcontent.ChunkedToXContentObject; import org.elasticsearch.core.RestApiVersion; import org.elasticsearch.core.UpdateForV10; @@ -26,7 +25,6 @@ import org.elasticsearch.xcontent.ToXContent; import java.io.IOException; -import java.util.Collections; import java.util.Iterator; import java.util.Objects; @@ -98,20 +96,15 @@ public Iterator toXContentChunked(ToXContent.Params outerP } @Override - public Iterator toXContentChunkedV7(ToXContent.Params outerParams) { - return Iterators.concat( - Iterators.single((builder, params) -> builder.startObject().field(ACKNOWLEDGED_KEY, isAcknowledged())), - emitState(outerParams) - ? ChunkedToXContentHelper.wrapWithObject("state", state.toXContentChunked(outerParams)) - : Collections.emptyIterator(), - Iterators.single((builder, params) -> { - if (params.paramAsBoolean("explain", false)) { - explanations.toXContent(builder, params); - } - - builder.endObject(); - return builder; - }) - ); + public Iterator toXContentChunkedV7(ToXContent.Params params) { + return ChunkedToXContent.builder(params).object(b -> { + b.field(ACKNOWLEDGED_KEY, isAcknowledged()); + if (emitState(params)) { + b.xContentObject("state", state); + } + if (params.paramAsBoolean("explain", false)) { + b.append(explanations); + } + }); } } diff --git a/server/src/main/java/org/elasticsearch/cluster/ClusterState.java b/server/src/main/java/org/elasticsearch/cluster/ClusterState.java index cafda93dda9a5..64df6e77326e4 100644 --- a/server/src/main/java/org/elasticsearch/cluster/ClusterState.java +++ b/server/src/main/java/org/elasticsearch/cluster/ClusterState.java @@ -759,10 +759,8 @@ public Iterator toXContentChunked(ToXContent.Params outerP // customs metrics.contains(Metric.CUSTOMS) - ? Iterators.flatMap( - customs.entrySet().iterator(), - cursor -> ChunkedToXContentHelper.wrapWithObject(cursor.getKey(), cursor.getValue().toXContentChunked(outerParams)) - ) + ? ChunkedToXContent.builder(outerParams) + .forEach(customs.entrySet().iterator(), (b, e) -> b.xContentObject(e.getKey(), e.getValue())) : Collections.emptyIterator() ); } diff --git a/server/src/main/java/org/elasticsearch/common/xcontent/ChunkedToXContentBuilder.java b/server/src/main/java/org/elasticsearch/common/xcontent/ChunkedToXContentBuilder.java index 0868a7fa303ae..0102e58c7c1dc 100644 --- a/server/src/main/java/org/elasticsearch/common/xcontent/ChunkedToXContentBuilder.java +++ b/server/src/main/java/org/elasticsearch/common/xcontent/ChunkedToXContentBuilder.java @@ -38,6 +38,10 @@ private void addChunk(ToXContent content) { builder.add(Objects.requireNonNull(content)); } + public ToXContent.Params params() { + return params; + } + private void startObject() { addChunk((b, p) -> b.startObject()); } @@ -259,6 +263,16 @@ public ChunkedToXContentBuilder array(Iterator items, BiConsumer items) { + startArray(); + items.forEachRemaining(this::append); + endArray(); + return this; + } + /** * Creates an array, with the contents set by appending together * the return values of {@code create} called on each item returned by {@code items} @@ -351,6 +365,12 @@ public ChunkedToXContentBuilder field(String name, ToXContent value) { return this; } + public ChunkedToXContentBuilder field(String name, ChunkedToXContent value) { + addChunk((b, p) -> b.field(name)); + append(value); + return this; + } + public ChunkedToXContentBuilder field(String name, Object value) { addChunk((b, p) -> b.field(name, value)); return this; diff --git a/server/src/main/java/org/elasticsearch/common/xcontent/ChunkedToXContentHelper.java b/server/src/main/java/org/elasticsearch/common/xcontent/ChunkedToXContentHelper.java index 940d4495ae909..fcbe0ac2b2edb 100644 --- a/server/src/main/java/org/elasticsearch/common/xcontent/ChunkedToXContentHelper.java +++ b/server/src/main/java/org/elasticsearch/common/xcontent/ChunkedToXContentHelper.java @@ -53,26 +53,10 @@ public static Iterator field(String name, String value) { return Iterators.single(((builder, params) -> builder.field(name, value))); } - /** - * Creates an Iterator to serialize a named field where the value is represented by a {@link ChunkedToXContentObject}. - * Chunked equivalent for {@code XContentBuilder field(String name, ToXContent value)} - * @param name name of the field - * @param value value for this field - * @param params params to propagate for XContent serialization - * @return Iterator composing field name and value serialization - */ - public static Iterator field(String name, ChunkedToXContentObject value, ToXContent.Params params) { - return Iterators.concat(Iterators.single((builder, innerParam) -> builder.field(name)), value.toXContentChunked(params)); - } - public static Iterator array(String name, Iterator contents) { return Iterators.concat(ChunkedToXContentHelper.startArray(name), contents, ChunkedToXContentHelper.endArray()); } - public static Iterator wrapWithObject(String name, Iterator iterator) { - return Iterators.concat(startObject(name), iterator, endObject()); - } - /** * Creates an Iterator of a single ToXContent object that serializes the given object as a single chunk. Just wraps {@link * Iterators#single}, but still useful because it avoids any type ambiguity. diff --git a/server/src/main/java/org/elasticsearch/script/ScriptCacheStats.java b/server/src/main/java/org/elasticsearch/script/ScriptCacheStats.java index a9a89a3fa7610..adc1f65b88732 100644 --- a/server/src/main/java/org/elasticsearch/script/ScriptCacheStats.java +++ b/server/src/main/java/org/elasticsearch/script/ScriptCacheStats.java @@ -21,15 +21,8 @@ import java.util.Iterator; import java.util.Map; import java.util.Objects; +import java.util.function.Function; -import static org.elasticsearch.common.collect.Iterators.concat; -import static org.elasticsearch.common.collect.Iterators.flatMap; -import static org.elasticsearch.common.collect.Iterators.single; -import static org.elasticsearch.common.xcontent.ChunkedToXContentHelper.endArray; -import static org.elasticsearch.common.xcontent.ChunkedToXContentHelper.endObject; -import static org.elasticsearch.common.xcontent.ChunkedToXContentHelper.field; -import static org.elasticsearch.common.xcontent.ChunkedToXContentHelper.startArray; -import static org.elasticsearch.common.xcontent.ChunkedToXContentHelper.startObject; import static org.elasticsearch.script.ScriptCacheStats.Fields.SCRIPT_CACHE_STATS; // This class is deprecated in favor of ScriptStats and ScriptContextStats @@ -76,35 +69,25 @@ public void writeTo(StreamOutput out) throws IOException { @Override public Iterator toXContentChunked(ToXContent.Params outerParams) { - return concat( - startObject(SCRIPT_CACHE_STATS), - startObject(Fields.SUM), - general != null - ? concat( - field(ScriptStats.Fields.COMPILATIONS, general.getCompilations()), - field(ScriptStats.Fields.CACHE_EVICTIONS, general.getCacheEvictions()), - field(ScriptStats.Fields.COMPILATION_LIMIT_TRIGGERED, general.getCompilationLimitTriggered()), - endObject(), - endObject() - ) - : concat(single((builder, params) -> { - var sum = sum(); - return builder.field(ScriptStats.Fields.COMPILATIONS, sum.getCompilations()) - .field(ScriptStats.Fields.CACHE_EVICTIONS, sum.getCacheEvictions()) - .field(ScriptStats.Fields.COMPILATION_LIMIT_TRIGGERED, sum.getCompilationLimitTriggered()) - .endObject(); - }), startArray(Fields.CONTEXTS), flatMap(context.keySet().stream().sorted().iterator(), ctx -> { - var stats = context.get(ctx); - return concat( - startObject(), - field(Fields.CONTEXT, ctx), - field(ScriptStats.Fields.COMPILATIONS, stats.getCompilations()), - field(ScriptStats.Fields.CACHE_EVICTIONS, stats.getCacheEvictions()), - field(ScriptStats.Fields.COMPILATION_LIMIT_TRIGGERED, stats.getCompilationLimitTriggered()), - endObject() - ); - }), endArray(), endObject()) - ); + Function statsFields = s -> (b, p) -> b.field(ScriptStats.Fields.COMPILATIONS, s.getCompilations()) + .field(ScriptStats.Fields.CACHE_EVICTIONS, s.getCacheEvictions()) + .field(ScriptStats.Fields.COMPILATION_LIMIT_TRIGGERED, s.getCompilationLimitTriggered()); + + return ChunkedToXContent.builder(outerParams).object(SCRIPT_CACHE_STATS, sb -> { + if (general != null) { + sb.xContentObject(Fields.SUM, statsFields.apply(general)); + } else { + sb.xContentObject(Fields.SUM, statsFields.apply(sum())); + sb.array( + Fields.CONTEXTS, + context.entrySet().stream().sorted(Map.Entry.comparingByKey()).iterator(), + (eb, e) -> eb.object(ebo -> { + ebo.field(Fields.CONTEXT, e.getKey()); + ebo.append(statsFields.apply(e.getValue())); + }) + ); + } + }); } /** diff --git a/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java index 8adf18cd82f5c..67e5f30f023c9 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java @@ -313,11 +313,15 @@ private void assertXContent( fail(e); } - final var expectedChunks = Objects.equals(params.param("metric"), "none") - ? 2 - : 4 + ClusterStateTests.expectedChunkCount(params, response.getState()); + int[] expectedChunks = new int[] { 3 }; + if (Objects.equals(params.param("metric"), "none") == false) { + expectedChunks[0] += 2 + ClusterStateTests.expectedChunkCount(params, response.getState()); + } + if (params.paramAsBoolean("explain", false)) { + expectedChunks[0]++; + } - AbstractChunkedSerializingTestCase.assertChunkCount(response, params, ignored -> expectedChunks); + AbstractChunkedSerializingTestCase.assertChunkCount(response, params, o -> expectedChunks[0]); assertCriticalWarnings(criticalDeprecationWarnings); // check the v7 API too @@ -331,7 +335,7 @@ public Iterator toXContentChunked(ToXContent.Params outerP public boolean isFragment() { return response.isFragment(); } - }, params, ignored -> expectedChunks); + }, params, o -> expectedChunks[0]++); // the v7 API should not emit any deprecation warnings assertCriticalWarnings(); } diff --git a/server/src/test/java/org/elasticsearch/common/xcontent/ChunkedToXContentBuilderTests.java b/server/src/test/java/org/elasticsearch/common/xcontent/ChunkedToXContentBuilderTests.java new file mode 100644 index 0000000000000..ff811f5d6d736 --- /dev/null +++ b/server/src/test/java/org/elasticsearch/common/xcontent/ChunkedToXContentBuilderTests.java @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.common.xcontent; + +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.collect.Iterators; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xcontent.ToXContent; + +import java.util.function.IntFunction; +import java.util.stream.IntStream; + +import static org.hamcrest.Matchers.equalTo; + +public class ChunkedToXContentBuilderTests extends ESTestCase { + + public void testFieldWithInnerChunkedObject() { + + ToXContent innerXContent = (b, p) -> { + b.startObject(); + b.field("field1", 10); + b.field("field2", "aaa"); + b.endObject(); + return b; + }; + + ToXContent outerXContent = (b, p) -> b.field("field3", 10).field("field4", innerXContent); + + String expectedContent = Strings.toString(outerXContent); + + ChunkedToXContentObject innerChunkedContent = params -> new ChunkedToXContentBuilder(params).object( + o -> o.field("field1", 10).field("field2", "aaa") + ); + + ChunkedToXContent outerChunkedContent = params -> new ChunkedToXContentBuilder(params).field("field3", 10) + .field("field4", innerChunkedContent); + + assertThat(Strings.toString(outerChunkedContent), equalTo(expectedContent)); + } + + public void testFieldWithInnerChunkedArray() { + + ToXContent innerXContent = (b, p) -> { + b.startArray(); + b.value(10); + b.value(20); + b.endArray(); + return b; + }; + + ToXContent outerXContent = (b, p) -> b.field("field3", 10).field("field4", innerXContent); + + String expectedContent = Strings.toString(outerXContent); + + IntFunction value = v -> (b, p) -> b.value(v); + + ChunkedToXContentObject innerChunkedContent = params -> new ChunkedToXContentBuilder(params).array( + IntStream.of(10, 20).mapToObj(value).iterator() + ); + + ChunkedToXContent outerChunkedContent = params -> new ChunkedToXContentBuilder(params).field("field3", 10) + .field("field4", innerChunkedContent); + + assertThat(Strings.toString(outerChunkedContent), equalTo(expectedContent)); + } + + public void testFieldWithInnerChunkedField() { + + ToXContent innerXContent = (b, p) -> b.value(10); + ToXContent outerXContent = (b, p) -> b.field("field3", 10).field("field4", innerXContent); + + String expectedContent = Strings.toString(outerXContent); + + ChunkedToXContentObject innerChunkedContent = params -> Iterators.single((b, p) -> b.value(10)); + + ChunkedToXContent outerChunkedContent = params -> new ChunkedToXContentBuilder(params).field("field3", 10) + .field("field4", innerChunkedContent); + + assertThat(Strings.toString(outerChunkedContent), equalTo(expectedContent)); + } +} diff --git a/server/src/test/java/org/elasticsearch/common/xcontent/ChunkedToXContentHelperTests.java b/server/src/test/java/org/elasticsearch/common/xcontent/ChunkedToXContentHelperTests.java deleted file mode 100644 index 353725fbd0756..0000000000000 --- a/server/src/test/java/org/elasticsearch/common/xcontent/ChunkedToXContentHelperTests.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -package org.elasticsearch.common.xcontent; - -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.collect.Iterators; -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.xcontent.ToXContent; - -import java.util.Iterator; -import java.util.function.IntFunction; - -import static org.elasticsearch.xcontent.ToXContent.EMPTY_PARAMS; -import static org.hamcrest.Matchers.equalTo; - -public class ChunkedToXContentHelperTests extends ESTestCase { - - public void testFieldWithInnerChunkedObject() { - - ToXContent innerXContent = (builder, p) -> { - builder.startObject(); - builder.field("field1", 10); - builder.field("field2", "aaa"); - builder.endObject(); - return builder; - }; - - ToXContent outerXContent = (builder, p) -> { - builder.field("field3", 10); - builder.field("field4", innerXContent); - return builder; - }; - - var expectedContent = Strings.toString(outerXContent); - - ChunkedToXContentObject innerChunkedContent = params -> Iterators.concat( - ChunkedToXContentHelper.startObject(), - ChunkedToXContentHelper.field("field1", 10), - ChunkedToXContentHelper.field("field2", "aaa"), - ChunkedToXContentHelper.endObject() - ); - - ChunkedToXContent outerChunkedContent = params -> Iterators.concat( - ChunkedToXContentHelper.field("field3", 10), - ChunkedToXContentHelper.field("field4", innerChunkedContent, EMPTY_PARAMS) - ); - - assertThat(Strings.toString(outerChunkedContent), equalTo(expectedContent)); - } - - public void testFieldWithInnerChunkedArray() { - - ToXContent innerXContent = (builder, p) -> { - builder.startArray(); - builder.value(10); - builder.value(20); - builder.endArray(); - return builder; - }; - - ToXContent outerXContent = (builder, p) -> { - builder.field("field3", 10); - builder.field("field4", innerXContent); - return builder; - }; - - var expectedContent = Strings.toString(outerXContent); - - IntFunction> value = v -> Iterators.single(((builder, p) -> builder.value(v))); - - ChunkedToXContentObject innerChunkedContent = params -> Iterators.concat( - ChunkedToXContentHelper.startArray(), - value.apply(10), - value.apply(20), - ChunkedToXContentHelper.endArray() - ); - - ChunkedToXContent outerChunkedContent = params -> Iterators.concat( - ChunkedToXContentHelper.field("field3", 10), - ChunkedToXContentHelper.field("field4", innerChunkedContent, EMPTY_PARAMS) - ); - - assertThat(Strings.toString(outerChunkedContent), equalTo(expectedContent)); - } - - public void testFieldWithInnerChunkedField() { - - ToXContent innerXContent = (builder, p) -> { - builder.value(10); - return builder; - }; - - ToXContent outerXContent = (builder, p) -> { - builder.field("field3", 10); - builder.field("field4", innerXContent); - return builder; - }; - - var expectedContent = Strings.toString(outerXContent); - - IntFunction> value = v -> Iterators.single(((builder, p) -> builder.value(v))); - - ChunkedToXContentObject innerChunkedContent = params -> Iterators.single((builder, p) -> builder.value(10)); - - ChunkedToXContent outerChunkedContent = params -> Iterators.concat( - ChunkedToXContentHelper.field("field3", 10), - ChunkedToXContentHelper.field("field4", innerChunkedContent, EMPTY_PARAMS) - ); - - assertThat(Strings.toString(outerChunkedContent), equalTo(expectedContent)); - } -} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponse.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponse.java index 8e4da3f138a6f..3232f3a9118d4 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponse.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponse.java @@ -15,7 +15,6 @@ import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.common.xcontent.ChunkedToXContent; import org.elasticsearch.common.xcontent.ChunkedToXContentBuilder; -import org.elasticsearch.common.xcontent.ChunkedToXContentHelper; import org.elasticsearch.common.xcontent.ChunkedToXContentObject; import org.elasticsearch.compute.data.BlockFactory; import org.elasticsearch.compute.data.BlockStreamInput; @@ -30,7 +29,6 @@ import org.elasticsearch.xpack.esql.core.type.DataType; import java.io.IOException; -import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Objects; @@ -186,58 +184,35 @@ public EsqlExecutionInfo getExecutionInfo() { return executionInfo; } - private Iterator asyncPropertiesOrEmpty() { - if (isAsync) { - return ChunkedToXContentHelper.singleChunk((builder, params) -> { - if (asyncExecutionId != null) { - builder.field("id", asyncExecutionId); - } - builder.field("is_running", isRunning); - return builder; - }); - } else { - return Collections.emptyIterator(); - } - } - @Override public Iterator toXContentChunked(ToXContent.Params params) { - boolean dropNullColumns = params.paramAsBoolean(DROP_NULL_COLUMNS_OPTION, false); - boolean[] nullColumns = dropNullColumns ? nullColumns() : null; - - Iterator tookTime; - if (executionInfo != null && executionInfo.overallTook() != null) { - tookTime = ChunkedToXContentHelper.singleChunk((builder, p) -> { - builder.field("took", executionInfo.overallTook().millis()); - return builder; - }); - } else { - tookTime = Collections.emptyIterator(); - } + return ChunkedToXContent.builder(params).object(b -> { + boolean dropNullColumns = b.params().paramAsBoolean(DROP_NULL_COLUMNS_OPTION, false); + boolean[] nullColumns = dropNullColumns ? nullColumns() : null; - Iterator columnHeadings = dropNullColumns - ? Iterators.concat( - ResponseXContentUtils.allColumns(columns, "all_columns"), - ResponseXContentUtils.nonNullColumns(columns, nullColumns, "columns") - ) - : ResponseXContentUtils.allColumns(columns, "columns"); - Iterator valuesIt = ResponseXContentUtils.columnValues(this.columns, this.pages, columnar, nullColumns); - Iterator profileRender = profile == null - ? List.of().iterator() - : ChunkedToXContentHelper.field("profile", profile, params); - Iterator executionInfoRender = executionInfo == null || executionInfo.isCrossClusterSearch() == false - ? List.of().iterator() - : ChunkedToXContentHelper.field("_clusters", executionInfo, params); - return Iterators.concat( - ChunkedToXContentHelper.startObject(), - asyncPropertiesOrEmpty(), - tookTime, - columnHeadings, - ChunkedToXContentHelper.array("values", valuesIt), - executionInfoRender, - profileRender, - ChunkedToXContentHelper.endObject() - ); + if (isAsync) { + if (asyncExecutionId != null) { + b.field("id", asyncExecutionId); + } + b.field("is_running", isRunning); + } + if (executionInfo != null && executionInfo.overallTook() != null) { + b.field("took", executionInfo.overallTook().millis()); + } + if (dropNullColumns) { + b.append(ResponseXContentUtils.allColumns(columns, "all_columns")) + .append(ResponseXContentUtils.nonNullColumns(columns, nullColumns, "columns")); + } else { + b.append(ResponseXContentUtils.allColumns(columns, "columns")); + } + b.array("values", ResponseXContentUtils.columnValues(this.columns, this.pages, columnar, nullColumns)); + if (executionInfo != null && executionInfo.isCrossClusterSearch()) { + b.field("_clusters", executionInfo); + } + if (profile != null) { + b.field("profile", profile); + } + }); } private boolean[] nullColumns() { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponseTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponseTests.java index 7c0b6e6a2eaa3..abf03d4fe06dd 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponseTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/action/EsqlQueryResponseTests.java @@ -525,19 +525,19 @@ public void testChunkResponseSizeColumnar() { try (EsqlQueryResponse resp = randomResponseAsync(true, null, true)) { int columnCount = resp.pages().get(0).getBlockCount(); int bodySize = resp.pages().stream().mapToInt(p -> p.getPositionCount() * p.getBlockCount()).sum() + columnCount * 2; - assertChunkCount(resp, r -> 6 + sizeClusterDetails + bodySize); // is_running + assertChunkCount(resp, r -> 7 + sizeClusterDetails + bodySize); // is_running } } public void testChunkResponseSizeRows() { int sizeClusterDetails = 14; try (EsqlQueryResponse resp = randomResponse(false, null)) { - int bodySize = resp.pages().stream().mapToInt(p -> p.getPositionCount()).sum(); + int bodySize = resp.pages().stream().mapToInt(Page::getPositionCount).sum(); assertChunkCount(resp, r -> 5 + sizeClusterDetails + bodySize); } try (EsqlQueryResponse resp = randomResponseAsync(false, null, true)) { - int bodySize = resp.pages().stream().mapToInt(p -> p.getPositionCount()).sum(); - assertChunkCount(resp, r -> 6 + sizeClusterDetails + bodySize); + int bodySize = resp.pages().stream().mapToInt(Page::getPositionCount).sum(); + assertChunkCount(resp, r -> 7 + sizeClusterDetails + bodySize); } } diff --git a/x-pack/plugin/shutdown/src/main/java/org/elasticsearch/xpack/shutdown/SingleNodeShutdownStatus.java b/x-pack/plugin/shutdown/src/main/java/org/elasticsearch/xpack/shutdown/SingleNodeShutdownStatus.java index 39bf9e78b3b01..810bd8f6e9ceb 100644 --- a/x-pack/plugin/shutdown/src/main/java/org/elasticsearch/xpack/shutdown/SingleNodeShutdownStatus.java +++ b/x-pack/plugin/shutdown/src/main/java/org/elasticsearch/xpack/shutdown/SingleNodeShutdownStatus.java @@ -12,11 +12,10 @@ import org.elasticsearch.cluster.metadata.ShutdownShardMigrationStatus; import org.elasticsearch.cluster.metadata.SingleNodeShutdownMetadata; import org.elasticsearch.common.Strings; -import org.elasticsearch.common.collect.Iterators; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.Writeable; -import org.elasticsearch.common.xcontent.ChunkedToXContentHelper; +import org.elasticsearch.common.xcontent.ChunkedToXContent; import org.elasticsearch.common.xcontent.ChunkedToXContentObject; import org.elasticsearch.xcontent.ParseField; import org.elasticsearch.xcontent.ToXContent; @@ -25,10 +24,6 @@ import java.util.Iterator; import java.util.Objects; -import static org.elasticsearch.common.xcontent.ChunkedToXContentHelper.endObject; -import static org.elasticsearch.common.xcontent.ChunkedToXContentHelper.singleChunk; -import static org.elasticsearch.common.xcontent.ChunkedToXContentHelper.startObject; - public class SingleNodeShutdownStatus implements Writeable, ChunkedToXContentObject { private final SingleNodeShutdownMetadata metadata; @@ -116,26 +111,27 @@ public String toString() { @Override public Iterator toXContentChunked(ToXContent.Params params) { - return Iterators.concat(startObject(), singleChunk((builder, p) -> { - builder.field(SingleNodeShutdownMetadata.NODE_ID_FIELD.getPreferredName(), metadata.getNodeId()); - builder.field(SingleNodeShutdownMetadata.TYPE_FIELD.getPreferredName(), metadata.getType()); - builder.field(SingleNodeShutdownMetadata.REASON_FIELD.getPreferredName(), metadata.getReason()); - if (metadata.getAllocationDelay() != null) { - builder.field( - SingleNodeShutdownMetadata.ALLOCATION_DELAY_FIELD.getPreferredName(), - metadata.getAllocationDelay().getStringRep() + return ChunkedToXContent.builder(params).object(b -> { + b.append((builder, p) -> { + builder.field(SingleNodeShutdownMetadata.NODE_ID_FIELD.getPreferredName(), metadata.getNodeId()); + builder.field(SingleNodeShutdownMetadata.TYPE_FIELD.getPreferredName(), metadata.getType()); + builder.field(SingleNodeShutdownMetadata.REASON_FIELD.getPreferredName(), metadata.getReason()); + if (metadata.getAllocationDelay() != null) { + builder.field( + SingleNodeShutdownMetadata.ALLOCATION_DELAY_FIELD.getPreferredName(), + metadata.getAllocationDelay().getStringRep() + ); + } + builder.timeField( + SingleNodeShutdownMetadata.STARTED_AT_MILLIS_FIELD.getPreferredName(), + SingleNodeShutdownMetadata.STARTED_AT_READABLE_FIELD, + metadata.getStartedAtMillis() ); - } - builder.timeField( - SingleNodeShutdownMetadata.STARTED_AT_MILLIS_FIELD.getPreferredName(), - SingleNodeShutdownMetadata.STARTED_AT_READABLE_FIELD, - metadata.getStartedAtMillis() - ); - builder.field(STATUS.getPreferredName(), overallStatus()); - return builder; - }), - ChunkedToXContentHelper.field(SHARD_MIGRATION_FIELD.getPreferredName(), shardMigrationStatus, params), - singleChunk((builder, p) -> { + builder.field(STATUS.getPreferredName(), overallStatus()); + return builder; + }); + b.field(SHARD_MIGRATION_FIELD.getPreferredName(), shardMigrationStatus); + b.append((builder, p) -> { builder.field(PERSISTENT_TASKS_FIELD.getPreferredName(), persistentTasksStatus); builder.field(PLUGINS_STATUS.getPreferredName(), pluginsStatus); if (metadata.getTargetNodeName() != null) { @@ -148,8 +144,7 @@ public Iterator toXContentChunked(ToXContent.Params params ); } return builder; - }), - endObject() - ); + }); + }); } }