@finos/legend-application-studio
Version:
Legend Studio application core
1,037 lines (946 loc) • 32 kB
text/typescript
/**
* 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 { observable, action, flow, makeObservable, flowResult } from 'mobx';
import {
type GeneratorFn,
assertErrorThrown,
LogEvent,
stringifyLosslessJSON,
UnsupportedOperationError,
filterByType,
guaranteeNonNullable,
StopWatch,
} from '@finos/legend-shared';
import type { ServiceEditorState } from './ServiceEditorState.js';
import {
decorateRuntimeWithNewMapping,
RuntimeEditorState,
} from '../../../editor-state/element-editor-state/RuntimeEditorState.js';
import {
type ServiceExecution,
type PureExecution,
type Mapping,
type Runtime,
type PackageableRuntime,
type RawExecutionPlan,
type PackageableElementReference,
type QueryInfo,
type LightQuery,
type ExecutionResultWithMetadata,
PureSingleExecution,
PureMultiExecution,
KeyedExecutionParameter,
GRAPH_MANAGER_EVENT,
RawLambda,
EngineRuntime,
RuntimePointer,
PackageableElementExplicitReference,
buildSourceInformationSourceId,
QueryProjectCoordinates,
buildLambdaVariableExpressions,
observe_ValueSpecification,
VariableExpression,
stub_PackageableRuntime,
stub_Mapping,
reportGraphAnalytics,
QuerySearchSpecification,
} from '@finos/legend-graph';
import { parseGACoordinates } from '@finos/legend-storage';
import { runtime_addMapping } from '../../../../graph-modifier/DSL_Mapping_GraphModifierHelper.js';
import type { EditorStore } from '../../../EditorStore.js';
import {
keyedExecutionParameter_setKey,
pureExecution_setFunction,
pureMultiExecution_addExecutionParameter,
pureMultiExecution_deleteExecutionParameter,
pureMultiExecution_setExecutionKey,
pureSingleExecution_setMapping,
pureSingleExecution_setRuntime,
service_setExecution,
} from '../../../../graph-modifier/DSL_Service_GraphModifierHelper.js';
import {
buildExecutionParameterValues,
getExecutionQueryFromRawLambda,
LambdaEditorState,
LambdaParametersState,
LambdaParameterState,
PARAMETER_SUBMIT_ACTION,
QueryBuilderTelemetryHelper,
QueryLoaderState,
QUERY_BUILDER_EVENT,
ExecutionPlanState,
QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT,
} from '@finos/legend-query-builder';
import { DEFAULT_TAB_SIZE } from '@finos/legend-application';
export class ServiceExecutionParametersState extends LambdaParametersState {
executionState: ServicePureExecutionState;
constructor(executionState: ServicePureExecutionState) {
super();
makeObservable(this, {
parameterValuesEditorState: observable,
parameterStates: observable,
addParameter: action,
removeParameter: action,
openModal: action,
build: action,
setParameters: action,
});
this.executionState = executionState;
}
openModal(query: RawLambda): void {
this.parameterStates = this.build(query);
this.parameterValuesEditorState.open(
(): Promise<void> =>
flowResult(this.executionState.runQuery()).catch(
this.executionState.editorStore.applicationStore.alertUnhandledError,
),
PARAMETER_SUBMIT_ACTION.RUN,
);
}
build(query: RawLambda): LambdaParameterState[] {
const parameters = buildLambdaVariableExpressions(
query,
this.executionState.editorStore.graphManagerState,
)
.map((p) =>
observe_ValueSpecification(
p,
this.executionState.editorStore.changeDetectionState.observerContext,
),
)
.filter(filterByType(VariableExpression));
const states = parameters.map((p) => {
const parmeterState = new LambdaParameterState(
p,
this.executionState.editorStore.changeDetectionState.observerContext,
this.executionState.editorStore.graphManagerState.graph,
);
parmeterState.mockParameterValue();
return parmeterState;
});
return states;
}
}
export abstract class ServiceExecutionState {
readonly editorStore: EditorStore;
readonly serviceEditorState: ServiceEditorState;
readonly execution: ServiceExecution;
constructor(
editorStore: EditorStore,
serviceEditorState: ServiceEditorState,
execution: ServiceExecution,
) {
makeObservable(this, {
execution: observable,
});
this.editorStore = editorStore;
this.execution = execution;
this.serviceEditorState = serviceEditorState;
}
abstract get serviceExecutionParameters():
| { query: RawLambda; mapping: Mapping; runtime: Runtime }
| undefined;
}
export class UnsupportedServiceExecutionState extends ServiceExecutionState {
get serviceExecutionParameters():
| { query: RawLambda; mapping: Mapping; runtime: Runtime }
| undefined {
return undefined;
}
}
const decorateSearchSpecificationForServiceQueryImporter = (
val: QuerySearchSpecification,
editorStore: EditorStore,
): QuerySearchSpecification => {
const currentProjectCoordinates = new QueryProjectCoordinates();
currentProjectCoordinates.groupId =
editorStore.projectConfigurationEditorState.currentProjectConfiguration.groupId;
currentProjectCoordinates.artifactId =
editorStore.projectConfigurationEditorState.currentProjectConfiguration.artifactId;
val.projectCoordinates = [
// either get queries for the current project
currentProjectCoordinates,
// or any of its dependencies
...Array.from(
editorStore.graphManagerState.graph.dependencyManager.projectDependencyModelsIndex.keys(),
).map((dependencyKey) => {
const { groupId, artifactId } = parseGACoordinates(dependencyKey);
const coordinates = new QueryProjectCoordinates();
coordinates.groupId = groupId;
coordinates.artifactId = artifactId;
return coordinates;
}),
];
return val;
};
export class ServicePureExecutionQueryState extends LambdaEditorState {
readonly editorStore: EditorStore;
readonly queryLoaderState: QueryLoaderState;
execution: PureExecution;
isInitializingLambda = false;
constructor(editorStore: EditorStore, execution: PureExecution) {
super('', '');
makeObservable(this, {
execution: observable,
isInitializingLambda: observable,
setIsInitializingLambda: action,
setLambda: action,
updateLamba: flow,
importQuery: flow,
});
this.editorStore = editorStore;
this.execution = execution;
this.queryLoaderState = new QueryLoaderState(
editorStore.applicationStore,
editorStore.graphManagerState.graphManager,
{
loadQuery: (query: LightQuery): void => {
flowResult(this.importQuery(query.id)).catch(
this.editorStore.applicationStore.alertUnhandledError,
);
},
decorateSearchSpecification: (val) =>
decorateSearchSpecificationForServiceQueryImporter(
val,
this.editorStore,
),
fetchDefaultQueries: async (): Promise<LightQuery[]> => {
const searchSpecification = new QuerySearchSpecification();
searchSpecification.limit = QUERY_LOADER_TYPEAHEAD_SEARCH_LIMIT;
return this.editorStore.graphManagerState.graphManager.searchQueries(
decorateSearchSpecificationForServiceQueryImporter(
searchSpecification,
this.editorStore,
),
);
},
isReadOnly: true,
},
);
}
get lambdaId(): string {
return buildSourceInformationSourceId([
this.execution._OWNER.path,
'execution',
]);
}
get query(): RawLambda {
return this.execution.func;
}
setIsInitializingLambda(val: boolean): void {
this.isInitializingLambda = val;
}
setLambda(val: RawLambda): void {
pureExecution_setFunction(this.execution, val);
}
*importQuery(selectedQueryID: string): GeneratorFn<void> {
try {
const content =
(yield this.editorStore.graphManagerState.graphManager.prettyLambdaContent(
(
(yield this.editorStore.graphManagerState.graphManager.getQueryInfo(
selectedQueryID,
)) as QueryInfo
).content,
)) as string;
const lambda =
(yield this.editorStore.graphManagerState.graphManager.pureCodeToLambda(
content,
)) as RawLambda;
yield flowResult(this.updateLamba(lambda));
} catch (error) {
assertErrorThrown(error);
this.editorStore.applicationStore.notificationService.notifyError(error);
} finally {
this.queryLoaderState.setQueryLoaderDialogOpen(false);
}
}
*updateLamba(val: RawLambda): GeneratorFn<void> {
this.setLambda(val);
yield flowResult(this.convertLambdaObjectToGrammarString({ pretty: true }));
}
*convertLambdaObjectToGrammarString(options?: {
pretty?: boolean | undefined;
}): GeneratorFn<void> {
if (this.execution.func.body) {
try {
const lambdas = new Map<string, RawLambda>();
lambdas.set(
this.lambdaId,
new RawLambda(
this.execution.func.parameters,
this.execution.func.body,
),
);
const isolatedLambdas =
(yield this.editorStore.graphManagerState.graphManager.lambdasToPureCode(
lambdas,
options?.pretty,
)) as Map<string, string>;
const grammarText = isolatedLambdas.get(this.lambdaId);
this.setLambdaString(
grammarText !== undefined
? this.extractLambdaString(grammarText)
: '',
);
this.clearErrors();
} catch (error) {
assertErrorThrown(error);
this.editorStore.applicationStore.logService.error(
LogEvent.create(GRAPH_MANAGER_EVENT.PARSING_FAILURE),
error,
);
}
} else {
this.clearErrors();
this.setLambdaString('');
}
}
// NOTE: since we don't allow edition in text mode, we don't need to implement this
*convertLambdaGrammarStringToObject(): GeneratorFn<void> {
throw new UnsupportedOperationError();
}
}
export interface ServiceExecutionContext {
mapping: PackageableElementReference<Mapping>;
runtime: Runtime;
}
export abstract class ServiceExecutionContextState {
executionState: ServiceExecutionState;
constructor(executionState: ServiceExecutionState) {
this.executionState = executionState;
}
abstract get executionContext(): ServiceExecutionContext;
abstract setMapping(value: Mapping): void;
abstract setRuntime(value: Runtime): void;
}
export class SingleExecutionContextState extends ServiceExecutionContextState {
declare executionState: SingleServicePureExecutionState;
constructor(executionState: SingleServicePureExecutionState) {
super(executionState);
makeObservable(this, {
setMapping: action,
setRuntime: action,
});
this.executionState = executionState;
}
setMapping(value: Mapping): void {
pureSingleExecution_setMapping(
this.executionState.execution,
value,
this.executionState.editorStore.changeDetectionState.observerContext,
);
}
setRuntime(value: Runtime): void {
pureSingleExecution_setRuntime(
this.executionState.execution,
value,
this.executionState.editorStore.changeDetectionState.observerContext,
);
}
get executionContext(): ServiceExecutionContext {
return {
mapping: guaranteeNonNullable(this.executionState.execution.mapping),
runtime: guaranteeNonNullable(this.executionState.execution.runtime),
};
}
}
export class KeyedExecutionContextState extends ServiceExecutionContextState {
keyedExecutionParameter: KeyedExecutionParameter;
constructor(
keyedExecutionParameter: KeyedExecutionParameter,
executionState: MultiServicePureExecutionState,
) {
super(executionState);
makeObservable(this, {
setMapping: action,
setRuntime: action,
});
this.keyedExecutionParameter = keyedExecutionParameter;
}
setMapping(value: Mapping): void {
pureSingleExecution_setMapping(
this.keyedExecutionParameter,
value,
this.executionState.editorStore.changeDetectionState.observerContext,
);
}
setRuntime(value: Runtime): void {
pureSingleExecution_setRuntime(
this.keyedExecutionParameter,
value,
this.executionState.editorStore.changeDetectionState.observerContext,
);
}
get executionContext(): ServiceExecutionContext {
return this.keyedExecutionParameter;
}
}
export abstract class ServicePureExecutionState extends ServiceExecutionState {
declare execution: PureExecution;
queryState: ServicePureExecutionQueryState;
selectedExecutionContextState: ServiceExecutionContextState | undefined;
runtimeEditorState?: RuntimeEditorState | undefined;
isOpeningQueryEditor = false;
showChangeExecModal = false;
isRunningQuery = false;
isGeneratingPlan = false;
executionResultText?: string | undefined; // NOTE: stored as lossless JSON string
executionPlanState: ExecutionPlanState;
readonly parametersState: ServiceExecutionParametersState;
queryRunPromise: Promise<ExecutionResultWithMetadata> | undefined = undefined;
constructor(
editorStore: EditorStore,
serviceEditorState: ServiceEditorState,
execution: PureExecution,
) {
super(editorStore, serviceEditorState, execution);
makeObservable(this, {
cancelQuery: flow,
});
this.execution = execution;
this.queryState = new ServicePureExecutionQueryState(
this.editorStore,
execution,
);
this.executionPlanState = new ExecutionPlanState(
this.editorStore.applicationStore,
this.editorStore.graphManagerState,
);
this.parametersState = new ServiceExecutionParametersState(this);
}
abstract changeExecution(): void;
isChangeExecutionDisabled(): boolean {
return false;
}
setIsRunningQuery(val: boolean): void {
this.isRunningQuery = val;
}
setShowChangeExecModal(val: boolean): void {
this.showChangeExecModal = val;
}
setOpeningQueryEditor(val: boolean): void {
this.isOpeningQueryEditor = val;
}
setExecutionResultText = (executionResult: string | undefined): void => {
this.executionResultText = executionResult;
};
setQueryState = (queryState: ServicePureExecutionQueryState): void => {
this.queryState = queryState;
};
setQueryRunPromise = (
promise: Promise<ExecutionResultWithMetadata> | undefined,
): void => {
this.queryRunPromise = promise;
};
*generatePlan(debug: boolean): GeneratorFn<void> {
if (this.isGeneratingPlan) {
return;
}
try {
const query = this.queryState.query;
this.isGeneratingPlan = true;
let rawPlan: RawExecutionPlan;
const stopWatch = new StopWatch();
const report = reportGraphAnalytics(
this.editorStore.graphManagerState.graph,
);
if (debug) {
QueryBuilderTelemetryHelper.logEvent_ExecutionPlanDebugLaunched(
this.editorStore.applicationStore.telemetryService,
);
const debugResult =
(yield this.editorStore.graphManagerState.graphManager.debugExecutionPlanGeneration(
query,
this.selectedExecutionContextState?.executionContext.mapping.value,
this.selectedExecutionContextState?.executionContext.runtime,
this.editorStore.graphManagerState.graph,
report,
)) as { plan: RawExecutionPlan; debug: string };
rawPlan = debugResult.plan;
this.executionPlanState.setDebugText(debugResult.debug);
} else {
QueryBuilderTelemetryHelper.logEvent_ExecutionPlanGenerationLaunched(
this.editorStore.applicationStore.telemetryService,
);
rawPlan =
(yield this.editorStore.graphManagerState.graphManager.generateExecutionPlan(
query,
this.selectedExecutionContextState?.executionContext.mapping.value,
this.selectedExecutionContextState?.executionContext.runtime,
this.editorStore.graphManagerState.graph,
report,
)) as object;
}
stopWatch.record();
try {
this.executionPlanState.setRawPlan(rawPlan);
const plan =
this.editorStore.graphManagerState.graphManager.buildExecutionPlan(
rawPlan,
this.editorStore.graphManagerState.graph,
);
this.executionPlanState.initialize(plan);
} catch {
// do nothing
}
stopWatch.record(QUERY_BUILDER_EVENT.BUILD_EXECUTION_PLAN__SUCCESS);
// report
report.timings =
this.editorStore.applicationStore.timeService.finalizeTimingsRecord(
stopWatch,
report.timings,
);
if (debug) {
QueryBuilderTelemetryHelper.logEvent_ExecutionPlanDebugSucceeded(
this.editorStore.applicationStore.telemetryService,
report,
);
} else {
QueryBuilderTelemetryHelper.logEvent_ExecutionPlanGenerationSucceeded(
this.editorStore.applicationStore.telemetryService,
report,
);
}
} catch (error) {
assertErrorThrown(error);
this.editorStore.applicationStore.logService.error(
LogEvent.create(GRAPH_MANAGER_EVENT.EXECUTION_FAILURE),
error,
);
this.editorStore.applicationStore.notificationService.notifyError(error);
} finally {
this.isGeneratingPlan = false;
}
}
*handleRunQuery(): GeneratorFn<void> {
if (this.isRunningQuery) {
return;
}
const query = this.queryState.query;
const parameters = (query.parameters ?? []) as object[];
if (parameters.length) {
this.parametersState.openModal(query);
} else {
this.runQuery();
}
}
*runQuery(): GeneratorFn<void> {
if (this.isRunningQuery) {
return;
}
QueryBuilderTelemetryHelper.logEvent_QueryRunLaunched(
this.editorStore.applicationStore.telemetryService,
);
let promise;
try {
this.isRunningQuery = true;
const stopWatch = new StopWatch();
const report = reportGraphAnalytics(
this.editorStore.graphManagerState.graph,
);
promise = this.editorStore.graphManagerState.graphManager.runQuery(
getExecutionQueryFromRawLambda(
this.queryState.query,
this.parametersState.parameterStates,
this.editorStore.graphManagerState,
),
this.selectedExecutionContextState?.executionContext.mapping.value,
this.selectedExecutionContextState?.executionContext.runtime,
this.editorStore.graphManagerState.graph,
{
useLosslessParse: true,
parameterValues: buildExecutionParameterValues(
this.parametersState.parameterStates,
this.editorStore.graphManagerState,
),
},
report,
);
this.setQueryRunPromise(promise);
const result = (yield promise) as ExecutionResultWithMetadata;
if (this.queryRunPromise === promise) {
this.setExecutionResultText(
stringifyLosslessJSON(
result.executionResult,
undefined,
DEFAULT_TAB_SIZE,
),
);
this.parametersState.setParameters([]);
// report
report.timings =
this.editorStore.applicationStore.timeService.finalizeTimingsRecord(
stopWatch,
report.timings,
);
QueryBuilderTelemetryHelper.logEvent_QueryRunSucceeded(
this.editorStore.applicationStore.telemetryService,
report,
);
}
} catch (error) {
// When user cancels the query by calling the cancelQuery api, it will throw an execution failure error.
// For now, we don't want to notify users about this failure. Therefore we check to ensure the promise is still the same one.
// When cancelled the query, we set the queryRunPromise as undefined.
if (this.queryRunPromise === promise) {
assertErrorThrown(error);
this.editorStore.applicationStore.logService.error(
LogEvent.create(GRAPH_MANAGER_EVENT.EXECUTION_FAILURE),
error,
);
this.editorStore.applicationStore.notificationService.notifyError(
error,
);
}
} finally {
this.isRunningQuery = false;
}
}
*cancelQuery(): GeneratorFn<void> {
this.setIsRunningQuery(false);
this.setQueryRunPromise(undefined);
try {
yield this.editorStore.graphManagerState.graphManager.cancelUserExecutions(
true,
);
} catch (error) {
// Don't notify users about success or failure
this.editorStore.applicationStore.logService.error(
LogEvent.create(GRAPH_MANAGER_EVENT.EXECUTION_FAILURE),
error,
);
}
}
get serviceExecutionParameters():
| { query: RawLambda; mapping: Mapping; runtime: Runtime }
| undefined {
if (!this.selectedExecutionContextState || this.isRunningQuery) {
return undefined;
}
const query = this.queryState.query;
return {
query,
mapping:
this.selectedExecutionContextState.executionContext.mapping.value,
runtime: this.selectedExecutionContextState.executionContext.runtime,
};
}
closeRuntimeEditor(): void {
this.runtimeEditorState = undefined;
}
openRuntimeEditor(): void {
if (
this.selectedExecutionContextState &&
!(
this.selectedExecutionContextState.executionContext.runtime instanceof
RuntimePointer
)
) {
this.runtimeEditorState = new RuntimeEditorState(
this.editorStore,
this.selectedExecutionContextState.executionContext.runtime,
true,
);
}
}
useCustomRuntime(): void {
const customRuntime = new EngineRuntime();
guaranteeNonNullable(this.selectedExecutionContextState);
const executionState = this
.selectedExecutionContextState as ServiceExecutionContextState;
runtime_addMapping(
customRuntime,
PackageableElementExplicitReference.create(
executionState.executionContext.mapping.value,
),
);
decorateRuntimeWithNewMapping(
customRuntime,
executionState.executionContext.mapping.value,
this.editorStore,
);
executionState.setRuntime(customRuntime);
}
autoSelectRuntimeOnMappingChange(mapping: Mapping): void {
if (this.selectedExecutionContextState) {
const runtimes =
this.editorStore.graphManagerState.graph.ownRuntimes.filter((runtime) =>
runtime.runtimeValue.mappings.map((m) => m.value).includes(mapping),
);
if (runtimes.length) {
this.selectedExecutionContextState.setRuntime(
(runtimes[0] as PackageableRuntime).runtimeValue,
);
} else {
this.useCustomRuntime();
}
}
}
abstract getInitiallySelectedExecutionContextState():
| ServiceExecutionContextState
| undefined;
updateExecutionQuery(): void {
pureExecution_setFunction(this.execution, this.queryState.query);
}
}
export class InlineServicePureExecutionState extends ServicePureExecutionState {
declare execution: PureSingleExecution;
constructor(
editorStore: EditorStore,
serviceEditorState: ServiceEditorState,
execution: PureSingleExecution,
) {
super(editorStore, serviceEditorState, execution);
makeObservable(this, {
queryState: observable,
isRunningQuery: observable,
isGeneratingPlan: observable,
isOpeningQueryEditor: observable,
executionResultText: observable,
executionPlanState: observable,
showChangeExecModal: observable,
setExecutionResultText: action,
setQueryState: action,
updateExecutionQuery: action,
setOpeningQueryEditor: action,
generatePlan: flow,
handleRunQuery: flow,
runQuery: flow,
});
this.selectedExecutionContextState =
this.getInitiallySelectedExecutionContextState();
}
changeExecution(): void {
throw new Error('Method not implemented.');
}
getInitiallySelectedExecutionContextState():
| ServiceExecutionContextState
| undefined {
return undefined;
}
}
export class SingleServicePureExecutionState extends ServicePureExecutionState {
declare execution: PureSingleExecution;
declare selectedExecutionContextState: ServiceExecutionContextState;
multiExecutionKey = 'key';
constructor(
editorStore: EditorStore,
serviceEditorState: ServiceEditorState,
execution: PureSingleExecution,
) {
super(editorStore, serviceEditorState, execution);
makeObservable(this, {
queryState: observable,
getInitiallySelectedExecutionContextState: observable,
selectedExecutionContextState: observable,
runtimeEditorState: observable,
isRunningQuery: observable,
isGeneratingPlan: observable,
isOpeningQueryEditor: observable,
executionResultText: observable,
executionPlanState: observable,
showChangeExecModal: observable,
multiExecutionKey: observable,
setExecutionResultText: action,
closeRuntimeEditor: action,
openRuntimeEditor: action,
useCustomRuntime: action,
setQueryState: action,
autoSelectRuntimeOnMappingChange: action,
updateExecutionQuery: action,
setOpeningQueryEditor: action,
changeExecution: action,
setMultiExecutionKey: action,
setShowChangeExecModal: action,
setIsRunningQuery: action,
generatePlan: flow,
handleRunQuery: flow,
runQuery: flow,
});
this.selectedExecutionContextState =
this.getInitiallySelectedExecutionContextState();
}
override isChangeExecutionDisabled(): boolean {
return this.multiExecutionKey === '';
}
getInitiallySelectedExecutionContextState(): ServiceExecutionContextState {
return new SingleExecutionContextState(this);
}
setMultiExecutionKey(val: string): void {
this.multiExecutionKey = val;
}
changeExecution(): void {
if (this.execution.mapping && this.execution.runtime) {
const _execution = new PureMultiExecution(
this.multiExecutionKey,
this.execution.func,
this.serviceEditorState.service,
);
const _parameter = new KeyedExecutionParameter(
`execContext_1`,
this.execution.mapping,
this.execution.runtime,
);
_execution.executionParameters = [_parameter];
service_setExecution(
this.serviceEditorState.service,
_execution,
this.editorStore.changeDetectionState.observerContext,
);
this.serviceEditorState.resetExecutionState();
}
}
}
export class MultiServicePureExecutionState extends ServicePureExecutionState {
declare execution: PureMultiExecution;
newKeyParameterModal = false;
renameKey: KeyedExecutionParameter | undefined;
singleExecutionKey: KeyedExecutionParameter | undefined;
constructor(
editorStore: EditorStore,
serviceEditorState: ServiceEditorState,
execution: PureMultiExecution,
) {
super(editorStore, serviceEditorState, execution);
makeObservable(this, {
queryState: observable,
selectedExecutionContextState: observable,
runtimeEditorState: observable,
isRunningQuery: observable,
isGeneratingPlan: observable,
isOpeningQueryEditor: observable,
executionResultText: observable,
executionPlanState: observable,
newKeyParameterModal: observable,
renameKey: observable,
singleExecutionKey: observable,
showChangeExecModal: observable,
setExecutionResultText: action,
closeRuntimeEditor: action,
openRuntimeEditor: action,
useCustomRuntime: action,
setQueryState: action,
autoSelectRuntimeOnMappingChange: action,
updateExecutionQuery: action,
setOpeningQueryEditor: action,
deleteKeyExecutionParameter: action,
setNewKeyParameterModal: action,
changeKeyedExecutionParameter: action,
setRenameKey: action,
addExecutionParameter: action,
setExecutionKey: action,
changeKeyValue: action,
setSingleExecutionKey: action,
setShowChangeExecModal: action,
setIsRunningQuery: action,
changeExecution: action,
generatePlan: flow,
handleRunQuery: flow,
runQuery: flow,
});
this.execution = execution;
this.selectedExecutionContextState =
this.getInitiallySelectedExecutionContextState();
this.queryState = new ServicePureExecutionQueryState(
this.editorStore,
execution,
);
this.executionPlanState = new ExecutionPlanState(
this.editorStore.applicationStore,
this.editorStore.graphManagerState,
);
}
get keyedExecutionParameters(): KeyedExecutionParameter[] {
return this.execution.executionParameters ?? [];
}
setSingleExecutionKey(val: KeyedExecutionParameter | undefined): void {
this.singleExecutionKey = val;
}
changeExecution(): void {
const mappingExecution = this.singleExecutionKey;
// stub
const _mapping = mappingExecution?.mapping.value ?? stub_Mapping();
const mapping = PackageableElementExplicitReference.create(_mapping);
const runtime = mappingExecution?.runtime ?? stub_PackageableRuntime();
const _execution = new PureSingleExecution(
this.execution.func,
this.serviceEditorState.service,
mapping,
runtime,
);
service_setExecution(
this.serviceEditorState.service,
_execution,
this.editorStore.changeDetectionState.observerContext,
);
this.serviceEditorState.resetExecutionState();
}
setRenameKey(key: KeyedExecutionParameter | undefined): void {
this.renameKey = key;
}
setNewKeyParameterModal(val: boolean): void {
this.newKeyParameterModal = val;
}
setExecutionKey(val: string): void {
pureMultiExecution_setExecutionKey(this.execution, val);
}
getInitiallySelectedExecutionContextState():
| ServiceExecutionContextState
| undefined {
const parameter = this.keyedExecutionParameters[0];
return parameter
? new KeyedExecutionContextState(parameter, this)
: undefined;
}
changeKeyedExecutionParameter(value: KeyedExecutionParameter): void {
this.selectedExecutionContextState = new KeyedExecutionContextState(
value,
this,
);
}
deleteKeyExecutionParameter(value: KeyedExecutionParameter): void {
pureMultiExecution_deleteExecutionParameter(
this.keyedExecutionParameters,
value,
);
if (value === this.selectedExecutionContextState?.executionContext) {
this.selectedExecutionContextState =
this.getInitiallySelectedExecutionContextState();
}
}
addExecutionParameter(value: string): void {
const _mapping =
this.editorStore.graphManagerState.usableMappings[0] ?? stub_Mapping();
const _key = new KeyedExecutionParameter(
value,
PackageableElementExplicitReference.create(_mapping),
stub_PackageableRuntime(),
);
pureMultiExecution_addExecutionParameter(
this.keyedExecutionParameters,
_key,
this.editorStore.changeDetectionState.observerContext,
);
this.selectedExecutionContextState = new KeyedExecutionContextState(
_key,
this,
);
}
changeKeyValue(key: KeyedExecutionParameter, value: string): void {
keyedExecutionParameter_setKey(key, value);
}
}