Skip to content

Commit 91428b2

Browse files
committed
Prevent refreshing in parallel
While adding an automatic refresh I discovered it was easy to accidentally cause two refreshes to go off at the same time which causes some races.
1 parent 5054d75 commit 91428b2

File tree

1 file changed

+38
-16
lines changed

1 file changed

+38
-16
lines changed

src/workspacesProvider.ts

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export enum WorkspaceQuery {
1414
export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
1515
private workspaces: WorkspaceTreeItem[] = []
1616
private agentWatchers: Record<WorkspaceAgent["id"], { dispose: () => void; metadata?: AgentMetadataEvent[] }> = {}
17+
private fetching = false
1718

1819
constructor(
1920
private readonly getWorkspacesQuery: WorkspaceQuery,
@@ -22,26 +23,47 @@ export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeIte
2223
this.fetchAndRefresh()
2324
}
2425

25-
// fetchAndRefrehsh fetches new workspaces then re-renders the entire tree.
26+
// fetchAndRefresh fetches new workspaces then re-renders the entire tree.
27+
// Trying to call this while already refreshing is a no-op and will return
28+
// immediately.
2629
async fetchAndRefresh() {
30+
if (this.fetching) {
31+
return
32+
}
33+
this.fetching = true
34+
35+
const dispose = () => {
36+
Object.values(this.agentWatchers).forEach((watcher) => watcher.dispose())
37+
this.workspaces = []
38+
this.fetching = false
39+
}
40+
41+
// Assume that no URL or no token means we are not logged in.
42+
const url = this.storage.getURL()
2743
const token = await this.storage.getSessionToken()
28-
const workspacesTreeItem: WorkspaceTreeItem[] = []
29-
Object.values(this.agentWatchers).forEach((watcher) => watcher.dispose())
30-
// If the URL is set then we are logged in.
31-
if (this.storage.getURL()) {
32-
const resp = await getWorkspaces({ q: this.getWorkspacesQuery })
33-
resp.workspaces.forEach((workspace) => {
34-
const showMetadata = this.getWorkspacesQuery === WorkspaceQuery.Mine
35-
if (showMetadata && token) {
36-
const agents = extractAgents(workspace)
37-
agents.forEach((agent) => this.monitorMetadata(agent.id, token)) // monitor metadata for all agents
38-
}
39-
const treeItem = new WorkspaceTreeItem(workspace, this.getWorkspacesQuery === WorkspaceQuery.All, showMetadata)
40-
workspacesTreeItem.push(treeItem)
41-
})
44+
if (!url || !token) {
45+
return dispose()
4246
}
43-
this.workspaces = workspacesTreeItem
47+
48+
const resp = await getWorkspaces({ q: this.getWorkspacesQuery })
49+
50+
// We could have logged out while waiting for the query.
51+
if (!url || !token) {
52+
return dispose()
53+
}
54+
55+
this.workspaces = resp.workspaces.map((workspace) => {
56+
const showMetadata = this.getWorkspacesQuery === WorkspaceQuery.Mine
57+
if (showMetadata && token) {
58+
const agents = extractAgents(workspace)
59+
agents.forEach((agent) => this.monitorMetadata(agent.id, token)) // monitor metadata for all agents
60+
}
61+
return new WorkspaceTreeItem(workspace, this.getWorkspacesQuery === WorkspaceQuery.All, showMetadata)
62+
})
63+
4464
this.refresh()
65+
66+
this.fetching = false
4567
}
4668

4769
private _onDidChangeTreeData: vscode.EventEmitter<vscode.TreeItem | undefined | null | void> =

0 commit comments

Comments
 (0)