Skip to content

Commit 1f6d8f2

Browse files
Merge branch 'main' into robertbrignull/discovery-logging
2 parents a4a6785 + 00bd7b7 commit 1f6d8f2

File tree

12 files changed

+106
-110
lines changed

12 files changed

+106
-110
lines changed

.github/codeql/queries/assert-pure.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class PureFile extends File {
1919
this.getRelativePath().regexpMatch(".*/src/pure/.*") or
2020
this.getRelativePath().regexpMatch(".*/src/common/.*")
2121
) and
22-
not this.getRelativePath().regexpMatch(".*/src/common/vscode/.*")
22+
not this.getRelativePath().regexpMatch(".*/vscode/.*")
2323
}
2424
}
2525

extensions/ql-vscode/src/common/discovery.ts

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,28 @@ import { Logger } from "./logging";
88
* same time.
99
*/
1010
export abstract class Discovery<T> extends DisposableObject {
11-
private retry = false;
12-
private discoveryInProgress = false;
11+
private restartWhenFinished = false;
12+
private currentDiscoveryPromise: Promise<void> | undefined;
1313

1414
constructor(private readonly name: string, private readonly logger: Logger) {
1515
super();
1616
}
1717

18+
/**
19+
* Returns the promise of the currently running refresh operation, if one is in progress.
20+
* Otherwise returns a promise that resolves immediately.
21+
*/
22+
public waitForCurrentRefresh(): Promise<void> {
23+
return this.currentDiscoveryPromise ?? Promise.resolve();
24+
}
25+
1826
/**
1927
* Force the discovery process to run. Normally invoked by the derived class when a relevant file
2028
* system change is detected.
29+
*
30+
* Returns a promise that resolves when the refresh is complete, including any retries.
2131
*/
22-
public refresh(): void {
32+
public refresh(): Promise<void> {
2333
// We avoid having multiple discovery operations in progress at the same time. Otherwise, if we
2434
// got a storm of refresh requests due to, say, the copying or deletion of a large directory
2535
// tree, we could potentially spawn a separate simultaneous discovery operation for each
@@ -36,49 +46,48 @@ export abstract class Discovery<T> extends DisposableObject {
3646
// other change notifications that might be coming along. However, this would create more
3747
// latency in the common case, in order to save a bit of latency in the uncommon case.
3848

39-
if (this.discoveryInProgress) {
49+
if (this.currentDiscoveryPromise !== undefined) {
4050
// There's already a discovery operation in progress. Tell it to restart when it's done.
41-
this.retry = true;
51+
this.restartWhenFinished = true;
4252
} else {
4353
// No discovery in progress, so start one now.
44-
this.discoveryInProgress = true;
45-
this.launchDiscovery();
54+
this.currentDiscoveryPromise = this.launchDiscovery().finally(() => {
55+
this.currentDiscoveryPromise = undefined;
56+
});
4657
}
58+
return this.currentDiscoveryPromise;
4759
}
4860

4961
/**
5062
* Starts the asynchronous discovery operation by invoking the `discover` function. When the
5163
* discovery operation completes, the `update` function will be invoked with the results of the
5264
* discovery.
5365
*/
54-
private launchDiscovery(): void {
55-
const discoveryPromise = this.discover();
56-
discoveryPromise
57-
.then((results) => {
58-
if (!this.retry) {
59-
// Update any listeners with the results of the discovery.
60-
this.discoveryInProgress = false;
61-
this.update(results);
62-
}
63-
})
64-
65-
.catch((err: unknown) => {
66-
void this.logger.log(
67-
`${this.name} failed. Reason: ${getErrorMessage(err)}`,
68-
);
69-
})
66+
private async launchDiscovery(): Promise<void> {
67+
let results: T | undefined;
68+
try {
69+
results = await this.discover();
70+
} catch (err) {
71+
void this.logger.log(
72+
`${this.name} failed. Reason: ${getErrorMessage(err)}`,
73+
);
74+
results = undefined;
75+
}
7076

71-
.finally(() => {
72-
if (this.retry) {
73-
// Another refresh request came in while we were still running a previous discovery
74-
// operation. Since the discovery results we just computed are now stale, we'll launch
75-
// another discovery operation instead of updating.
76-
// Note that by doing this inside of `finally`, we will relaunch discovery even if the
77-
// initial discovery operation failed.
78-
this.retry = false;
79-
this.launchDiscovery();
80-
}
81-
});
77+
if (this.restartWhenFinished) {
78+
// Another refresh request came in while we were still running a previous discovery
79+
// operation. Since the discovery results we just computed are now stale, we'll launch
80+
// another discovery operation instead of updating.
81+
// We want to relaunch discovery regardless of if the initial discovery operation
82+
// succeeded or failed.
83+
this.restartWhenFinished = false;
84+
await this.launchDiscovery();
85+
} else {
86+
// If the discovery was successful, then update any listeners with the results.
87+
if (results !== undefined) {
88+
this.update(results);
89+
}
90+
}
8291
}
8392

8493
/**

extensions/ql-vscode/src/common/selection-commands.ts renamed to extensions/ql-vscode/src/common/vscode/selection-commands.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { showAndLogErrorMessage } from "../helpers";
1+
import { showAndLogErrorMessage } from "../../helpers";
22
import {
33
ExplorerSelectionCommandFunction,
44
TreeViewContextMultiSelectionCommandFunction,
55
TreeViewContextSingleSelectionCommandFunction,
6-
} from "./commands";
6+
} from "../commands";
77

88
// A hack to match types that are not an array, which is useful to help avoid
99
// misusing createSingleSelectionCommand, e.g. where T accidentally gets instantiated

extensions/ql-vscode/src/databases/local-databases-ui.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ import { LocalDatabasesCommands } from "../common/commands";
4949
import {
5050
createMultiSelectionCommand,
5151
createSingleSelectionCommand,
52-
} from "../common/selection-commands";
52+
} from "../common/vscode/selection-commands";
5353

5454
enum SortOrder {
5555
NameAsc = "NameAsc",

extensions/ql-vscode/src/local-queries/local-queries.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ import { App } from "../common/app";
4747
import { DisposableObject } from "../pure/disposable-object";
4848
import { SkeletonQueryWizard } from "../skeleton-query-wizard";
4949
import { LocalQueryRun } from "./local-query-run";
50-
import { createMultiSelectionCommand } from "../common/selection-commands";
50+
import { createMultiSelectionCommand } from "../common/vscode/selection-commands";
5151

5252
interface DatabaseQuickPickItem extends QuickPickItem {
5353
databaseItem: DatabaseItem;

extensions/ql-vscode/src/queries-panel/queries-module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class QueriesModule extends DisposableObject {
2121

2222
const queryDiscovery = new QueryDiscovery(app, cliServer);
2323
this.push(queryDiscovery);
24-
queryDiscovery.refresh();
24+
void queryDiscovery.refresh();
2525

2626
const queriesPanel = new QueriesPanel(queryDiscovery);
2727
this.push(queriesPanel);

extensions/ql-vscode/src/query-history/query-history-manager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ import { tryOpenExternalFile } from "../common/vscode/external-files";
5959
import {
6060
createMultiSelectionCommand,
6161
createSingleSelectionCommand,
62-
} from "../common/selection-commands";
62+
} from "../common/vscode/selection-commands";
6363

6464
/**
6565
* query-history-manager.ts

extensions/ql-vscode/src/query-testing/qltest-discovery.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export class QLTestDiscovery extends Discovery<QLTestDiscoveryResults> {
6565

6666
private handleDidChange(uri: Uri): void {
6767
if (!QLTestDiscovery.ignoreTestPath(uri.fsPath)) {
68-
this.refresh();
68+
void this.refresh();
6969
}
7070
}
7171
protected async discover(): Promise<QLTestDiscoveryResults> {

extensions/ql-vscode/src/query-testing/test-adapter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ export class QLTestAdapter extends DisposableObject implements TestAdapter {
115115
this.qlTestDiscovery = this.push(
116116
new QLTestDiscovery(workspaceFolder, cliServer),
117117
);
118-
this.qlTestDiscovery.refresh();
118+
void this.qlTestDiscovery.refresh();
119119

120120
this.push(this.qlTestDiscovery.onDidChangeTests(this.discoverTests, this));
121121
}

extensions/ql-vscode/src/query-testing/test-manager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ class WorkspaceFolderHandler extends DisposableObject {
9292
this.push(
9393
this.testDiscovery.onDidChangeTests(this.handleDidChangeTests, this),
9494
);
95-
this.testDiscovery.refresh();
95+
void this.testDiscovery.refresh();
9696
}
9797

9898
private handleDidChangeTests(): void {

0 commit comments

Comments
 (0)