Quellcode durchsuchen

Refactor Metadata.toXContent by extracting methods (#124689)

The method is long and has two distinct paths for multi-project and
single-project formats. This PR extracts separate method for each of the
code paths for readability.

See also:
https://github.com/elastic/elasticsearch/pull/124613#discussion_r1990981472
Yang Wang vor 7 Monaten
Ursprung
Commit
cd25958700
1 geänderte Dateien mit 92 neuen und 75 gelöschten Zeilen
  1. 92 75
      server/src/main/java/org/elasticsearch/cluster/metadata/Metadata.java

+ 92 - 75
server/src/main/java/org/elasticsearch/cluster/metadata/Metadata.java

@@ -683,11 +683,19 @@ public class Metadata implements Diffable<Metadata>, ChunkedToXContent {
 
     @Override
     public Iterator<? extends ToXContent> toXContentChunked(ToXContent.Params p) {
-        XContentContext context = XContentContext.from(p);
+        final XContentContext context = XContentContext.from(p);
         final Iterator<? extends ToXContent> start = context == XContentContext.API
             ? ChunkedToXContentHelper.startObject("metadata")
             : Iterators.single((builder, params) -> builder.startObject("meta-data").field("version", version()));
 
+        final Iterator<? extends ToXContent> clusterCoordination = Iterators.single((builder, params) -> {
+            builder.field("cluster_uuid", clusterUUID);
+            builder.field("cluster_uuid_committed", clusterUUIDCommitted);
+            builder.startObject("cluster_coordination");
+            coordinationMetadata().toXContent(builder, params);
+            return builder.endObject();
+        });
+
         final Iterator<? extends ToXContent> persistentSettings = context != XContentContext.API && persistentSettings().isEmpty() == false
             ? Iterators.single((builder, params) -> {
                 builder.startObject("settings");
@@ -696,89 +704,98 @@ public class Metadata implements Diffable<Metadata>, ChunkedToXContent {
             })
             : Collections.emptyIterator();
 
-        // use a tree map so the order is deterministic
-        Map<String, ReservedStateMetadata> clusterReservedState = new TreeMap<>(reservedStateMetadata);
-
         @FixForMultiProject
         // Need to revisit whether this should be a param or something else.
         final boolean multiProject = p.paramAsBoolean("multi-project", false);
         if (multiProject) {
-            return Iterators.concat(start, Iterators.single((builder, params) -> {
-                builder.field("cluster_uuid", clusterUUID);
-                builder.field("cluster_uuid_committed", clusterUUIDCommitted);
-                builder.startObject("cluster_coordination");
-                coordinationMetadata().toXContent(builder, params);
-                return builder.endObject();
-            }),
-                persistentSettings,
-                ChunkedToXContentHelper.array(
-                    "projects",
-                    Iterators.flatMap(
-                        projectMetadata.entrySet().iterator(),
-                        e -> Iterators.concat(
-                            ChunkedToXContentHelper.startObject(),
-                            Iterators.single((builder, params) -> builder.field("id", e.getKey())),
-                            e.getValue().toXContentChunked(p),
-                            ChunkedToXContentHelper.endObject()
-                        )
-                    )
-                ),
-                Iterators.flatMap(
-                    customs.entrySet().iterator(),
-                    entry -> entry.getValue().context().contains(context)
-                        ? ChunkedToXContentHelper.object(entry.getKey(), entry.getValue().toXContentChunked(p))
-                        : Collections.emptyIterator()
-                ),
-                ChunkedToXContentHelper.object("reserved_state", reservedStateMetadata().values().iterator()),
-                ChunkedToXContentHelper.endObject()
-            );
+            return toXContentChunkedWithMultiProjectFormat(p, context, start, clusterCoordination, persistentSettings);
         } else {
-            if (projectMetadata.size() != 1) {
-                throw new MultiProjectPendingException("There are multiple projects " + projectMetadata.keySet());
-            }
-            // Need to rethink what to do here. This might be right, but maybe not...
-            @FixForMultiProject
-            final ProjectMetadata project = projectMetadata.values().iterator().next();
-
-            // need to combine reserved state together into a single block so we don't get duplicate keys
-            // and not include it in the project xcontent output (through the lack of multi-project params)
-            clusterReservedState.putAll(project.reservedStateMetadata());
-
-            // Similarly, combine cluster and project persistent tasks and report them under a single key
-            Iterator<ToXContent> customs = Iterators.flatMap(customs().entrySet().iterator(), entry -> {
-                if (entry.getValue().context().contains(context)
-                    && ClusterPersistentTasksCustomMetadata.TYPE.equals(entry.getKey()) == false) {
-                    return ChunkedToXContentHelper.object(entry.getKey(), entry.getValue().toXContentChunked(p));
-                } else {
-                    return Collections.emptyIterator();
-                }
-            });
-            final var combinedTasks = PersistentTasksCustomMetadata.combine(
-                ClusterPersistentTasksCustomMetadata.get(this),
-                PersistentTasksCustomMetadata.get(project)
-            );
-            if (combinedTasks != null) {
-                customs = Iterators.concat(
-                    customs,
-                    ChunkedToXContentHelper.object(PersistentTasksCustomMetadata.TYPE, combinedTasks.toXContentChunked(p))
-                );
-            }
+            return toXContentChunkedWithSingleProjectFormat(p, context, start, clusterCoordination, persistentSettings);
+        }
+    }
 
-            final var iterators = Iterators.concat(start, Iterators.single((builder, params) -> {
-                builder.field("cluster_uuid", clusterUUID);
-                builder.field("cluster_uuid_committed", clusterUUIDCommitted);
-                builder.startObject("cluster_coordination");
-                coordinationMetadata().toXContent(builder, params);
-                return builder.endObject();
-            }),
-                persistentSettings,
-                project.toXContentChunked(p),
+    private Iterator<? extends ToXContent> toXContentChunkedWithMultiProjectFormat(
+        ToXContent.Params p,
+        XContentContext context,
+        Iterator<? extends ToXContent> start,
+        Iterator<? extends ToXContent> clusterCoordination,
+        Iterator<? extends ToXContent> persistentSettings
+    ) {
+        return Iterators.concat(
+            start,
+            clusterCoordination,
+            persistentSettings,
+            ChunkedToXContentHelper.array(
+                "projects",
+                Iterators.flatMap(
+                    projectMetadata.entrySet().iterator(),
+                    e -> Iterators.concat(
+                        ChunkedToXContentHelper.startObject(),
+                        Iterators.single((builder, params) -> builder.field("id", e.getKey())),
+                        e.getValue().toXContentChunked(p),
+                        ChunkedToXContentHelper.endObject()
+                    )
+                )
+            ),
+            Iterators.flatMap(
+                customs.entrySet().iterator(),
+                entry -> entry.getValue().context().contains(context)
+                    ? ChunkedToXContentHelper.object(entry.getKey(), entry.getValue().toXContentChunked(p))
+                    : Collections.emptyIterator()
+            ),
+            ChunkedToXContentHelper.object("reserved_state", reservedStateMetadata().values().iterator()),
+            ChunkedToXContentHelper.endObject()
+        );
+    }
+
+    private Iterator<? extends ToXContent> toXContentChunkedWithSingleProjectFormat(
+        ToXContent.Params p,
+        XContentContext context,
+        Iterator<? extends ToXContent> start,
+        Iterator<? extends ToXContent> clusterCoordination,
+        Iterator<? extends ToXContent> persistentSettings
+    ) {
+        if (projectMetadata.size() != 1) {
+            throw new MultiProjectPendingException("There are multiple projects " + projectMetadata.keySet());
+        }
+        // Need to rethink what to do here. This might be right, but maybe not...
+        @FixForMultiProject
+        final ProjectMetadata project = projectMetadata.values().iterator().next();
+
+        // need to combine reserved state together into a single block so we don't get duplicate keys
+        // and not include it in the project xcontent output (through the lack of multi-project params)
+        // use a tree map so the order is deterministic
+        final Map<String, ReservedStateMetadata> clusterReservedState = new TreeMap<>(reservedStateMetadata);
+        clusterReservedState.putAll(project.reservedStateMetadata());
+
+        // Similarly, combine cluster and project persistent tasks and report them under a single key
+        Iterator<ToXContent> customs = Iterators.flatMap(customs().entrySet().iterator(), entry -> {
+            if (entry.getValue().context().contains(context) && ClusterPersistentTasksCustomMetadata.TYPE.equals(entry.getKey()) == false) {
+                return ChunkedToXContentHelper.object(entry.getKey(), entry.getValue().toXContentChunked(p));
+            } else {
+                return Collections.emptyIterator();
+            }
+        });
+        final var combinedTasks = PersistentTasksCustomMetadata.combine(
+            ClusterPersistentTasksCustomMetadata.get(this),
+            PersistentTasksCustomMetadata.get(project)
+        );
+        if (combinedTasks != null) {
+            customs = Iterators.concat(
                 customs,
-                ChunkedToXContentHelper.object("reserved_state", clusterReservedState.values().iterator()),
-                ChunkedToXContentHelper.endObject()
+                ChunkedToXContentHelper.object(PersistentTasksCustomMetadata.TYPE, combinedTasks.toXContentChunked(p))
             );
-            return iterators;
         }
+
+        return Iterators.concat(
+            start,
+            clusterCoordination,
+            persistentSettings,
+            project.toXContentChunked(p),
+            customs,
+            ChunkedToXContentHelper.object("reserved_state", clusterReservedState.values().iterator()),
+            ChunkedToXContentHelper.endObject()
+        );
     }
 
     private static final DiffableUtils.KeySerializer<ProjectId> PROJECT_ID_SERIALIZER = DiffableUtils.getWriteableKeySerializer(