Add model evaluation run to store and view (#3385)
This commit is contained in:
@@ -25,6 +25,7 @@ import type {
|
||||
UrlValueResolvable,
|
||||
} from "./raw-result-types";
|
||||
import type { AccessPathSuggestionOptions } from "../model-editor/suggestions";
|
||||
import type { ModelEvaluationRunState } from "../model-editor/shared/model-evaluation-run-state";
|
||||
|
||||
/**
|
||||
* This module contains types and code that are shared between
|
||||
@@ -638,6 +639,11 @@ interface SetAccessPathSuggestionsMessage {
|
||||
accessPathSuggestions: AccessPathSuggestionOptions;
|
||||
}
|
||||
|
||||
interface SetModelEvaluationRunMessage {
|
||||
t: "setModelEvaluationRun";
|
||||
run: ModelEvaluationRunState | undefined;
|
||||
}
|
||||
|
||||
export type ToModelEditorMessage =
|
||||
| SetExtensionPackStateMessage
|
||||
| SetMethodsMessage
|
||||
@@ -646,7 +652,8 @@ export type ToModelEditorMessage =
|
||||
| SetInProgressMethodsMessage
|
||||
| SetProcessedByAutoModelMethodsMessage
|
||||
| RevealMethodMessage
|
||||
| SetAccessPathSuggestionsMessage;
|
||||
| SetAccessPathSuggestionsMessage
|
||||
| SetModelEvaluationRunMessage;
|
||||
|
||||
export type FromModelEditorMessage =
|
||||
| CommonFromViewMessages
|
||||
|
||||
@@ -57,12 +57,15 @@ import { LSPErrorCodes } from "vscode-languageclient";
|
||||
import type { AccessPathSuggestionOptions } from "./suggestions";
|
||||
import { runSuggestionsQuery } from "./suggestion-queries";
|
||||
import { parseAccessPathSuggestionRowsToOptions } from "./suggestions-bqrs";
|
||||
import { ModelEvaluator } from "./model-evaluator";
|
||||
import type { ModelEvaluationRunState } from "./shared/model-evaluation-run-state";
|
||||
|
||||
export class ModelEditorView extends AbstractWebview<
|
||||
ToModelEditorMessage,
|
||||
FromModelEditorMessage
|
||||
> {
|
||||
private readonly autoModeler: AutoModeler;
|
||||
private readonly modelEvaluator: ModelEvaluator;
|
||||
private readonly languageDefinition: ModelsAsDataLanguage;
|
||||
|
||||
public constructor(
|
||||
@@ -101,6 +104,14 @@ export class ModelEditorView extends AbstractWebview<
|
||||
},
|
||||
);
|
||||
this.languageDefinition = getModelsAsDataLanguage(language);
|
||||
|
||||
this.modelEvaluator = new ModelEvaluator(
|
||||
modelingStore,
|
||||
modelingEvents,
|
||||
databaseItem,
|
||||
this.updateModelEvaluationRun.bind(this),
|
||||
);
|
||||
this.push(this.modelEvaluator);
|
||||
}
|
||||
|
||||
public async openView() {
|
||||
@@ -338,10 +349,10 @@ export class ModelEditorView extends AbstractWebview<
|
||||
break;
|
||||
}
|
||||
case "startModelEvaluation":
|
||||
this.startModelEvaluation();
|
||||
await this.modelEvaluator.startEvaluation();
|
||||
break;
|
||||
case "stopModelEvaluation":
|
||||
this.stopModelEvaluation();
|
||||
await this.modelEvaluator.stopEvaluation();
|
||||
break;
|
||||
case "telemetry":
|
||||
telemetryListener?.sendUIInteraction(msg.action);
|
||||
@@ -920,11 +931,10 @@ export class ModelEditorView extends AbstractWebview<
|
||||
this.modelingStore.addModifiedMethod(this.databaseItem, signature);
|
||||
}
|
||||
|
||||
private startModelEvaluation() {
|
||||
// Do nothing for now. This will be fleshed out in the near future.
|
||||
}
|
||||
|
||||
private stopModelEvaluation() {
|
||||
// Do nothing for now. This will be fleshed out in the near future.
|
||||
private async updateModelEvaluationRun(run: ModelEvaluationRunState) {
|
||||
await this.postMessage({
|
||||
t: "setModelEvaluationRun",
|
||||
run,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface ModelEvaluationRun {
|
||||
isPreparing: boolean;
|
||||
variantAnalysisId: number | undefined;
|
||||
}
|
||||
73
extensions/ql-vscode/src/model-editor/model-evaluator.ts
Normal file
73
extensions/ql-vscode/src/model-editor/model-evaluator.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import type { ModelingStore } from "./modeling-store";
|
||||
import type { ModelingEvents } from "./modeling-events";
|
||||
import type { DatabaseItem } from "../databases/local-databases";
|
||||
import type { ModelEvaluationRun } from "./model-evaluation-run";
|
||||
import { DisposableObject } from "../common/disposable-object";
|
||||
import { sleep } from "../common/time";
|
||||
import type { ModelEvaluationRunState } from "./shared/model-evaluation-run-state";
|
||||
|
||||
export class ModelEvaluator extends DisposableObject {
|
||||
public constructor(
|
||||
private readonly modelingStore: ModelingStore,
|
||||
private readonly modelingEvents: ModelingEvents,
|
||||
private readonly dbItem: DatabaseItem,
|
||||
private readonly updateView: (
|
||||
run: ModelEvaluationRunState,
|
||||
) => Promise<void>,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.registerToModelingEvents();
|
||||
}
|
||||
|
||||
public async startEvaluation() {
|
||||
// Update store with evaluation run status
|
||||
const evaluationRun: ModelEvaluationRun = {
|
||||
isPreparing: true,
|
||||
variantAnalysisId: undefined,
|
||||
};
|
||||
this.modelingStore.updateModelEvaluationRun(this.dbItem, evaluationRun);
|
||||
|
||||
// For now, just wait 5 seconds and then update the store.
|
||||
// In the future, this will be replaced with the actual evaluation process.
|
||||
void sleep(5000).then(() => {
|
||||
const completedEvaluationRun: ModelEvaluationRun = {
|
||||
isPreparing: false,
|
||||
variantAnalysisId: undefined,
|
||||
};
|
||||
this.modelingStore.updateModelEvaluationRun(
|
||||
this.dbItem,
|
||||
completedEvaluationRun,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
public async stopEvaluation() {
|
||||
// For now just update the store.
|
||||
// This will be fleshed out in the near future.
|
||||
const evaluationRun: ModelEvaluationRun = {
|
||||
isPreparing: false,
|
||||
variantAnalysisId: undefined,
|
||||
};
|
||||
this.modelingStore.updateModelEvaluationRun(this.dbItem, evaluationRun);
|
||||
}
|
||||
|
||||
private registerToModelingEvents() {
|
||||
this.push(
|
||||
this.modelingEvents.onModelEvaluationRunChanged(async (event) => {
|
||||
if (
|
||||
event.evaluationRun &&
|
||||
event.dbUri === this.dbItem.databaseUri.toString()
|
||||
) {
|
||||
const run: ModelEvaluationRunState = {
|
||||
isPreparing: event.evaluationRun.isPreparing,
|
||||
|
||||
// TODO: Get variant analysis from id.
|
||||
variantAnalysis: undefined,
|
||||
};
|
||||
await this.updateView(run);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { DisposableObject } from "../common/disposable-object";
|
||||
import type { AppEvent, AppEventEmitter } from "../common/events";
|
||||
import type { DatabaseItem } from "../databases/local-databases";
|
||||
import type { Method, Usage } from "./method";
|
||||
import type { ModelEvaluationRun } from "./model-evaluation-run";
|
||||
import type { ModeledMethod } from "./modeled-method";
|
||||
import type { Mode } from "./shared/mode";
|
||||
|
||||
@@ -55,6 +56,11 @@ interface ProcessedByAutoModelMethodsChangedEvent {
|
||||
readonly methods: ReadonlySet<string>;
|
||||
}
|
||||
|
||||
interface ModelEvaluationRunChangedEvent {
|
||||
readonly dbUri: string;
|
||||
readonly evaluationRun: ModelEvaluationRun | undefined;
|
||||
}
|
||||
|
||||
interface RevealInModelEditorEvent {
|
||||
dbUri: string;
|
||||
method: Method;
|
||||
@@ -76,6 +82,7 @@ export class ModelingEvents extends DisposableObject {
|
||||
public readonly onSelectedMethodChanged: AppEvent<SelectedMethodChangedEvent>;
|
||||
public readonly onInProgressMethodsChanged: AppEvent<InProgressMethodsChangedEvent>;
|
||||
public readonly onProcessedByAutoModelMethodsChanged: AppEvent<ProcessedByAutoModelMethodsChangedEvent>;
|
||||
public readonly onModelEvaluationRunChanged: AppEvent<ModelEvaluationRunChangedEvent>;
|
||||
public readonly onRevealInModelEditor: AppEvent<RevealInModelEditorEvent>;
|
||||
public readonly onFocusModelEditor: AppEvent<FocusModelEditorEvent>;
|
||||
|
||||
@@ -90,6 +97,7 @@ export class ModelingEvents extends DisposableObject {
|
||||
private readonly onSelectedMethodChangedEventEmitter: AppEventEmitter<SelectedMethodChangedEvent>;
|
||||
private readonly onInProgressMethodsChangedEventEmitter: AppEventEmitter<InProgressMethodsChangedEvent>;
|
||||
private readonly onProcessedByAutoModelMethodsChangedEventEmitter: AppEventEmitter<ProcessedByAutoModelMethodsChangedEvent>;
|
||||
private readonly onModelEvaluationRunChangedEventEmitter: AppEventEmitter<ModelEvaluationRunChangedEvent>;
|
||||
private readonly onRevealInModelEditorEventEmitter: AppEventEmitter<RevealInModelEditorEvent>;
|
||||
private readonly onFocusModelEditorEventEmitter: AppEventEmitter<FocusModelEditorEvent>;
|
||||
|
||||
@@ -155,6 +163,12 @@ export class ModelingEvents extends DisposableObject {
|
||||
this.onProcessedByAutoModelMethodsChanged =
|
||||
this.onProcessedByAutoModelMethodsChangedEventEmitter.event;
|
||||
|
||||
this.onModelEvaluationRunChangedEventEmitter = this.push(
|
||||
app.createEventEmitter<ModelEvaluationRunChangedEvent>(),
|
||||
);
|
||||
this.onModelEvaluationRunChanged =
|
||||
this.onModelEvaluationRunChangedEventEmitter.event;
|
||||
|
||||
this.onRevealInModelEditorEventEmitter = this.push(
|
||||
app.createEventEmitter<RevealInModelEditorEvent>(),
|
||||
);
|
||||
@@ -273,6 +287,16 @@ export class ModelingEvents extends DisposableObject {
|
||||
});
|
||||
}
|
||||
|
||||
public fireModelEvaluationRunChangedEvent(
|
||||
dbUri: string,
|
||||
evaluationRun: ModelEvaluationRun | undefined,
|
||||
) {
|
||||
this.onModelEvaluationRunChangedEventEmitter.fire({
|
||||
dbUri,
|
||||
evaluationRun,
|
||||
});
|
||||
}
|
||||
|
||||
public fireRevealInModelEditorEvent(dbUri: string, method: Method) {
|
||||
this.onRevealInModelEditorEventEmitter.fire({
|
||||
dbUri,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { DisposableObject } from "../common/disposable-object";
|
||||
import type { DatabaseItem } from "../databases/local-databases";
|
||||
import type { Method, Usage } from "./method";
|
||||
import type { ModelEvaluationRun } from "./model-evaluation-run";
|
||||
import type { ModeledMethod } from "./modeled-method";
|
||||
import type { ModelingEvents } from "./modeling-events";
|
||||
import { INITIAL_HIDE_MODELED_METHODS_VALUE } from "./shared/hide-modeled-methods";
|
||||
@@ -17,6 +18,7 @@ interface InternalDbModelingState {
|
||||
processedByAutoModelMethods: Set<string>;
|
||||
selectedMethod: Method | undefined;
|
||||
selectedUsage: Usage | undefined;
|
||||
modelEvaluationRun: ModelEvaluationRun | undefined;
|
||||
}
|
||||
|
||||
interface DbModelingState {
|
||||
@@ -30,6 +32,7 @@ interface DbModelingState {
|
||||
readonly processedByAutoModelMethods: ReadonlySet<string>;
|
||||
readonly selectedMethod: Method | undefined;
|
||||
readonly selectedUsage: Usage | undefined;
|
||||
readonly modelEvaluationRun: ModelEvaluationRun | undefined;
|
||||
}
|
||||
|
||||
interface SelectedMethodDetails {
|
||||
@@ -66,6 +69,7 @@ export class ModelingStore extends DisposableObject {
|
||||
selectedMethod: undefined,
|
||||
selectedUsage: undefined,
|
||||
inProgressMethods: new Set(),
|
||||
modelEvaluationRun: undefined,
|
||||
});
|
||||
|
||||
this.modelingEvents.fireDbOpenedEvent(databaseItem);
|
||||
@@ -372,6 +376,15 @@ export class ModelingStore extends DisposableObject {
|
||||
});
|
||||
}
|
||||
|
||||
public updateModelEvaluationRun(
|
||||
dbItem: DatabaseItem,
|
||||
evaluationRun: ModelEvaluationRun,
|
||||
) {
|
||||
this.changeModelEvaluationRun(dbItem, (state) => {
|
||||
state.modelEvaluationRun = evaluationRun;
|
||||
});
|
||||
}
|
||||
|
||||
public getSelectedMethodDetails(): SelectedMethodDetails | undefined {
|
||||
const dbState = this.getInternalStateForActiveDb();
|
||||
if (!dbState) {
|
||||
@@ -465,4 +478,18 @@ export class ModelingStore extends DisposableObject {
|
||||
state.processedByAutoModelMethods,
|
||||
);
|
||||
}
|
||||
|
||||
private changeModelEvaluationRun(
|
||||
dbItem: DatabaseItem,
|
||||
updateState: (state: InternalDbModelingState) => void,
|
||||
) {
|
||||
const state = this.getState(dbItem);
|
||||
|
||||
updateState(state);
|
||||
|
||||
this.modelingEvents.fireModelEvaluationRunChangedEvent(
|
||||
dbItem.databaseUri.toString(),
|
||||
state.modelEvaluationRun,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { VariantAnalysisStatus } from "../../variant-analysis/shared/variant-analysis";
|
||||
import type { VariantAnalysis } from "../../variant-analysis/shared/variant-analysis";
|
||||
|
||||
export interface ModelEvaluationRunState {
|
||||
isPreparing: boolean;
|
||||
variantAnalysis: VariantAnalysis | undefined;
|
||||
}
|
||||
|
||||
export function modelEvaluationRunIsRunning(
|
||||
run: ModelEvaluationRunState,
|
||||
): boolean {
|
||||
return (
|
||||
run.isPreparing ||
|
||||
!!(
|
||||
run.variantAnalysis &&
|
||||
run.variantAnalysis.status === VariantAnalysisStatus.InProgress
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -20,6 +20,8 @@ import { Mode } from "../../model-editor/shared/mode";
|
||||
import { getLanguageDisplayName } from "../../common/query-language";
|
||||
import { INITIAL_HIDE_MODELED_METHODS_VALUE } from "../../model-editor/shared/hide-modeled-methods";
|
||||
import type { AccessPathSuggestionOptions } from "../../model-editor/suggestions";
|
||||
import type { ModelEvaluationRunState } from "../../model-editor/shared/model-evaluation-run-state";
|
||||
import { modelEvaluationRunIsRunning } from "../../model-editor/shared/model-evaluation-run-state";
|
||||
|
||||
const LoadingContainer = styled.div`
|
||||
text-align: center;
|
||||
@@ -87,20 +89,20 @@ const ModelEvaluation = ({
|
||||
modifiedSignatures,
|
||||
onStartEvaluation,
|
||||
onStopEvaluation,
|
||||
evaluationInProgress,
|
||||
evaluationRun,
|
||||
}: {
|
||||
viewState: ModelEditorViewState;
|
||||
modeledMethods: Record<string, ModeledMethod[]>;
|
||||
modifiedSignatures: Set<string>;
|
||||
onStartEvaluation: () => void;
|
||||
onStopEvaluation: () => void;
|
||||
evaluationInProgress: boolean;
|
||||
evaluationRun: ModelEvaluationRunState | undefined;
|
||||
}) => {
|
||||
if (!viewState.showEvaluationUi) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!evaluationInProgress) {
|
||||
if (!evaluationRun || !modelEvaluationRunIsRunning(evaluationRun)) {
|
||||
const customModelsExist = Object.values(modeledMethods).some(
|
||||
(methods) => methods.filter((m) => m.type !== "none").length > 0,
|
||||
);
|
||||
@@ -166,7 +168,9 @@ export function ModelEditor({
|
||||
string | null
|
||||
>(null);
|
||||
|
||||
const [evaluationInProgress, setEvaluationInProgress] = useState(false);
|
||||
const [evaluationRun, setEvaluationRun] = useState<
|
||||
ModelEvaluationRunState | undefined
|
||||
>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
vscode.postMessage({
|
||||
@@ -214,6 +218,9 @@ export function ModelEditor({
|
||||
case "setAccessPathSuggestions":
|
||||
setAccessPathSuggestions(msg.accessPathSuggestions);
|
||||
break;
|
||||
case "setModelEvaluationRun":
|
||||
setEvaluationRun(msg.run);
|
||||
break;
|
||||
default:
|
||||
assertNever(msg);
|
||||
}
|
||||
@@ -309,14 +316,12 @@ export function ModelEditor({
|
||||
);
|
||||
|
||||
const onStartEvaluation = useCallback(() => {
|
||||
setEvaluationInProgress(true);
|
||||
vscode.postMessage({
|
||||
t: "startModelEvaluation",
|
||||
});
|
||||
}, []);
|
||||
|
||||
const onStopEvaluation = useCallback(() => {
|
||||
setEvaluationInProgress(false);
|
||||
vscode.postMessage({
|
||||
t: "stopModelEvaluation",
|
||||
});
|
||||
@@ -447,7 +452,7 @@ export function ModelEditor({
|
||||
modifiedSignatures={modifiedSignatures}
|
||||
onStartEvaluation={onStartEvaluation}
|
||||
onStopEvaluation={onStopEvaluation}
|
||||
evaluationInProgress={evaluationInProgress}
|
||||
evaluationRun={evaluationRun}
|
||||
/>
|
||||
</ButtonsContainer>
|
||||
</HeaderRow>
|
||||
|
||||
@@ -13,6 +13,7 @@ export function createMockModelingEvents({
|
||||
onProcessedByAutoModelMethodsChanged = jest.fn(),
|
||||
onRevealInModelEditor = jest.fn(),
|
||||
onFocusModelEditor = jest.fn(),
|
||||
onModelEvaluationRunChanged = jest.fn(),
|
||||
}: {
|
||||
onActiveDbChanged?: ModelingEvents["onActiveDbChanged"];
|
||||
onDbClosed?: ModelingEvents["onDbClosed"];
|
||||
@@ -25,6 +26,7 @@ export function createMockModelingEvents({
|
||||
onProcessedByAutoModelMethodsChanged?: ModelingEvents["onProcessedByAutoModelMethodsChanged"];
|
||||
onRevealInModelEditor?: ModelingEvents["onRevealInModelEditor"];
|
||||
onFocusModelEditor?: ModelingEvents["onFocusModelEditor"];
|
||||
onModelEvaluationRunChanged?: ModelingEvents["onModelEvaluationRunChanged"];
|
||||
} = {}): ModelingEvents {
|
||||
return mockedObject<ModelingEvents>({
|
||||
onActiveDbChanged,
|
||||
@@ -38,5 +40,6 @@ export function createMockModelingEvents({
|
||||
onProcessedByAutoModelMethodsChanged,
|
||||
onRevealInModelEditor,
|
||||
onFocusModelEditor,
|
||||
onModelEvaluationRunChanged,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user