@finos/legend-extension-dsl-data-quality
Version:
Legend extension for Data Quality
270 lines • 13.3 kB
JavaScript
/**
* Copyright (c) 2020-present, Goldman Sachs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { buildExecutionParameterValues, ExecutionPlanState, QUERY_BUILDER_EVENT, QueryBuilderTelemetryHelper, PARAMETER_SUBMIT_ACTION, } from '@finos/legend-query-builder';
import { action, flow, flowResult, makeObservable, observable } from 'mobx';
import { assertErrorThrown, LogEvent, StopWatch, getContentTypeFileExtension, ActionState, ContentType, UnsupportedOperationError, } from '@finos/legend-shared';
import { GRAPH_MANAGER_EVENT, V1_DELEGATED_EXPORT_HEADER, EXECUTION_SERIALIZATION_FORMAT, } from '@finos/legend-graph';
import { getDataQualityPureGraphManagerExtension } from '../../graph-manager/protocol/pure/DSL_DataQuality_PureGraphManagerExtension.js';
import { downloadStream } from '@finos/legend-application';
export const DEFAULT_LIMIT = 1000;
export class DataQualityRelationResultState {
dataQualityRelationValidationConfigurationState;
executionPlanState;
exportState = ActionState.create();
previewLimit = DEFAULT_LIMIT;
isRunningValidation = false;
isGeneratingPlan = false;
executionResult;
executionDuration;
latestRunHashCode;
validationRunPromise = undefined;
validationToRun;
constructor(dataQualityRelationValidationState) {
makeObservable(this, {
executionResult: observable,
previewLimit: observable,
executionDuration: observable,
latestRunHashCode: observable,
validationRunPromise: observable,
isGeneratingPlan: observable,
isRunningValidation: observable,
validationToRun: observable,
setIsRunningValidation: action,
setExecutionResult: action,
setExecutionDuration: action,
setPreviewLimit: action,
setValidationRunPromise: action,
setValidationToRun: action,
handleRunValidation: action,
handleExport: action,
runValidation: flow,
cancelValidation: flow,
generatePlan: flow,
exportData: flow,
});
this.dataQualityRelationValidationConfigurationState =
dataQualityRelationValidationState;
this.executionPlanState = new ExecutionPlanState(this.dataQualityRelationValidationConfigurationState.editorStore.applicationStore, this.dataQualityRelationValidationConfigurationState.editorStore.graphManagerState);
}
setIsRunningValidation(val) {
this.isRunningValidation = val;
}
setExecutionResult(val) {
this.executionResult = val;
}
setExecutionDuration(val) {
this.executionDuration = val;
}
setPreviewLimit(val) {
this.previewLimit = Math.max(1, val);
}
setValidationRunPromise(promise) {
this.validationRunPromise = promise;
}
setValidationToRun(validation) {
this.validationToRun = validation;
}
get checkForStaleResults() {
if (this.latestRunHashCode !==
this.dataQualityRelationValidationConfigurationState.hashCode) {
return true;
}
return false;
}
handleRunValidation() {
const queryLambda = this.dataQualityRelationValidationConfigurationState
.bodyExpressionSequence;
const parameters = (queryLambda.parameters ?? []);
if (parameters.length) {
this.dataQualityRelationValidationConfigurationState.parametersState.openModal(queryLambda, true);
}
else {
flowResult(this.runValidation()).catch(this.dataQualityRelationValidationConfigurationState.editorStore
.applicationStore.alertUnhandledError);
}
}
handleExport(format) {
const queryLambda = this.dataQualityRelationValidationConfigurationState
.bodyExpressionSequence;
const parameters = (queryLambda.parameters ?? []);
if (parameters.length) {
this.dataQualityRelationValidationConfigurationState.parametersState.parameterStates =
this.dataQualityRelationValidationConfigurationState.parametersState.build(queryLambda);
this.dataQualityRelationValidationConfigurationState.parametersState.parameterValuesEditorState.open(() => flowResult(this.exportData(format)).catch(this.dataQualityRelationValidationConfigurationState.editorStore
.applicationStore.alertUnhandledError), PARAMETER_SUBMIT_ACTION.EXPORT);
}
else {
flowResult(this.exportData(format)).catch(this.dataQualityRelationValidationConfigurationState.editorStore
.applicationStore.alertUnhandledError);
}
}
*runValidation() {
let promise;
try {
this.setIsRunningValidation(true);
const currentHashCode = this.dataQualityRelationValidationConfigurationState.hashCode;
const packagePath = this.dataQualityRelationValidationConfigurationState.validationElement
.path;
const model = this.dataQualityRelationValidationConfigurationState.editorStore
.graphManagerState.graph;
const stopWatch = new StopWatch();
promise = getDataQualityPureGraphManagerExtension(this.dataQualityRelationValidationConfigurationState.editorStore
.graphManagerState.graphManager).execute(model, packagePath, {
previewLimit: this.previewLimit,
validationName: this.validationToRun?.name,
lambdaParameterValues: buildExecutionParameterValues(this.dataQualityRelationValidationConfigurationState.parametersState
.parameterStates, this.dataQualityRelationValidationConfigurationState.editorStore
.graphManagerState),
});
this.setValidationRunPromise(promise);
const result = (yield promise);
if (this.validationRunPromise === promise) {
this.setExecutionResult(result);
this.latestRunHashCode = currentHashCode;
this.setExecutionDuration(stopWatch.elapsed);
}
}
catch (error) {
if (this.validationRunPromise === promise) {
assertErrorThrown(error);
this.setExecutionResult(undefined);
this.dataQualityRelationValidationConfigurationState.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.EXECUTION_FAILURE), error);
this.dataQualityRelationValidationConfigurationState.editorStore.applicationStore.notificationService.notifyError(error);
}
}
finally {
this.setIsRunningValidation(false);
}
}
*cancelValidation() {
this.setIsRunningValidation(false);
this.setValidationRunPromise(undefined);
try {
yield this.dataQualityRelationValidationConfigurationState.editorStore.graphManagerState.graphManager.cancelUserExecutions(true);
}
catch (error) {
// Don't notify users about success or failure
this.dataQualityRelationValidationConfigurationState.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.EXECUTION_FAILURE), error);
}
}
*generatePlan(debug) {
const packagePath = this.dataQualityRelationValidationConfigurationState.validationElement
.path;
const model = this.dataQualityRelationValidationConfigurationState.editorStore
.graphManagerState.graph;
try {
this.isGeneratingPlan = true;
let rawPlan;
const stopWatch = new StopWatch();
if (debug) {
const debugResult = (yield getDataQualityPureGraphManagerExtension(this.dataQualityRelationValidationConfigurationState.editorStore
.graphManagerState.graphManager).debugExecutionPlanGeneration(model, packagePath, {
validationName: this.validationToRun?.name,
previewLimit: this.previewLimit,
}));
rawPlan = debugResult.plan;
this.executionPlanState.setDebugText(debugResult.debug);
}
else {
QueryBuilderTelemetryHelper.logEvent_ExecutionPlanGenerationLaunched(this.dataQualityRelationValidationConfigurationState.editorStore
.applicationStore.telemetryService);
rawPlan = (yield getDataQualityPureGraphManagerExtension(this.dataQualityRelationValidationConfigurationState.editorStore
.graphManagerState.graphManager).generatePlan(model, packagePath, {
validationName: this.validationToRun?.name,
previewLimit: this.previewLimit,
}));
}
stopWatch.record();
try {
this.executionPlanState.setRawPlan(rawPlan);
const plan = this.dataQualityRelationValidationConfigurationState.editorStore.graphManagerState.graphManager.buildExecutionPlan(rawPlan, this.dataQualityRelationValidationConfigurationState.editorStore
.graphManagerState.graph);
this.executionPlanState.initialize(plan);
}
catch {
//do nothing
}
stopWatch.record(QUERY_BUILDER_EVENT.BUILD_EXECUTION_PLAN__SUCCESS);
}
catch (error) {
assertErrorThrown(error);
this.dataQualityRelationValidationConfigurationState.editorStore.applicationStore.logService.error(LogEvent.create(GRAPH_MANAGER_EVENT.EXECUTION_FAILURE), error);
this.dataQualityRelationValidationConfigurationState.editorStore.applicationStore.notificationService.notifyError(error);
}
finally {
this.isGeneratingPlan = false;
}
}
getExportDataInfo(format) {
switch (format) {
case EXECUTION_SERIALIZATION_FORMAT.CSV:
return {
contentType: ContentType.TEXT_CSV,
serializationFormat: EXECUTION_SERIALIZATION_FORMAT.CSV,
};
default:
throw new UnsupportedOperationError(`Unsupported TDS export type ${format}`);
}
}
get exportDataFormatOptions() {
return [EXECUTION_SERIALIZATION_FORMAT.CSV];
}
*exportData(format) {
try {
this.exportState.inProgress();
const packagePath = this.dataQualityRelationValidationConfigurationState.validationElement
.path;
const model = this.dataQualityRelationValidationConfigurationState.editorStore
.graphManagerState.graph;
this.dataQualityRelationValidationConfigurationState.editorStore.applicationStore.notificationService.notifySuccess(`Export ${format} will run in background`);
const exportData = this.getExportDataInfo(format);
const contentType = exportData.contentType;
const serializationFormat = exportData.serializationFormat;
const result = (yield getDataQualityPureGraphManagerExtension(this.dataQualityRelationValidationConfigurationState.editorStore
.graphManagerState.graphManager).exportData(model, packagePath, {
serializationFormat,
previewLimit: this.previewLimit,
validationName: this.validationToRun?.name,
lambdaParameterValues: buildExecutionParameterValues(this.dataQualityRelationValidationConfigurationState.parametersState
.parameterStates, this.dataQualityRelationValidationConfigurationState.editorStore
.graphManagerState),
}));
if (result.headers.get(V1_DELEGATED_EXPORT_HEADER) === 'true') {
if (result.status === 200) {
this.exportState.pass();
}
else {
this.exportState.fail();
}
return;
}
downloadStream(result, `result.${getContentTypeFileExtension(contentType)}`, exportData.contentType)
.then(() => {
this.exportState.pass();
})
.catch((error) => {
assertErrorThrown(error);
});
}
catch (error) {
this.exportState.fail();
assertErrorThrown(error);
this.dataQualityRelationValidationConfigurationState.editorStore.applicationStore.notificationService.notifyError(error);
this.exportState.complete();
}
}
}
//# sourceMappingURL=DataQualityRelationResultState.js.map