Skip to content

Commit 2763ad6

Browse files
committed
Add optimized updateSingleProject on Metadata
For legacy reasons, `Metadata.Builder` contains a map of `ProjectMetadata.Builder`s instead of a map of `ProjectMetadata`s. While the plan is still to change that, there is a significant amount of refactoring that needs to be done before we can make that change. We have seen regressions in benchmarks due to this extra conversion of project metadata -> builder -> project metadata. We add a method that allows updating a single project without having to convert all the projects to builders first.
1 parent 9f78d11 commit 2763ad6

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

server/src/main/java/org/elasticsearch/cluster/ClusterState.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1005,7 +1005,7 @@ public ClusterState copyAndUpdateMetadata(Consumer<Metadata.Builder> updater) {
10051005
}
10061006

10071007
public ClusterState copyAndUpdateProject(ProjectId projectId, Consumer<ProjectMetadata.Builder> updater) {
1008-
return copyAndUpdate(builder -> builder.putProjectMetadata(metadata().getProject(projectId).copyAndUpdate(updater)));
1008+
return copyAndUpdate(builder -> builder.metadata(metadata.copyAndUpdateProject(projectId, updater)));
10091009
}
10101010

10111011
@SuppressForbidden(reason = "directly reading ClusterState#clusterFeatures")

server/src/main/java/org/elasticsearch/cluster/ProjectState.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,14 @@ public int hashCode() {
7373
public ClusterState updatedState(Consumer<ProjectMetadata.Builder> projectBuilderConsumer) {
7474
ProjectMetadata.Builder projectBuilder = ProjectMetadata.builder(metadata());
7575
projectBuilderConsumer.accept(projectBuilder);
76-
return ClusterState.builder(cluster).putProjectMetadata(projectBuilder).build();
76+
return updatedState(projectBuilder.build());
7777
}
7878

7979
/**
8080
* Build a new {@link ClusterState} with the updated project.
8181
*/
8282
public ClusterState updatedState(ProjectMetadata updatedProject) {
83-
return ClusterState.builder(cluster).putProjectMetadata(updatedProject).build();
83+
return ClusterState.builder(cluster).metadata(cluster.metadata().updateSingleProject(updatedProject)).build();
8484
}
8585

8686
/**
@@ -100,6 +100,6 @@ public ProjectState updateProject(ProjectMetadata updatedProject) {
100100
)
101101
);
102102
}
103-
return new ProjectState(ClusterState.builder(cluster).putProjectMetadata(updatedProject).build(), project);
103+
return new ProjectState(updatedState(updatedProject), project);
104104
}
105105
}

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,42 @@ private Metadata updateSingleProject(Function<ProjectMetadata, ProjectMetadata>
404404
}
405405
}
406406

407+
/**
408+
* Updates a single project in the metadata. This offers a more performant way of updating a single project compared to the Builder.
409+
*/
410+
public Metadata updateSingleProject(ProjectMetadata updatedProject) {
411+
final var existingProject = projectMetadata.get(updatedProject.id());
412+
if (existingProject == null) {
413+
throw new IllegalArgumentException(
414+
"Can only update existing project, cannot update new project [" + updatedProject.id() + "]. Use the builder instead"
415+
);
416+
}
417+
if (updatedProject == existingProject) {
418+
return this;
419+
}
420+
final Map<ProjectId, ProjectMetadata> updatedMap;
421+
if (projects().size() == 1) {
422+
updatedMap = Map.of(updatedProject.id(), updatedProject);
423+
} else {
424+
final var hashMap = new HashMap<>(projectMetadata);
425+
hashMap.put(updatedProject.id(), updatedProject);
426+
updatedMap = Collections.unmodifiableMap(hashMap);
427+
}
428+
return new Metadata(
429+
clusterUUID,
430+
clusterUUIDCommitted,
431+
version,
432+
coordinationMetadata,
433+
updatedMap,
434+
transientSettings,
435+
persistentSettings,
436+
settings,
437+
hashesOfConsistentSettings,
438+
customs,
439+
reservedStateMetadata
440+
);
441+
}
442+
407443
public long version() {
408444
return this.version;
409445
}
@@ -1487,6 +1523,13 @@ public Metadata copyAndUpdate(Consumer<Builder> updater) {
14871523
return builder.build();
14881524
}
14891525

1526+
public Metadata copyAndUpdateProject(ProjectId projectId, Consumer<ProjectMetadata.Builder> updater) {
1527+
final var existingProject = projectMetadata.get(projectId);
1528+
final var builder = ProjectMetadata.builder(existingProject);
1529+
updater.accept(builder);
1530+
return updateSingleProject(builder.build());
1531+
}
1532+
14901533
public static class Builder {
14911534

14921535
private String clusterUUID;

0 commit comments

Comments
 (0)