3636import org .elasticsearch .common .xcontent .ChunkedToXContent ;
3737import org .elasticsearch .common .xcontent .ChunkedToXContentHelper ;
3838import org .elasticsearch .common .xcontent .XContentParserUtils ;
39- import org .elasticsearch .core .Assertions ;
4039import org .elasticsearch .core .FixForMultiProject ;
4140import org .elasticsearch .core .Nullable ;
4241import org .elasticsearch .core .Tuple ;
@@ -1662,19 +1661,12 @@ public Metadata build() {
16621661 }
16631662
16641663 public Metadata build (boolean skipNameCollisionChecks ) {
1665- if (projectMetadata .isEmpty ()) {
1666- createDefaultProject ();
1667- } else if (Assertions .ENABLED ) {
1668- projectMetadata .forEach ((id , project ) -> {
1669- assert project .getId ().equals (id ) : "project id mismatch key=[" + id + "] builder=[" + project .getId () + "]" ;
1670- });
1671- }
16721664 return new Metadata (
16731665 clusterUUID ,
16741666 clusterUUIDCommitted ,
16751667 version ,
16761668 coordinationMetadata ,
1677- Collections . unmodifiableMap ( Maps . transformValues ( projectMetadata , m -> m . build ( skipNameCollisionChecks )) ),
1669+ buildProjectMetadata ( skipNameCollisionChecks ),
16781670 transientSettings ,
16791671 persistentSettings ,
16801672 Settings .builder ().put (persistentSettings ).put (transientSettings ).build (),
@@ -1684,10 +1676,32 @@ public Metadata build(boolean skipNameCollisionChecks) {
16841676 );
16851677 }
16861678
1679+ private Map <ProjectId , ProjectMetadata > buildProjectMetadata (boolean skipNameCollisionChecks ) {
1680+ if (projectMetadata .isEmpty ()) {
1681+ createDefaultProject ();
1682+ }
1683+ assert assertProjectIdAndProjectMetadataConsistency ();
1684+ if (projectMetadata .size () == 1 ) {
1685+ final var entry = projectMetadata .entrySet ().iterator ().next ();
1686+ // Map.of() with a single entry is highly optimized
1687+ // so we want take advantage of that performance boost for this common case of a single project
1688+ return Map .of (entry .getKey (), entry .getValue ().build (skipNameCollisionChecks ));
1689+ } else {
1690+ return Collections .unmodifiableMap (Maps .transformValues (projectMetadata , m -> m .build (skipNameCollisionChecks )));
1691+ }
1692+ }
1693+
16871694 private ProjectMetadata .Builder createDefaultProject () {
16881695 return projectMetadata .put (DEFAULT_PROJECT_ID , new ProjectMetadata .Builder (Map .of (), 0 ).id (DEFAULT_PROJECT_ID ));
16891696 }
16901697
1698+ private boolean assertProjectIdAndProjectMetadataConsistency () {
1699+ projectMetadata .forEach ((id , project ) -> {
1700+ assert project .getId ().equals (id ) : "project id mismatch key=[" + id + "] builder=[" + project .getId () + "]" ;
1701+ });
1702+ return true ;
1703+ }
1704+
16911705 /**
16921706 * There are a set of specific custom sections that have moved from top-level sections to project-level sections
16931707 * as part of the multi-project refactor. Enumerate them here so we can move them to the right place
0 commit comments