Skip to content

Commit cd25958

Browse files
authored
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: #124613 (comment)
1 parent 73f0693 commit cd25958

File tree

1 file changed

+92
-75
lines changed
  • server/src/main/java/org/elasticsearch/cluster/metadata

1 file changed

+92
-75
lines changed

server/src/main/java/org/elasticsearch/cluster/metadata/Metadata.java

Lines changed: 92 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -683,11 +683,19 @@ public static Metadata fromXContent(XContentParser parser) throws IOException {
683683

684684
@Override
685685
public Iterator<? extends ToXContent> toXContentChunked(ToXContent.Params p) {
686-
XContentContext context = XContentContext.from(p);
686+
final XContentContext context = XContentContext.from(p);
687687
final Iterator<? extends ToXContent> start = context == XContentContext.API
688688
? ChunkedToXContentHelper.startObject("metadata")
689689
: Iterators.single((builder, params) -> builder.startObject("meta-data").field("version", version()));
690690

691+
final Iterator<? extends ToXContent> clusterCoordination = Iterators.single((builder, params) -> {
692+
builder.field("cluster_uuid", clusterUUID);
693+
builder.field("cluster_uuid_committed", clusterUUIDCommitted);
694+
builder.startObject("cluster_coordination");
695+
coordinationMetadata().toXContent(builder, params);
696+
return builder.endObject();
697+
});
698+
691699
final Iterator<? extends ToXContent> persistentSettings = context != XContentContext.API && persistentSettings().isEmpty() == false
692700
? Iterators.single((builder, params) -> {
693701
builder.startObject("settings");
@@ -696,89 +704,98 @@ public Iterator<? extends ToXContent> toXContentChunked(ToXContent.Params p) {
696704
})
697705
: Collections.emptyIterator();
698706

699-
// use a tree map so the order is deterministic
700-
Map<String, ReservedStateMetadata> clusterReservedState = new TreeMap<>(reservedStateMetadata);
701-
702707
@FixForMultiProject
703708
// Need to revisit whether this should be a param or something else.
704709
final boolean multiProject = p.paramAsBoolean("multi-project", false);
705710
if (multiProject) {
706-
return Iterators.concat(start, Iterators.single((builder, params) -> {
707-
builder.field("cluster_uuid", clusterUUID);
708-
builder.field("cluster_uuid_committed", clusterUUIDCommitted);
709-
builder.startObject("cluster_coordination");
710-
coordinationMetadata().toXContent(builder, params);
711-
return builder.endObject();
712-
}),
713-
persistentSettings,
714-
ChunkedToXContentHelper.array(
715-
"projects",
716-
Iterators.flatMap(
717-
projectMetadata.entrySet().iterator(),
718-
e -> Iterators.concat(
719-
ChunkedToXContentHelper.startObject(),
720-
Iterators.single((builder, params) -> builder.field("id", e.getKey())),
721-
e.getValue().toXContentChunked(p),
722-
ChunkedToXContentHelper.endObject()
723-
)
724-
)
725-
),
726-
Iterators.flatMap(
727-
customs.entrySet().iterator(),
728-
entry -> entry.getValue().context().contains(context)
729-
? ChunkedToXContentHelper.object(entry.getKey(), entry.getValue().toXContentChunked(p))
730-
: Collections.emptyIterator()
731-
),
732-
ChunkedToXContentHelper.object("reserved_state", reservedStateMetadata().values().iterator()),
733-
ChunkedToXContentHelper.endObject()
734-
);
711+
return toXContentChunkedWithMultiProjectFormat(p, context, start, clusterCoordination, persistentSettings);
735712
} else {
736-
if (projectMetadata.size() != 1) {
737-
throw new MultiProjectPendingException("There are multiple projects " + projectMetadata.keySet());
738-
}
739-
// Need to rethink what to do here. This might be right, but maybe not...
740-
@FixForMultiProject
741-
final ProjectMetadata project = projectMetadata.values().iterator().next();
742-
743-
// need to combine reserved state together into a single block so we don't get duplicate keys
744-
// and not include it in the project xcontent output (through the lack of multi-project params)
745-
clusterReservedState.putAll(project.reservedStateMetadata());
746-
747-
// Similarly, combine cluster and project persistent tasks and report them under a single key
748-
Iterator<ToXContent> customs = Iterators.flatMap(customs().entrySet().iterator(), entry -> {
749-
if (entry.getValue().context().contains(context)
750-
&& ClusterPersistentTasksCustomMetadata.TYPE.equals(entry.getKey()) == false) {
751-
return ChunkedToXContentHelper.object(entry.getKey(), entry.getValue().toXContentChunked(p));
752-
} else {
753-
return Collections.emptyIterator();
754-
}
755-
});
756-
final var combinedTasks = PersistentTasksCustomMetadata.combine(
757-
ClusterPersistentTasksCustomMetadata.get(this),
758-
PersistentTasksCustomMetadata.get(project)
759-
);
760-
if (combinedTasks != null) {
761-
customs = Iterators.concat(
762-
customs,
763-
ChunkedToXContentHelper.object(PersistentTasksCustomMetadata.TYPE, combinedTasks.toXContentChunked(p))
764-
);
765-
}
713+
return toXContentChunkedWithSingleProjectFormat(p, context, start, clusterCoordination, persistentSettings);
714+
}
715+
}
766716

767-
final var iterators = Iterators.concat(start, Iterators.single((builder, params) -> {
768-
builder.field("cluster_uuid", clusterUUID);
769-
builder.field("cluster_uuid_committed", clusterUUIDCommitted);
770-
builder.startObject("cluster_coordination");
771-
coordinationMetadata().toXContent(builder, params);
772-
return builder.endObject();
773-
}),
774-
persistentSettings,
775-
project.toXContentChunked(p),
717+
private Iterator<? extends ToXContent> toXContentChunkedWithMultiProjectFormat(
718+
ToXContent.Params p,
719+
XContentContext context,
720+
Iterator<? extends ToXContent> start,
721+
Iterator<? extends ToXContent> clusterCoordination,
722+
Iterator<? extends ToXContent> persistentSettings
723+
) {
724+
return Iterators.concat(
725+
start,
726+
clusterCoordination,
727+
persistentSettings,
728+
ChunkedToXContentHelper.array(
729+
"projects",
730+
Iterators.flatMap(
731+
projectMetadata.entrySet().iterator(),
732+
e -> Iterators.concat(
733+
ChunkedToXContentHelper.startObject(),
734+
Iterators.single((builder, params) -> builder.field("id", e.getKey())),
735+
e.getValue().toXContentChunked(p),
736+
ChunkedToXContentHelper.endObject()
737+
)
738+
)
739+
),
740+
Iterators.flatMap(
741+
customs.entrySet().iterator(),
742+
entry -> entry.getValue().context().contains(context)
743+
? ChunkedToXContentHelper.object(entry.getKey(), entry.getValue().toXContentChunked(p))
744+
: Collections.emptyIterator()
745+
),
746+
ChunkedToXContentHelper.object("reserved_state", reservedStateMetadata().values().iterator()),
747+
ChunkedToXContentHelper.endObject()
748+
);
749+
}
750+
751+
private Iterator<? extends ToXContent> toXContentChunkedWithSingleProjectFormat(
752+
ToXContent.Params p,
753+
XContentContext context,
754+
Iterator<? extends ToXContent> start,
755+
Iterator<? extends ToXContent> clusterCoordination,
756+
Iterator<? extends ToXContent> persistentSettings
757+
) {
758+
if (projectMetadata.size() != 1) {
759+
throw new MultiProjectPendingException("There are multiple projects " + projectMetadata.keySet());
760+
}
761+
// Need to rethink what to do here. This might be right, but maybe not...
762+
@FixForMultiProject
763+
final ProjectMetadata project = projectMetadata.values().iterator().next();
764+
765+
// need to combine reserved state together into a single block so we don't get duplicate keys
766+
// and not include it in the project xcontent output (through the lack of multi-project params)
767+
// use a tree map so the order is deterministic
768+
final Map<String, ReservedStateMetadata> clusterReservedState = new TreeMap<>(reservedStateMetadata);
769+
clusterReservedState.putAll(project.reservedStateMetadata());
770+
771+
// Similarly, combine cluster and project persistent tasks and report them under a single key
772+
Iterator<ToXContent> customs = Iterators.flatMap(customs().entrySet().iterator(), entry -> {
773+
if (entry.getValue().context().contains(context) && ClusterPersistentTasksCustomMetadata.TYPE.equals(entry.getKey()) == false) {
774+
return ChunkedToXContentHelper.object(entry.getKey(), entry.getValue().toXContentChunked(p));
775+
} else {
776+
return Collections.emptyIterator();
777+
}
778+
});
779+
final var combinedTasks = PersistentTasksCustomMetadata.combine(
780+
ClusterPersistentTasksCustomMetadata.get(this),
781+
PersistentTasksCustomMetadata.get(project)
782+
);
783+
if (combinedTasks != null) {
784+
customs = Iterators.concat(
776785
customs,
777-
ChunkedToXContentHelper.object("reserved_state", clusterReservedState.values().iterator()),
778-
ChunkedToXContentHelper.endObject()
786+
ChunkedToXContentHelper.object(PersistentTasksCustomMetadata.TYPE, combinedTasks.toXContentChunked(p))
779787
);
780-
return iterators;
781788
}
789+
790+
return Iterators.concat(
791+
start,
792+
clusterCoordination,
793+
persistentSettings,
794+
project.toXContentChunked(p),
795+
customs,
796+
ChunkedToXContentHelper.object("reserved_state", clusterReservedState.values().iterator()),
797+
ChunkedToXContentHelper.endObject()
798+
);
782799
}
783800

784801
private static final DiffableUtils.KeySerializer<ProjectId> PROJECT_ID_SERIALIZER = DiffableUtils.getWriteableKeySerializer(

0 commit comments

Comments
 (0)