@finos/legend-graph 32.5.1 → 32.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/lib/graph/metamodel/pure/dataProduct/DataProduct.d.ts +4 -3
  2. package/lib/graph/metamodel/pure/dataProduct/DataProduct.d.ts.map +1 -1
  3. package/lib/graph/metamodel/pure/dataProduct/DataProduct.js +7 -5
  4. package/lib/graph/metamodel/pure/dataProduct/DataProduct.js.map +1 -1
  5. package/lib/graph-manager/AbstractPureGraphManager.d.ts +1 -0
  6. package/lib/graph-manager/AbstractPureGraphManager.d.ts.map +1 -1
  7. package/lib/graph-manager/AbstractPureGraphManager.js.map +1 -1
  8. package/lib/graph-manager/action/analytics/data-product/DataProductAnalysis.d.ts +4 -4
  9. package/lib/graph-manager/action/analytics/data-product/DataProductAnalysis.d.ts.map +1 -1
  10. package/lib/graph-manager/action/analytics/data-product/DataProductAnalysis.js.map +1 -1
  11. package/lib/graph-manager/action/query/Query.d.ts +2 -0
  12. package/lib/graph-manager/action/query/Query.d.ts.map +1 -1
  13. package/lib/graph-manager/action/query/Query.js +2 -0
  14. package/lib/graph-manager/action/query/Query.js.map +1 -1
  15. package/lib/graph-manager/protocol/pure/v1/V1_PureGraphManager.d.ts +22 -1
  16. package/lib/graph-manager/protocol/pure/v1/V1_PureGraphManager.d.ts.map +1 -1
  17. package/lib/graph-manager/protocol/pure/v1/V1_PureGraphManager.js +289 -102
  18. package/lib/graph-manager/protocol/pure/v1/V1_PureGraphManager.js.map +1 -1
  19. package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineHelper.d.ts.map +1 -1
  20. package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineHelper.js +3 -0
  21. package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineHelper.js.map +1 -1
  22. package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineServerClient.d.ts +1 -0
  23. package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineServerClient.d.ts.map +1 -1
  24. package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineServerClient.js +2 -0
  25. package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineServerClient.js.map +1 -1
  26. package/lib/graph-manager/protocol/pure/v1/engine/V1_GraphManagerEngine.d.ts +1 -0
  27. package/lib/graph-manager/protocol/pure/v1/engine/V1_GraphManagerEngine.d.ts.map +1 -1
  28. package/lib/graph-manager/protocol/pure/v1/engine/V1_RemoteEngine.d.ts +1 -0
  29. package/lib/graph-manager/protocol/pure/v1/engine/V1_RemoteEngine.d.ts.map +1 -1
  30. package/lib/graph-manager/protocol/pure/v1/engine/V1_RemoteEngine.js +3 -0
  31. package/lib/graph-manager/protocol/pure/v1/engine/V1_RemoteEngine.js.map +1 -1
  32. package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_MappingModelCoverageAnalysis.d.ts.map +1 -1
  33. package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_MappingModelCoverageAnalysis.js +7 -0
  34. package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_MappingModelCoverageAnalysis.js.map +1 -1
  35. package/lib/graph-manager/protocol/pure/v1/engine/query/V1_Query.d.ts +2 -1
  36. package/lib/graph-manager/protocol/pure/v1/engine/query/V1_Query.d.ts.map +1 -1
  37. package/lib/graph-manager/protocol/pure/v1/engine/query/V1_Query.js +3 -1
  38. package/lib/graph-manager/protocol/pure/v1/engine/query/V1_Query.js.map +1 -1
  39. package/lib/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DataProductBuilder.d.ts +1 -1
  40. package/lib/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DataProductBuilder.d.ts.map +1 -1
  41. package/lib/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DataProductBuilder.js +6 -6
  42. package/lib/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DataProductBuilder.js.map +1 -1
  43. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_PureProtocolSerialization.d.ts.map +1 -1
  44. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_PureProtocolSerialization.js +14 -10
  45. package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_PureProtocolSerialization.js.map +1 -1
  46. package/lib/package.json +1 -1
  47. package/package.json +3 -3
  48. package/src/graph/metamodel/pure/dataProduct/DataProduct.ts +13 -5
  49. package/src/graph-manager/AbstractPureGraphManager.ts +4 -0
  50. package/src/graph-manager/action/analytics/data-product/DataProductAnalysis.ts +11 -4
  51. package/src/graph-manager/action/query/Query.ts +2 -0
  52. package/src/graph-manager/protocol/pure/v1/V1_PureGraphManager.ts +690 -499
  53. package/src/graph-manager/protocol/pure/v1/engine/V1_EngineHelper.ts +3 -0
  54. package/src/graph-manager/protocol/pure/v1/engine/V1_EngineServerClient.ts +12 -0
  55. package/src/graph-manager/protocol/pure/v1/engine/V1_GraphManagerEngine.ts +5 -0
  56. package/src/graph-manager/protocol/pure/v1/engine/V1_RemoteEngine.ts +10 -0
  57. package/src/graph-manager/protocol/pure/v1/engine/analytics/V1_MappingModelCoverageAnalysis.ts +7 -0
  58. package/src/graph-manager/protocol/pure/v1/engine/query/V1_Query.ts +3 -1
  59. package/src/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DataProductBuilder.ts +6 -3
  60. package/src/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_PureProtocolSerialization.ts +21 -23
@@ -17,6 +17,8 @@ import { GRAPH_MANAGER_EVENT } from '../../../../__lib__/GraphManagerEvent.js';
17
17
  import { CORE_PURE_PATH, PackageableElementPointerType, } from '../../../../graph/MetaModelConst.js';
18
18
  import { ActionState, TracerService, LogEvent, getClass, guaranteeNonNullable, UnsupportedOperationError, assertErrorThrown, promisify, StopWatch, isNonNullable, filterByType, isString, assertNonEmptyString, uniq, guaranteeType, guaranteeNonEmptyString, uuid, } from '@finos/legend-shared';
19
19
  import { AbstractPureGraphManager, } from '../../../../graph-manager/AbstractPureGraphManager.js';
20
+ import { Mapping } from '../../../../graph/metamodel/pure/packageableElements/mapping/Mapping.js';
21
+ import { PackageableRuntime } from '../../../../graph/metamodel/pure/packageableElements/runtime/PackageableRuntime.js';
20
22
  import { PureModel, } from '../../../../graph/PureModel.js';
21
23
  import { RawLambda } from '../../../../graph/metamodel/pure/rawValueSpecification/RawLambda.js';
22
24
  import { ServiceRegistrationSuccess, ServiceRegistrationFail, } from '../../../../graph-manager/action/service/ServiceRegistrationResult.js';
@@ -125,7 +127,7 @@ import { V1_INTERNAL__UnknownElement } from './model/packageableElements/V1_INTE
125
127
  import { V1_HostedService } from './model/packageableElements/function/V1_HostedService.js';
126
128
  import { V1_UserListOwnership } from './model/packageableElements/service/V1_ServiceOwnership.js';
127
129
  import { V1_PureSingleExecution } from './model/packageableElements/service/V1_ServiceExecution.js';
128
- import { V1_RuntimePointer, } from './model/packageableElements/runtime/V1_Runtime.js';
130
+ import { V1_EngineRuntime, V1_RuntimePointer, } from './model/packageableElements/runtime/V1_Runtime.js';
129
131
  import { V1_buildDebugTestsResult } from './engine/test/V1_DebugTestsResult.js';
130
132
  import { V1_CompleteCodeInput } from './engine/compilation/V1_CompleteCodeInput.js';
131
133
  import { V1_QueryParameterValue } from './engine/query/V1_Query.js';
@@ -134,7 +136,7 @@ import { V1_buildFunctionSignature, V1_createGenericTypeWithElementPath, } from
134
136
  import { V1_DataProduct } from './model/packageableElements/dataProduct/V1_DataProduct.js';
135
137
  import { V1_DataProductArtifact, V1_ModelAccessPointGroupInfo, } from './lakehouse/deploy/V1_DataProductArtifact.js';
136
138
  import { DataProductAnalysisQueryResult, DataProductAnalysis, } from '../../../action/analytics/data-product/DataProductAnalysis.js';
137
- import { DataProductAccessType, ModelAccessPointGroup, NativeModelAccess, NativeModelExecutionContext, } from '../../../../graph/metamodel/pure/dataProduct/DataProduct.js';
139
+ import { AccessPointGroup, DataProductAccessType, DataProductElementScope, LakehouseAccessPoint, ModelAccessPointGroup, NativeModelAccess, NativeModelExecutionContext, } from '../../../../graph/metamodel/pure/dataProduct/DataProduct.js';
138
140
  import { V1_MemSQLFunction } from './model/packageableElements/function/V1_MemSQLFunction.js';
139
141
  import { LineageModel } from '../../../../graph/metamodel/pure/lineage/LineageModel.js';
140
142
  import { V1_LineageInput, } from './model/lineage/V1_Lineage.js';
@@ -143,6 +145,11 @@ import { V1_DevMetadataPushRequest, V1_MetadataRequestOptions, V1_MetadatProject
143
145
  import { IngestDefinition } from '../../../../graph/metamodel/pure/packageableElements/ingest/IngestDefinition.js';
144
146
  import { Database } from '../../../../graph/metamodel/pure/packageableElements/store/relational/model/Database.js';
145
147
  import { V1_createAccessorFromPackageableElement } from './helpers/V1_AccessorHelper.js';
148
+ /**
149
+ * Number of elements to process synchronously before yielding to the event loop.
150
+ * This avoids per-element setTimeout overhead while keeping the UI responsive.
151
+ */
152
+ const GRAPH_BUILDER_BATCH_SIZE = 100;
146
153
  class V1_PureModelContextDataIndex {
147
154
  elements = [];
148
155
  nativeElements = [];
@@ -694,82 +701,122 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
694
701
  // this way, as we build the a graph, we know the next step's duplication check
695
702
  // has path cache consisting of all element from its base graphs
696
703
  const elementPathCache = new Set(graph.allElements.map((el) => el.path));
697
- await Promise.all(inputs.flatMap(async (input) => {
698
- // create the package cache
704
+ // NOTE: We must index ALL native elements across ALL inputs before indexing
705
+ // plugin-contributed ("other") elements. Plugin elements
706
+ // may resolve references to native elements (e.g. Mapping, Runtime) from
707
+ // other inputs during their first pass. If we process each input fully
708
+ // (native + other) before moving to the next, a plugin element in input[0]
709
+ // could fail to find a native element that only exists in input[1].
710
+ const packageCaches = new Map();
711
+ const createFirstPassBuilder = (input, packageCache, element) => new V1_ElementFirstPassBuilder(this.getBuilderContext(graph, input.model, element, options), packageCache, elementPathCache);
712
+ for (const input of inputs) {
699
713
  const packageCache = new Map();
700
- await Promise.all(input.data.nativeElements.map((element) => {
701
- return this.visitWithGraphBuilderErrorHandling(element, new V1_ElementFirstPassBuilder(this.getBuilderContext(graph, input.model, element, options), packageCache, elementPathCache));
702
- }));
703
- await Promise.all(this.graphBuilderExtensions.sortedExtraElementBuilders.flatMap((builder) => (input.data.otherElementsByBuilder.get(builder) ?? []).map((element) => {
704
- return this.visitWithGraphBuilderErrorHandling(element, new V1_ElementFirstPassBuilder(this.getBuilderContext(graph, input.model, element, options), packageCache, elementPathCache));
705
- })));
706
- }));
714
+ packageCaches.set(input, packageCache);
715
+ // Phase 1: index native elements for this input
716
+ await this.runBatchedLoop(input.data.nativeElements, (element) => this.visitWithGraphBuilderErrorHandling(element, createFirstPassBuilder(input, packageCache, element)));
717
+ }
718
+ // Phase 2: index other (plugin-contributed) elements across all inputs,
719
+ // now that all native elements have been indexed
720
+ for (const input of inputs) {
721
+ const packageCache = guaranteeNonNullable(packageCaches.get(input));
722
+ const otherElements = this.graphBuilderExtensions.sortedExtraElementBuilders.flatMap((builder) => input.data.otherElementsByBuilder.get(builder) ?? []);
723
+ await this.runBatchedLoop(otherElements, (element) => this.visitWithGraphBuilderErrorHandling(element, createFirstPassBuilder(input, packageCache, element)));
724
+ }
707
725
  }
708
726
  async buildTypes(graph, inputs, options) {
709
727
  // Second pass
710
- await Promise.all(inputs.flatMap((input) => input.data.profiles.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
711
- await Promise.all(inputs.flatMap((input) => input.data.classes.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
712
- await Promise.all(inputs.flatMap((input) => input.data.enumerations.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
713
- await Promise.all(inputs.flatMap((input) => input.data.measures.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
714
- await Promise.all(inputs.flatMap((input) => input.data.functions.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
728
+ await this.processElementsInBatches(graph, inputs, (data) => data.profiles, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
729
+ await this.processElementsInBatches(graph, inputs, (data) => data.classes, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
730
+ await this.processElementsInBatches(graph, inputs, (data) => data.enumerations, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
731
+ await this.processElementsInBatches(graph, inputs, (data) => data.measures, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
732
+ await this.processElementsInBatches(graph, inputs, (data) => data.functions, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
715
733
  // Third pass
716
- await Promise.all(inputs.flatMap((input) => input.data.classes.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementThirdPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
717
- await Promise.all(inputs.flatMap((input) => input.data.associations.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementThirdPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
734
+ await this.processElementsInBatches(graph, inputs, (data) => data.classes, (ctx) => new V1_ElementThirdPassBuilder(ctx), options);
735
+ await this.processElementsInBatches(graph, inputs, (data) => data.associations, (ctx) => new V1_ElementThirdPassBuilder(ctx), options);
718
736
  // Fourth Pass
719
- await Promise.all(inputs.flatMap((input) => input.data.classes.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementFourthPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
720
- await Promise.all(inputs.flatMap((input) => input.data.associations.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementFourthPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
737
+ await this.processElementsInBatches(graph, inputs, (data) => data.classes, (ctx) => new V1_ElementFourthPassBuilder(ctx), options);
738
+ await this.processElementsInBatches(graph, inputs, (data) => data.associations, (ctx) => new V1_ElementFourthPassBuilder(ctx), options);
721
739
  // Fifth pass
722
- await Promise.all(inputs.flatMap((input) => input.data.classes.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementFifthPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
740
+ await this.processElementsInBatches(graph, inputs, (data) => data.classes, (ctx) => new V1_ElementFifthPassBuilder(ctx), options);
723
741
  }
724
742
  async buildFunctionActivators(graph, inputs, options) {
725
- await Promise.all(inputs.flatMap((input) => input.data.functionActivators.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
743
+ await this.processElementsInBatches(graph, inputs, (data) => data.functionActivators, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
726
744
  }
727
745
  async buildStores(graph, inputs, options) {
728
- await Promise.all(inputs.flatMap((input) => input.data.stores.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
729
- await Promise.all(inputs.flatMap((input) => input.data.stores.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementThirdPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
730
- await Promise.all(inputs.flatMap((input) => input.data.stores.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementFourthPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
731
- await Promise.all(inputs.flatMap((input) => input.data.stores.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementFifthPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
746
+ await this.processElementsInBatches(graph, inputs, (data) => data.stores, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
747
+ await this.processElementsInBatches(graph, inputs, (data) => data.stores, (ctx) => new V1_ElementThirdPassBuilder(ctx), options);
748
+ await this.processElementsInBatches(graph, inputs, (data) => data.stores, (ctx) => new V1_ElementFourthPassBuilder(ctx), options);
749
+ await this.processElementsInBatches(graph, inputs, (data) => data.stores, (ctx) => new V1_ElementFifthPassBuilder(ctx), options);
732
750
  }
733
751
  async buildMappings(graph, inputs, options) {
734
- await Promise.all(inputs.flatMap((input) => input.data.mappings.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
735
- await Promise.all(inputs.flatMap((input) => input.data.mappings.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementThirdPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
736
- await Promise.all(inputs.flatMap((input) => input.data.mappings.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementFourthPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
752
+ await this.processElementsInBatches(graph, inputs, (data) => data.mappings, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
753
+ await this.processElementsInBatches(graph, inputs, (data) => data.mappings, (ctx) => new V1_ElementThirdPassBuilder(ctx), options);
754
+ await this.processElementsInBatches(graph, inputs, (data) => data.mappings, (ctx) => new V1_ElementFourthPassBuilder(ctx), options);
737
755
  }
738
756
  async buildConnectionsAndRuntimes(graph, inputs, options) {
739
757
  // NOTE: connections must be built before runtimes
740
- await Promise.all(inputs.flatMap((input) => input.data.connections.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
741
- await Promise.all(inputs.flatMap((input) => input.data.runtimes.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
758
+ await this.processElementsInBatches(graph, inputs, (data) => data.connections, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
759
+ await this.processElementsInBatches(graph, inputs, (data) => data.runtimes, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
742
760
  }
743
761
  async buildServices(graph, inputs, options) {
744
- await Promise.all(inputs.flatMap((input) => input.data.services.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
745
- await Promise.all(inputs.flatMap((input) => input.data.executionEnvironments.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
762
+ await this.processElementsInBatches(graph, inputs, (data) => data.services, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
763
+ await this.processElementsInBatches(graph, inputs, (data) => data.executionEnvironments, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
746
764
  }
747
765
  async buildDataElements(graph, inputs, options) {
748
- await Promise.all(inputs.flatMap((input) => input.data.dataElements.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
766
+ await this.processElementsInBatches(graph, inputs, (data) => data.dataElements, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
749
767
  }
750
768
  async buildDataProducts(graph, inputs, options) {
751
- await Promise.all(inputs.flatMap((input) => input.data.products.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
769
+ await this.processElementsInBatches(graph, inputs, (data) => data.products, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
752
770
  }
753
771
  async buildFileGenerations(graph, inputs, options) {
754
- await Promise.all(inputs.flatMap((input) => input.data.fileGenerations.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
772
+ await this.processElementsInBatches(graph, inputs, (data) => data.fileGenerations, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
755
773
  }
756
774
  async buildGenerationSpecifications(graph, inputs, options) {
757
- await Promise.all(inputs.flatMap((input) => input.data.generationSpecifications.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
775
+ await this.processElementsInBatches(graph, inputs, (data) => data.generationSpecifications, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
758
776
  }
759
777
  async buildSectionIndices(graph, inputs, options) {
760
- await Promise.all(inputs.flatMap((input) => input.data.sectionIndices.map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
778
+ await this.processElementsInBatches(graph, inputs, (data) => data.sectionIndices, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
761
779
  }
762
780
  async buildOtherElements(graph, inputs, options) {
763
- await Promise.all(this.graphBuilderExtensions.sortedExtraElementBuilders.map(async (builder) => {
764
- await Promise.all(inputs.flatMap((input) => (input.data.otherElementsByBuilder.get(builder) ?? []).map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementSecondPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
765
- await Promise.all(inputs.flatMap((input) => (input.data.otherElementsByBuilder.get(builder) ?? []).map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementThirdPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
766
- await Promise.all(inputs.flatMap((input) => (input.data.otherElementsByBuilder.get(builder) ?? []).map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementFourthPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
767
- await Promise.all(inputs.flatMap((input) => (input.data.otherElementsByBuilder.get(builder) ?? []).map((element) => this.visitWithGraphBuilderErrorHandling(element, new V1_ElementFifthPassBuilder(this.getBuilderContext(graph, input.model, element, options))))));
768
- }));
781
+ for (const builder of this.graphBuilderExtensions
782
+ .sortedExtraElementBuilders) {
783
+ const getElements = (data) => data.otherElementsByBuilder.get(builder) ?? [];
784
+ await this.processElementsInBatches(graph, inputs, getElements, (ctx) => new V1_ElementSecondPassBuilder(ctx), options);
785
+ await this.processElementsInBatches(graph, inputs, getElements, (ctx) => new V1_ElementThirdPassBuilder(ctx), options);
786
+ await this.processElementsInBatches(graph, inputs, getElements, (ctx) => new V1_ElementFourthPassBuilder(ctx), options);
787
+ await this.processElementsInBatches(graph, inputs, getElements, (ctx) => new V1_ElementFifthPassBuilder(ctx), options);
788
+ }
789
+ }
790
+ /**
791
+ * Run a callback for each item in the array, processing items in batches
792
+ * of {@link GRAPH_BUILDER_BATCH_SIZE} and yielding to the event loop between
793
+ * batches to keep the UI responsive.
794
+ */
795
+ async runBatchedLoop(items, process) {
796
+ for (let i = 0; i < items.length; i += GRAPH_BUILDER_BATCH_SIZE) {
797
+ if (i > 0) {
798
+ await new Promise((resolve) => setTimeout(resolve, 0));
799
+ }
800
+ const end = Math.min(i + GRAPH_BUILDER_BATCH_SIZE, items.length);
801
+ for (let j = i; j < end; j++) {
802
+ process(guaranteeNonNullable(items[j]));
803
+ }
804
+ }
805
+ }
806
+ /**
807
+ * Process elements from inputs in batches, yielding to the event loop
808
+ * between batches to keep the UI responsive.
809
+ */
810
+ async processElementsInBatches(graph, inputs, getElements, createVisitor, options) {
811
+ const allItems = inputs.flatMap((input) => getElements(input.data).map((element) => ({
812
+ element,
813
+ model: input.model,
814
+ })));
815
+ await this.runBatchedLoop(allItems, (item) => this.visitWithGraphBuilderErrorHandling(item.element, createVisitor(this.getBuilderContext(graph, item.model, item.element, options))));
769
816
  }
770
817
  visitWithGraphBuilderErrorHandling(element, visitor) {
771
818
  try {
772
- return promisify(() => element.accept_PackageableElementVisitor(visitor));
819
+ return element.accept_PackageableElementVisitor(visitor);
773
820
  }
774
821
  catch (err) {
775
822
  assertErrorThrown(err);
@@ -1722,55 +1769,140 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1722
1769
  const artifact = V1_DataProductArtifact.serialization.fromJson(artifactJson);
1723
1770
  return this.buildDataProductAnalysis(artifact, dataProductPath, pureGraph, accessPointId, dataProductAccessType, projectInfo, graphReport);
1724
1771
  }
1772
+ resolveArtifactElements(elementPaths, pureGraph) {
1773
+ const scopes = [];
1774
+ for (const path of elementPaths) {
1775
+ const el = pureGraph.getNullableElement(path, true);
1776
+ if (el) {
1777
+ const scope = new DataProductElementScope();
1778
+ scope.element = PackageableElementExplicitReference.create(el);
1779
+ scopes.push(scope);
1780
+ }
1781
+ }
1782
+ return scopes;
1783
+ }
1725
1784
  async buildDataProductAnalysis(artifact, dataProductPath, pureGraph, accessPointId, dataProductAccessType, projectInfo, graphReport) {
1726
- // Collect all mapping generation infos from model access point groups and native model access
1727
- const allMappingGenInfos = new Map();
1785
+ switch (dataProductAccessType) {
1786
+ case DataProductAccessType.MODEL:
1787
+ return this.buildModelAccessDataProductAnalysis(artifact, dataProductPath, pureGraph, accessPointId, projectInfo, graphReport);
1788
+ case DataProductAccessType.NATIVE:
1789
+ return this.buildNativeAccessDataProductAnalysis(artifact, dataProductPath, pureGraph, accessPointId, projectInfo, graphReport);
1790
+ case DataProductAccessType.LAKEHOUSE:
1791
+ return this.buildLakehouseAccessDataProductAnalysis(artifact, dataProductPath, pureGraph, accessPointId, projectInfo, graphReport);
1792
+ default:
1793
+ throw new UnsupportedOperationError(`Unsupported data product access type: '${dataProductAccessType}'`);
1794
+ }
1795
+ }
1796
+ async buildModelAccessDataProductAnalysis(artifact, dataProductPath, pureGraph, accessPointId, projectInfo, graphReport) {
1728
1797
  const modelAccessPointGroups = artifact.accessPointGroups.filter((group) => group instanceof V1_ModelAccessPointGroupInfo);
1729
- for (const group of modelAccessPointGroups) {
1730
- allMappingGenInfos.set(group.mappingGeneration.path, group.mappingGeneration);
1798
+ const accessGroup = modelAccessPointGroups.find((g) => g.id === accessPointId);
1799
+ if (!accessGroup) {
1800
+ throw new Error(`Can't resolve access point '${accessPointId}' (type: ${DataProductAccessType.MODEL}) in data product '${dataProductPath}'`);
1801
+ }
1802
+ const mappingPath = accessGroup.mappingGeneration.path;
1803
+ return this.buildDataProductAnalysisCore(artifact, dataProductPath, pureGraph, mappingPath, accessGroup, undefined, // no resolved runtime path for MODEL access
1804
+ projectInfo, graphReport);
1805
+ }
1806
+ async buildNativeAccessDataProductAnalysis(artifact, dataProductPath, pureGraph, accessPointId, projectInfo, graphReport) {
1807
+ const nativeCtx = artifact.nativeModelAccess?.nativeModelExecutionContexts.find((ctx) => ctx.key === accessPointId);
1808
+ if (!nativeCtx) {
1809
+ throw new Error(`Can't resolve access point '${accessPointId}' (type: ${DataProductAccessType.NATIVE}) in data product '${dataProductPath}'`);
1810
+ }
1811
+ const mappingPath = nativeCtx.mapping;
1812
+ if (!mappingPath) {
1813
+ throw new Error(`Can't resolve mapping path for access point '${accessPointId}' (type: ${DataProductAccessType.NATIVE}) in data product '${dataProductPath}'`);
1814
+ }
1815
+ // Resolve runtime path for the native context
1816
+ const resolvedRuntimePath = nativeCtx.runtimeGeneration?.path;
1817
+ return this.buildDataProductAnalysisCore(artifact, dataProductPath, pureGraph, mappingPath, nativeCtx, resolvedRuntimePath, projectInfo, graphReport);
1818
+ }
1819
+ async buildLakehouseAccessDataProductAnalysis(artifact, dataProductPath, pureGraph, accessPointId, projectInfo, graphReport) {
1820
+ // Create a dummy data product element
1821
+ const dummyDataProduct = new V1_DataProduct();
1822
+ dummyDataProduct.package =
1823
+ extractPackagePathFromPath(dataProductPath) ?? '';
1824
+ dummyDataProduct.name = extractElementNameFromPath(dataProductPath);
1825
+ dummyDataProduct.title = artifact.dataProduct.title;
1826
+ dummyDataProduct.description = artifact.dataProduct.description;
1827
+ // Build graph with only the data product
1828
+ const graphEntities = [dummyDataProduct]
1829
+ .filter((el) => !pureGraph.getNullableElement(el.path, false))
1830
+ .map((el) => this.elementProtocolToEntity(el));
1831
+ await this.buildGraph(pureGraph, graphEntities, ActionState.create(), {
1832
+ origin: new LegendSDLC(projectInfo.groupId, projectInfo.artifactId, projectInfo.versionId),
1833
+ }, graphReport);
1834
+ const data = pureGraph.getDataProduct(dataProductPath);
1835
+ // Create access point groups with LakehouseAccessPoints from artifact data
1836
+ data.accessPointGroups = artifact.accessPointGroups
1837
+ .filter((groupInfo) => !(groupInfo instanceof V1_ModelAccessPointGroupInfo))
1838
+ .map((groupInfo) => {
1839
+ const apGroup = new AccessPointGroup();
1840
+ apGroup.id = groupInfo.id;
1841
+ apGroup.description = groupInfo.description;
1842
+ apGroup.accessPoints = groupInfo.accessPointImplementations.map((apImpl) => {
1843
+ const lakehouseAP = new LakehouseAccessPoint(apImpl.id, '', // targetEnvironment is not available in the artifact
1844
+ new RawLambda(undefined, undefined), apGroup);
1845
+ lakehouseAP.description = apImpl.description;
1846
+ return lakehouseAP;
1847
+ });
1848
+ return apGroup;
1849
+ });
1850
+ // Find the lakehouse access point matching the requested id
1851
+ const lakehouseResult = data.accessPointGroups
1852
+ .flatMap((group) => group.accessPoints)
1853
+ .find((ap) => ap instanceof LakehouseAccessPoint && ap.id === accessPointId);
1854
+ if (!lakehouseResult) {
1855
+ throw new Error(`Can't resolve lakehouse access point '${accessPointId}' in data product '${dataProductPath}'`);
1731
1856
  }
1857
+ const result = new DataProductAnalysis();
1858
+ result.path = dataProductPath;
1859
+ result.title = artifact.dataProduct.title;
1860
+ result.description = artifact.dataProduct.description;
1861
+ return new DataProductAnalysisQueryResult(undefined, result, lakehouseResult);
1862
+ }
1863
+ /**
1864
+ * Shared core logic for building data product analysis after the access type
1865
+ * specific resolution has been performed.
1866
+ */
1867
+ async buildDataProductAnalysisCore(artifact, dataProductPath, pureGraph, mappingPath, accessGroup, resolvedRuntimePath, projectInfo, graphReport) {
1868
+ const modelAccessPointGroups = artifact.accessPointGroups.filter((group) => group instanceof V1_ModelAccessPointGroupInfo);
1869
+ // Collect mapping generation infos from all sources
1870
+ const includedGenInfos = new Map();
1732
1871
  if (artifact.nativeModelAccess?.mappingGenerations) {
1733
1872
  for (const [path, genInfo] of artifact.nativeModelAccess
1734
1873
  .mappingGenerations) {
1735
- if (!allMappingGenInfos.has(path)) {
1736
- allMappingGenInfos.set(path, genInfo);
1737
- }
1874
+ includedGenInfos.set(path, genInfo);
1738
1875
  }
1739
1876
  }
1740
- // Resolve mapping path from accessPointId and dataProductAccessType
1741
- let mappingPath;
1742
- let accessGroup = undefined;
1743
- if (dataProductAccessType === DataProductAccessType.MODEL) {
1744
- const group = modelAccessPointGroups.find((g) => g.id === accessPointId);
1745
- if (group) {
1746
- mappingPath = group.mappingGeneration.path;
1747
- accessGroup = group;
1877
+ for (const group of modelAccessPointGroups) {
1878
+ if (!includedGenInfos.has(group.mappingGeneration.path)) {
1879
+ includedGenInfos.set(group.mappingGeneration.path, group.mappingGeneration);
1748
1880
  }
1749
1881
  }
1750
- else if (dataProductAccessType === DataProductAccessType.NATIVE) {
1751
- const nativeCtx = artifact.nativeModelAccess?.nativeModelExecutionContexts.find((ctx) => ctx.key === accessPointId);
1752
- if (nativeCtx) {
1753
- mappingPath = nativeCtx.mapping;
1754
- accessGroup = nativeCtx;
1882
+ const nativeRuntimePaths = new Map();
1883
+ if (artifact.nativeModelAccess?.nativeModelExecutionContexts) {
1884
+ for (const ctx of artifact.nativeModelAccess
1885
+ .nativeModelExecutionContexts) {
1886
+ const rtPath = ctx.runtimeGeneration?.path;
1887
+ if (rtPath) {
1888
+ nativeRuntimePaths.set(ctx.key, rtPath);
1889
+ }
1755
1890
  }
1756
1891
  }
1757
- if (!mappingPath) {
1758
- throw new Error(`Can't resolve mapping path for access point '${accessPointId}' (type: ${dataProductAccessType}) in data product '${dataProductPath}'`);
1759
- }
1760
- if (!accessGroup) {
1761
- throw new Error(`Can't resolve access group for access point '${accessPointId}' (type: ${dataProductAccessType}) in data product '${dataProductPath}'`);
1762
- }
1763
- // Build the minimal graph using ONLY the elements from the resolved mapping
1764
- const resolvedMappingGenInfo = mappingPath
1765
- ? allMappingGenInfos.get(mappingPath)
1766
- : undefined;
1767
- if (!resolvedMappingGenInfo) {
1768
- throw new Error(`Can't find mapping generation info for access point '${accessPointId}' (type: ${dataProductAccessType}) in data product '${dataProductPath}'`);
1892
+ // Only add a stub for the resolved mapping to the graph
1893
+ const resolvedMappingStub = new V1_Mapping();
1894
+ resolvedMappingStub.package = extractPackagePathFromPath(mappingPath) ?? '';
1895
+ resolvedMappingStub.name = extractElementNameFromPath(mappingPath);
1896
+ // Only add a runtime stub for the resolved native context (if applicable)
1897
+ let resolvedRuntimeStub;
1898
+ if (resolvedRuntimePath) {
1899
+ resolvedRuntimeStub = new V1_PackageableRuntime();
1900
+ resolvedRuntimeStub.package =
1901
+ extractPackagePathFromPath(resolvedRuntimePath) ?? '';
1902
+ resolvedRuntimeStub.name =
1903
+ extractElementNameFromPath(resolvedRuntimePath);
1904
+ resolvedRuntimeStub.runtimeValue = new V1_EngineRuntime();
1769
1905
  }
1770
- // Create a dummy mapping for the resolved mapping path
1771
- const dummyMapping = new V1_Mapping();
1772
- dummyMapping.package = extractPackagePathFromPath(mappingPath) ?? '';
1773
- dummyMapping.name = extractElementNameFromPath(mappingPath);
1774
1906
  // Create a dummy data product element
1775
1907
  const dummyDataProduct = new V1_DataProduct();
1776
1908
  dummyDataProduct.package =
@@ -1778,9 +1910,11 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1778
1910
  dummyDataProduct.name = extractElementNameFromPath(dataProductPath);
1779
1911
  dummyDataProduct.title = artifact.dataProduct.title;
1780
1912
  dummyDataProduct.description = artifact.dataProduct.description;
1781
- // Build the minimal graph from the resolved mapping's model elements + dummy mapping + dummy data product
1782
- const graphEntities = resolvedMappingGenInfo.model.elements
1783
- .concat([dummyMapping])
1913
+ // Only load model elements for the resolved mapping
1914
+ const allModelElements = includedGenInfos.get(mappingPath)?.model.elements ?? [];
1915
+ const graphEntities = allModelElements
1916
+ .concat(resolvedMappingStub)
1917
+ .concat(resolvedRuntimeStub ? [resolvedRuntimeStub] : [])
1784
1918
  .concat(dummyDataProduct)
1785
1919
  .filter((el) => !pureGraph.getNullableElement(el.path, false))
1786
1920
  .map((el) => this.elementProtocolToEntity(el));
@@ -1788,30 +1922,74 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
1788
1922
  origin: new LegendSDLC(projectInfo.groupId, projectInfo.artifactId, projectInfo.versionId),
1789
1923
  }, graphReport);
1790
1924
  const data = pureGraph.getDataProduct(dataProductPath);
1791
- // build access point group
1792
1925
  let exec;
1926
+ if (artifact.nativeModelAccess?.defaultExecutionContext &&
1927
+ artifact.nativeModelAccess.nativeModelExecutionContexts.length) {
1928
+ const na = new NativeModelAccess();
1929
+ na.nativeModelExecutionContexts =
1930
+ artifact.nativeModelAccess.nativeModelExecutionContexts.map((ctxInfo) => {
1931
+ const ctx = new NativeModelExecutionContext();
1932
+ ctx.key = ctxInfo.key;
1933
+ const ctxMappingPath = ctxInfo.mapping;
1934
+ const ctxMapping = ctxMappingPath === mappingPath
1935
+ ? pureGraph.getMapping(ctxMappingPath)
1936
+ : new Mapping(ctxMappingPath);
1937
+ ctx.mapping =
1938
+ PackageableElementExplicitReference.create(ctxMapping);
1939
+ const rtPath = nativeRuntimePaths.get(ctxInfo.key);
1940
+ if (rtPath) {
1941
+ const ctxRuntime = rtPath === resolvedRuntimePath
1942
+ ? pureGraph.getRuntime(rtPath)
1943
+ : new PackageableRuntime(rtPath);
1944
+ ctx.runtime =
1945
+ PackageableElementExplicitReference.create(ctxRuntime);
1946
+ }
1947
+ ctx.__owner = na;
1948
+ return ctx;
1949
+ });
1950
+ const defaultExecutionContext = na.nativeModelExecutionContexts.find((ctx) => ctx.key === artifact.nativeModelAccess?.defaultExecutionContext);
1951
+ if (!defaultExecutionContext) {
1952
+ throw new Error(`Can't find execution context matching default context in '${dataProductPath}'`);
1953
+ }
1954
+ na.defaultExecutionContext = defaultExecutionContext;
1955
+ na.featuredElements = this.resolveArtifactElements(artifact.nativeModelAccess.elements, pureGraph);
1956
+ data.nativeModelAccess = na;
1957
+ }
1958
+ if (modelAccessPointGroups.length > 0) {
1959
+ data.accessPointGroups = modelAccessPointGroups.map((groupInfo) => {
1960
+ const group = new ModelAccessPointGroup();
1961
+ group.id = groupInfo.id;
1962
+ const groupMappingPath = groupInfo.mappingGeneration.path;
1963
+ const groupMapping = groupMappingPath === mappingPath
1964
+ ? pureGraph.getMapping(groupMappingPath)
1965
+ : new Mapping(groupMappingPath);
1966
+ group.mapping =
1967
+ PackageableElementExplicitReference.create(groupMapping);
1968
+ group.featuredElements = this.resolveArtifactElements(groupInfo.elements, pureGraph);
1969
+ return group;
1970
+ });
1971
+ }
1972
+ // Resolve the target exec state
1793
1973
  if (accessGroup instanceof V1_ModelAccessPointGroupInfo) {
1794
- const group = new ModelAccessPointGroup();
1795
- group.id = accessGroup.id;
1796
- data.accessPointGroups = [group];
1797
- group.mapping = PackageableElementExplicitReference.create(pureGraph.getMapping(mappingPath));
1798
- exec = group;
1974
+ exec = data.accessPointGroups.find((g) => g instanceof ModelAccessPointGroup && g.id === accessGroup.id);
1799
1975
  }
1800
1976
  else {
1801
- const nativeAccess = new NativeModelExecutionContext();
1802
- nativeAccess.key = accessGroup.key;
1803
- nativeAccess.mapping = PackageableElementExplicitReference.create(pureGraph.getMapping(mappingPath));
1804
- const na = new NativeModelAccess();
1805
- na.nativeModelExecutionContexts = [nativeAccess];
1806
- data.nativeModelAccess = na;
1807
- exec = nativeAccess;
1977
+ exec = data.nativeModelAccess?.nativeModelExecutionContexts.find((ctx) => ctx.key === accessGroup.key);
1978
+ }
1979
+ if (!exec) {
1980
+ throw new Error(`Can't find execution matching access id in '${dataProductPath}'`);
1808
1981
  }
1809
- // Build MappingModelCoverageAnalysisResult for the resolved mapping only
1982
+ // Build MappingModelCoverageAnalysisResult for all included mappings
1810
1983
  const mappingToMappingCoverageResult = new Map();
1811
- const v1Result = new V1_MappingModelCoverageAnalysisResult();
1812
- v1Result.mappedEntities = resolvedMappingGenInfo.mappedEntities;
1813
- v1Result.model = resolvedMappingGenInfo.model;
1814
- mappingToMappingCoverageResult.set(mappingPath, V1_buildModelCoverageAnalysisResult(v1Result, this, pureGraph.getMapping(mappingPath), resolvedMappingGenInfo.model));
1984
+ for (const [mPath, genInfo] of includedGenInfos) {
1985
+ const v1Result = new V1_MappingModelCoverageAnalysisResult();
1986
+ v1Result.mappedEntities = genInfo.mappedEntities;
1987
+ v1Result.model = genInfo.model;
1988
+ const coverageMapping = mPath === mappingPath
1989
+ ? pureGraph.getMapping(mPath)
1990
+ : new Mapping(mPath);
1991
+ mappingToMappingCoverageResult.set(mPath, V1_buildModelCoverageAnalysisResult(v1Result, this, coverageMapping, genInfo.model));
1992
+ }
1815
1993
  // Build the analysis result
1816
1994
  const result = new DataProductAnalysis();
1817
1995
  result.path = dataProductPath;
@@ -2113,6 +2291,15 @@ export class V1_PureGraphManager extends AbstractPureGraphManager {
2113
2291
  const serviceStorage = await this.engine.getServiceVersionInfo(serviceUrl, serviceId);
2114
2292
  await this.engine.activateServiceGeneration(serviceUrl, serviceStorage.getGenerationId());
2115
2293
  }
2294
+ async checkServiceRegisteredByPattern(serviceServerUrl, servicePattern) {
2295
+ try {
2296
+ await this.engine.getServiceMetadataByPattern(serviceServerUrl, servicePattern);
2297
+ return true;
2298
+ }
2299
+ catch {
2300
+ return false;
2301
+ }
2302
+ }
2116
2303
  async runServicePostValidations(service, graph, assertionId) {
2117
2304
  const contextData = this.getFullGraphModelData(graph);
2118
2305
  const result = await this.engine.runServicePostVal(service.path, contextData, assertionId);