@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.
- package/lib/graph/metamodel/pure/dataProduct/DataProduct.d.ts +4 -3
- package/lib/graph/metamodel/pure/dataProduct/DataProduct.d.ts.map +1 -1
- package/lib/graph/metamodel/pure/dataProduct/DataProduct.js +7 -5
- package/lib/graph/metamodel/pure/dataProduct/DataProduct.js.map +1 -1
- package/lib/graph-manager/AbstractPureGraphManager.d.ts +1 -0
- package/lib/graph-manager/AbstractPureGraphManager.d.ts.map +1 -1
- package/lib/graph-manager/AbstractPureGraphManager.js.map +1 -1
- package/lib/graph-manager/action/analytics/data-product/DataProductAnalysis.d.ts +4 -4
- package/lib/graph-manager/action/analytics/data-product/DataProductAnalysis.d.ts.map +1 -1
- package/lib/graph-manager/action/analytics/data-product/DataProductAnalysis.js.map +1 -1
- package/lib/graph-manager/action/query/Query.d.ts +2 -0
- package/lib/graph-manager/action/query/Query.d.ts.map +1 -1
- package/lib/graph-manager/action/query/Query.js +2 -0
- package/lib/graph-manager/action/query/Query.js.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/V1_PureGraphManager.d.ts +22 -1
- package/lib/graph-manager/protocol/pure/v1/V1_PureGraphManager.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/V1_PureGraphManager.js +289 -102
- package/lib/graph-manager/protocol/pure/v1/V1_PureGraphManager.js.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineHelper.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineHelper.js +3 -0
- package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineHelper.js.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineServerClient.d.ts +1 -0
- package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineServerClient.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineServerClient.js +2 -0
- package/lib/graph-manager/protocol/pure/v1/engine/V1_EngineServerClient.js.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/engine/V1_GraphManagerEngine.d.ts +1 -0
- package/lib/graph-manager/protocol/pure/v1/engine/V1_GraphManagerEngine.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/engine/V1_RemoteEngine.d.ts +1 -0
- package/lib/graph-manager/protocol/pure/v1/engine/V1_RemoteEngine.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/engine/V1_RemoteEngine.js +3 -0
- package/lib/graph-manager/protocol/pure/v1/engine/V1_RemoteEngine.js.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_MappingModelCoverageAnalysis.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_MappingModelCoverageAnalysis.js +7 -0
- package/lib/graph-manager/protocol/pure/v1/engine/analytics/V1_MappingModelCoverageAnalysis.js.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/engine/query/V1_Query.d.ts +2 -1
- package/lib/graph-manager/protocol/pure/v1/engine/query/V1_Query.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/engine/query/V1_Query.js +3 -1
- package/lib/graph-manager/protocol/pure/v1/engine/query/V1_Query.js.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DataProductBuilder.d.ts +1 -1
- package/lib/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DataProductBuilder.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DataProductBuilder.js +6 -6
- package/lib/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DataProductBuilder.js.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_PureProtocolSerialization.d.ts.map +1 -1
- package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_PureProtocolSerialization.js +14 -10
- package/lib/graph-manager/protocol/pure/v1/transformation/pureProtocol/V1_PureProtocolSerialization.js.map +1 -1
- package/lib/package.json +1 -1
- package/package.json +3 -3
- package/src/graph/metamodel/pure/dataProduct/DataProduct.ts +13 -5
- package/src/graph-manager/AbstractPureGraphManager.ts +4 -0
- package/src/graph-manager/action/analytics/data-product/DataProductAnalysis.ts +11 -4
- package/src/graph-manager/action/query/Query.ts +2 -0
- package/src/graph-manager/protocol/pure/v1/V1_PureGraphManager.ts +690 -499
- package/src/graph-manager/protocol/pure/v1/engine/V1_EngineHelper.ts +3 -0
- package/src/graph-manager/protocol/pure/v1/engine/V1_EngineServerClient.ts +12 -0
- package/src/graph-manager/protocol/pure/v1/engine/V1_GraphManagerEngine.ts +5 -0
- package/src/graph-manager/protocol/pure/v1/engine/V1_RemoteEngine.ts +10 -0
- package/src/graph-manager/protocol/pure/v1/engine/analytics/V1_MappingModelCoverageAnalysis.ts +7 -0
- package/src/graph-manager/protocol/pure/v1/engine/query/V1_Query.ts +3 -1
- package/src/graph-manager/protocol/pure/v1/transformation/pureGraph/to/helpers/V1_DataProductBuilder.ts +6 -3
- 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
|
-
|
|
698
|
-
|
|
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
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
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
|
|
711
|
-
await
|
|
712
|
-
await
|
|
713
|
-
await
|
|
714
|
-
await
|
|
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
|
|
717
|
-
await
|
|
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
|
|
720
|
-
await
|
|
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
|
|
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
|
|
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
|
|
729
|
-
await
|
|
730
|
-
await
|
|
731
|
-
await
|
|
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
|
|
735
|
-
await
|
|
736
|
-
await
|
|
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
|
|
741
|
-
await
|
|
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
|
|
745
|
-
await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
await
|
|
767
|
-
await
|
|
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
|
|
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
|
-
|
|
1727
|
-
|
|
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
|
-
|
|
1730
|
-
|
|
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
|
-
|
|
1736
|
-
allMappingGenInfos.set(path, genInfo);
|
|
1737
|
-
}
|
|
1874
|
+
includedGenInfos.set(path, genInfo);
|
|
1738
1875
|
}
|
|
1739
1876
|
}
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
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
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
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
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
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
|
-
//
|
|
1782
|
-
const
|
|
1783
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
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
|
|
1982
|
+
// Build MappingModelCoverageAnalysisResult for all included mappings
|
|
1810
1983
|
const mappingToMappingCoverageResult = new Map();
|
|
1811
|
-
const
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
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);
|