Merge pull request #2784 from github/robertbrignull/saving-progress

Make progress notifications more useful when calling loadExternalApiUsages
This commit is contained in:
Robert
2023-09-07 16:35:28 +01:00
committed by GitHub
2 changed files with 108 additions and 60 deletions

View File

@@ -58,6 +58,8 @@ export async function prepareExternalApiQuery(
return true;
}
export const externalApiQueriesProgressMaxStep = 2000;
export async function runExternalApiQueries(
mode: Mode,
{
@@ -76,6 +78,11 @@ export async function runExternalApiQueries(
// For a reference of what this should do in the future, see the previous implementation in
// https://github.com/github/vscode-codeql/blob/089d3566ef0bc67d9b7cc66e8fd6740b31c1c0b0/extensions/ql-vscode/src/data-extensions-editor/external-api-usage-query.ts#L33-L72
progress({
message: "Resolving QL packs",
step: 1,
maxStep: externalApiQueriesProgressMaxStep,
});
const additionalPacks = getOnDiskWorkspaceFolders();
const extensionPacks = Object.keys(
await cliServer.resolveQlpacks(additionalPacks, true),
@@ -92,7 +99,12 @@ export async function runExternalApiQueries(
queryStorageDir,
additionalPacks,
extensionPacks,
progress,
progress: (update) =>
progress({
step: update.step + 500,
maxStep: externalApiQueriesProgressMaxStep,
message: update.message,
}),
token,
// We need to create a lock file, because the query is inside our own pack
createLockFile: true,
@@ -105,8 +117,8 @@ export async function runExternalApiQueries(
// Read the results and covert to internal representation
progress({
message: "Decoding results",
step: 1100,
maxStep: 1500,
step: 1600,
maxStep: externalApiQueriesProgressMaxStep,
});
const bqrsChunk = await readQueryResults({
@@ -119,8 +131,8 @@ export async function runExternalApiQueries(
progress({
message: "Finalizing results",
step: 1450,
maxStep: 1500,
step: 1950,
maxStep: externalApiQueriesProgressMaxStep,
});
return decodeBqrsToExternalApiUsages(bqrsChunk);

View File

@@ -27,7 +27,10 @@ import { promptImportGithubDatabase } from "../databases/database-fetcher";
import { App } from "../common/app";
import { showResolvableLocation } from "../databases/local-databases/locations";
import { redactableError } from "../common/errors";
import { runExternalApiQueries } from "./external-api-usage-queries";
import {
externalApiQueriesProgressMaxStep,
runExternalApiQueries,
} from "./external-api-usage-queries";
import { Method, Usage } from "./method";
import { ModeledMethod } from "./modeled-method";
import { ExtensionPack } from "./shared/extension-pack";
@@ -190,7 +193,10 @@ export class ModelEditorView extends AbstractWebview<
break;
case "refreshMethods":
await this.loadExternalApiUsages();
await withProgress((progress) => this.loadExternalApiUsages(progress), {
cancellable: false,
});
void telemetryListener?.sendUIInteraction(
"model-editor-refresh-methods",
);
@@ -202,17 +208,39 @@ export class ModelEditorView extends AbstractWebview<
break;
case "saveModeledMethods":
await saveModeledMethods(
this.extensionPack,
this.databaseItem.name,
this.databaseItem.language,
msg.methods,
msg.modeledMethods,
this.mode,
this.cliServer,
this.app.logger,
await withProgress(
async (progress) => {
progress({
step: 1,
maxStep: 500 + externalApiQueriesProgressMaxStep,
message: "Writing model files",
});
await saveModeledMethods(
this.extensionPack,
this.databaseItem.name,
this.databaseItem.language,
msg.methods,
msg.modeledMethods,
this.mode,
this.cliServer,
this.app.logger,
);
await Promise.all([
this.setViewState(),
this.loadExternalApiUsages((update) =>
progress({
...update,
step: update.step + 500,
maxStep: 500 + externalApiQueriesProgressMaxStep,
}),
),
]);
},
{
cancellable: false,
},
);
await Promise.all([this.setViewState(), this.loadExternalApiUsages()]);
void telemetryListener?.sendUIInteraction(
"model-editor-save-modeled-methods",
);
@@ -249,7 +277,12 @@ export class ModelEditorView extends AbstractWebview<
break;
case "switchMode":
this.mode = msg.mode;
await Promise.all([this.setViewState(), this.loadExternalApiUsages()]);
await Promise.all([
this.setViewState(),
withProgress((progress) => this.loadExternalApiUsages(progress), {
cancellable: false,
}),
]);
void telemetryListener?.sendUIInteraction("model-editor-switch-modes");
break;
@@ -274,7 +307,9 @@ export class ModelEditorView extends AbstractWebview<
await Promise.all([
this.setViewState(),
this.loadExternalApiUsages(),
withProgress((progress) => this.loadExternalApiUsages(progress), {
cancellable: false,
}),
this.loadExistingModeledMethods(),
]);
}
@@ -317,48 +352,49 @@ export class ModelEditorView extends AbstractWebview<
}
}
protected async loadExternalApiUsages(): Promise<void> {
await withProgress(
async (progress) => {
try {
const cancellationTokenSource = new CancellationTokenSource();
const queryResult = await runExternalApiQueries(this.mode, {
cliServer: this.cliServer,
queryRunner: this.queryRunner,
databaseItem: this.databaseItem,
queryStorageDir: this.queryStorageDir,
queryDir: this.queryDir,
progress: (update) => progress({ ...update, maxStep: 1500 }),
token: cancellationTokenSource.token,
});
if (!queryResult) {
return;
}
this.methods = queryResult;
protected async loadExternalApiUsages(
progress: ProgressCallback,
): Promise<void> {
try {
const cancellationTokenSource = new CancellationTokenSource();
const queryResult = await runExternalApiQueries(this.mode, {
cliServer: this.cliServer,
queryRunner: this.queryRunner,
databaseItem: this.databaseItem,
queryStorageDir: this.queryStorageDir,
queryDir: this.queryDir,
progress: (update) =>
progress({
...update,
message: `Loading models: ${update.message}`,
}),
token: cancellationTokenSource.token,
});
if (!queryResult) {
return;
}
this.methods = queryResult;
await this.postMessage({
t: "setMethods",
methods: this.methods,
});
if (this.isMostRecentlyActiveView(this)) {
await this.updateMethodsUsagePanelState(
this.methods,
this.databaseItem,
this.hideModeledApis,
);
}
} catch (err) {
void showAndLogExceptionWithTelemetry(
this.app.logger,
this.app.telemetry,
redactableError(
asError(err),
)`Failed to load external API usages: ${getErrorMessage(err)}`,
);
}
},
{ cancellable: false },
);
await this.postMessage({
t: "setMethods",
methods: this.methods,
});
if (this.isMostRecentlyActiveView(this)) {
await this.updateMethodsUsagePanelState(
this.methods,
this.databaseItem,
this.hideModeledApis,
);
}
} catch (err) {
void showAndLogExceptionWithTelemetry(
this.app.logger,
this.app.telemetry,
redactableError(
asError(err),
)`Failed to load external API usages: ${getErrorMessage(err)}`,
);
}
}
protected async generateModeledMethods(): Promise<void> {