parentLoop: for()

in controlplane/src/core/repositories/FederatedGraphRepository.ts [1503:1781]


      parentLoop: for (const federatedGraph of federatedGraphs) {
        // Get published subgraphs for recomposition of the federated graph
        const subgraphs = await subgraphRepo.listByFederatedGraph({
          federatedGraphTargetId: federatedGraph.targetId,
          published: true,
        });

        const contracts = await contractRepo.bySourceFederatedGraphId(federatedGraph.id);
        const tagOptionsByContractName = new Map<string, ContractTagOptions>();
        for (const contract of contracts) {
          tagOptionsByContractName.set(
            contract.downstreamFederatedGraph.target.name,
            newContractTagOptionsFromArrays(contract.excludeTags, contract.includeTags),
          );
        }

        const baseCompositionSubgraphs = subgraphs.map((s) => ({
          name: s.name,
          url: s.routingUrl,
          definitions: parse(s.schemaSDL),
        }));

        // Collects the base graph and applicable feature flag related graphs
        const allSubgraphsToCompose: SubgraphsToCompose[] = await featureFlagRepo.getSubgraphsToCompose({
          baseSubgraphs: subgraphs,
          baseCompositionSubgraphs,
          fedGraphLabelMatchers: federatedGraph.labelMatchers,
        });

        /* baseCompositionData contains the router execution config and the schema version ID for the source graph
         * base composition (not a contract or feature flag composition)
         * */
        const baseCompositionData: BaseCompositionData = {
          featureFlagRouterExecutionConfigByFeatureFlagName: new Map<string, FeatureFlagRouterExecutionConfig>(),
        };

        /* Map of the contract base composition schema version ID, router execution config,
         * and any feature flag schema version IDs by contract ID */
        const contractBaseCompositionDataByContractId = new Map<string, ContractBaseCompositionData>();

        for (const subgraphsToCompose of allSubgraphsToCompose) {
          const result: FederationResult | FederationResultWithContracts = getFederationResultWithPotentialContracts(
            federatedGraph,
            subgraphsToCompose,
            tagOptionsByContractName,
          );

          if (!result.success) {
            // Collect all composition errors
            allCompositionErrors.push(
              ...result.errors.map((e) => ({
                federatedGraphName: federatedGraph.name,
                namespace: federatedGraph.namespace,
                message: e.message,
                featureFlag: subgraphsToCompose.featureFlagName || '',
              })),
            );
          }

          // Collect all composition warnings
          allCompositionWarnings.push(
            ...result.warnings.map((w) => ({
              federatedGraphName: federatedGraph.name,
              namespace: federatedGraph.namespace,
              message: w.message,
              featureFlag: subgraphsToCompose.featureFlagName || '',
            })),
          );

          if (!subgraphsToCompose.isFeatureFlagComposition && !result.success && !federatedGraph.contract) {
            allCompositionErrors.push(unsuccessfulBaseCompositionError(federatedGraph.name, federatedGraph.namespace));
          }

          const composedGraph = mapResultToComposedGraph(federatedGraph, subgraphsToCompose.subgraphs, result);

          const federatedSchemaVersionId = randomUUID();

          // Build the router execution config if the composed schema is valid
          const routerExecutionConfig = buildRouterExecutionConfig(
            composedGraph,
            federatedSchemaVersionId,
            federatedGraph.routerCompatibilityVersion,
          );

          const baseComposition = await composer.saveComposition({
            composedGraph,
            composedById: actorId,
            isFeatureFlagComposition: subgraphsToCompose.isFeatureFlagComposition,
            federatedSchemaVersionId,
            routerExecutionConfig,
            featureFlagId: subgraphsToCompose.featureFlagId,
          });

          if (!result.success || !baseComposition.schemaVersionId || !routerExecutionConfig) {
            /* If the base composition failed to compose or deploy, return to the parent loop, because
             * contracts are not composed if the base composition fails.
             */
            if (!subgraphsToCompose.isFeatureFlagComposition) {
              continue parentLoop;
            }
            // Record the feature flag composition to upload (if there are no errors)
          } else if (subgraphsToCompose.isFeatureFlagComposition) {
            baseCompositionData.featureFlagRouterExecutionConfigByFeatureFlagName.set(
              subgraphsToCompose.featureFlagName,
              routerConfigToFeatureFlagExecutionConfig(routerExecutionConfig),
            );
            // Otherwise, this is the base composition, so store the schema version id
          } else {
            baseCompositionData.schemaVersionId = baseComposition.schemaVersionId;
            baseCompositionData.routerExecutionConfig = routerExecutionConfig;
          }

          // If there are no contracts, there is nothing further to do
          if (!('federationResultByContractName' in result)) {
            continue;
          }

          for (const [contractName, contractResult] of result.federationResultByContractName) {
            const contractGraph = await fedGraphRepo.byName(contractName, federatedGraph.namespace);
            if (!contractGraph) {
              throw new Error(`The contract graph "${contractName}" was not found.`);
            }
            if (!contractResult.success) {
              allCompositionErrors.push(
                ...contractResult.errors.map((e) => ({
                  federatedGraphName: contractGraph.name,
                  namespace: contractGraph.namespace,
                  message: e.message,
                  featureFlag: subgraphsToCompose.featureFlagName,
                })),
              );
            }

            allCompositionWarnings.push(
              ...contractResult.warnings.map((w) => ({
                federatedGraphName: contractGraph.name,
                namespace: contractGraph.namespace,
                message: w.message,
                featureFlag: subgraphsToCompose.featureFlagName,
              })),
            );

            const composedContract = mapResultToComposedGraph(
              contractGraph,
              subgraphsToCompose.subgraphs,
              contractResult,
            );

            const contractSchemaVersionId = randomUUID();

            // Build the router execution config if the composed schema is valid
            const contractRouterExecutionConfig = buildRouterExecutionConfig(
              composedContract,
              contractSchemaVersionId,
              federatedGraph.routerCompatibilityVersion,
            );

            const contractComposition = await composer.saveComposition({
              composedGraph: composedContract,
              composedById: actorId,
              isFeatureFlagComposition: subgraphsToCompose.isFeatureFlagComposition,
              federatedSchemaVersionId: contractSchemaVersionId,
              routerExecutionConfig: contractRouterExecutionConfig,
              featureFlagId: subgraphsToCompose.featureFlagId,
            });

            if (!contractResult.success || !contractComposition.schemaVersionId || !contractRouterExecutionConfig) {
              continue;
            }

            /* If the base composition for which this contract has been made is NOT a feature flag composition,
             * it must be the contract base composition, which must always be uploaded.
             * The base composition is always the first item in the subgraphsToCompose array.
             * */
            if (!subgraphsToCompose.isFeatureFlagComposition) {
              contractBaseCompositionDataByContractId.set(contractGraph.id, {
                schemaVersionId: contractComposition.schemaVersionId,
                routerExecutionConfig: contractRouterExecutionConfig,
                featureFlagRouterExecutionConfigByFeatureFlagName: new Map<string, FeatureFlagRouterExecutionConfig>(),
              });
              continue;
            }

            /* If the contract has a feature flag, get the current array feature flag versions (or set a new one),
             * and then push the current schema version to the array
             * */
            const existingContractBaseCompositionData = contractBaseCompositionDataByContractId.get(contractGraph.id);
            /* If the existingContractSchemaVersions is undefined, it means the contract base composition failed.
             * In this case, simply continue, because when iterating a feature flag for the source graph composition,
             * there may not be any errors for the feature flag.
             * */
            if (!existingContractBaseCompositionData) {
              continue;
            }
            existingContractBaseCompositionData.featureFlagRouterExecutionConfigByFeatureFlagName.set(
              subgraphsToCompose.featureFlagName,
              routerConfigToFeatureFlagExecutionConfig(contractRouterExecutionConfig),
            );
          }
        }

        const federatedGraphDTO = await this.byId(federatedGraph.id);
        if (!federatedGraphDTO) {
          throw new Error(`Fatal:The federated graph "${federatedGraph.name}" was not found.`);
        }
        if (!baseCompositionData.routerExecutionConfig) {
          throw new Error(
            `Fatal: The latest router execution config for federated graph "${federatedGraph.name}" was not generated.`,
          );
        }
        if (!baseCompositionData.schemaVersionId) {
          throw new Error(
            `Fatal: The latest base composition for federated graph "${federatedGraph.name}" was not found.`,
          );
        }

        const { errors: uploadErrors } = await composer.composeAndUploadRouterConfig({
          federatedGraphId: federatedGraphDTO.id,
          featureFlagRouterExecutionConfigByFeatureFlagName:
            baseCompositionData.featureFlagRouterExecutionConfigByFeatureFlagName,
          blobStorage,
          organizationId: this.organizationId,
          admissionConfig: {
            cdnBaseUrl: admissionConfig.cdnBaseUrl,
            jwtSecret: admissionConfig.webhookJWTSecret,
          },
          baseCompositionRouterExecutionConfig: baseCompositionData.routerExecutionConfig,
          baseCompositionSchemaVersionId: baseCompositionData.schemaVersionId,
          federatedGraphAdmissionWebhookURL: federatedGraphDTO.admissionWebhookURL,
          federatedGraphAdmissionWebhookSecret: federatedGraphDTO.admissionWebhookSecret,
          actorId,
        });

        allDeploymentErrors.push(
          ...uploadErrors
            .filter((e) => e instanceof AdmissionError || e instanceof RouterConfigUploadError)
            .map((e) => ({
              federatedGraphName: federatedGraph.name,
              namespace: federatedGraph.namespace,
              message: e.message ?? '',
            })),
        );

        for (const [
          contractId,
          { featureFlagRouterExecutionConfigByFeatureFlagName, schemaVersionId, routerExecutionConfig },
        ] of contractBaseCompositionDataByContractId) {
          const contractDTO = await this.byId(contractId);
          if (!contractDTO) {
            throw new Error(`Unexpected: Contract graph with id "${contractId}" not found after latest composition`);
          }

          const { errors: uploadErrors } = await composer.composeAndUploadRouterConfig({
            admissionConfig: {
              cdnBaseUrl: admissionConfig.cdnBaseUrl,
              jwtSecret: admissionConfig.webhookJWTSecret,
            },
            baseCompositionRouterExecutionConfig: routerExecutionConfig,
            baseCompositionSchemaVersionId: schemaVersionId,
            blobStorage,
            featureFlagRouterExecutionConfigByFeatureFlagName,
            federatedGraphId: contractDTO.id,
            organizationId: this.organizationId,
            federatedGraphAdmissionWebhookURL: contractDTO.admissionWebhookURL,
            federatedGraphAdmissionWebhookSecret: contractDTO.admissionWebhookSecret,
            actorId,
          });

          allDeploymentErrors.push(
            ...uploadErrors
              .filter((e) => e instanceof AdmissionError || e instanceof RouterConfigUploadError)
              .map((e) => ({
                federatedGraphName: federatedGraph.name,
                namespace: federatedGraph.namespace,
                message: e.message ?? '',
              })),
          );
        }
      }