Skip to content

Commit dd7a77d

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 dd7a77d

File tree

1 file changed

+42
-17
lines changed

1 file changed

+42
-17
lines changed

src/workspacesProvider.ts

Lines changed: 42 additions & 17 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,50 @@ 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() {
27-
const token = await this.storage.getSessionToken()
28-
const workspacesTreeItem: WorkspaceTreeItem[] = []
30+
if (this.fetching) {
31+
return
32+
}
33+
this.fetching = true
34+
2935
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-
})
36+
37+
try {
38+
this.workspaces = await this.fetch()
39+
this.refresh()
40+
} catch (error) {
41+
this.workspaces = []
42+
}
43+
44+
this.fetching = false
45+
}
46+
47+
async fetch(): Promise<WorkspaceTreeItem[]> {
48+
// Assume that no URL or no token means we are not logged in.
49+
const url = this.storage.getURL()
50+
const token = await this.storage.getSessionToken()
51+
if (!url || !token) {
52+
throw new Error("not logged in")
53+
}
54+
55+
const resp = await getWorkspaces({ q: this.getWorkspacesQuery })
56+
57+
// We could have logged out while waiting for the query.
58+
if (!url || !token) {
59+
throw new Error("not logged in")
4260
}
43-
this.workspaces = workspacesTreeItem
44-
this.refresh()
61+
62+
return resp.workspaces.map((workspace) => {
63+
const showMetadata = this.getWorkspacesQuery === WorkspaceQuery.Mine
64+
if (showMetadata && token) {
65+
const agents = extractAgents(workspace)
66+
agents.forEach((agent) => this.monitorMetadata(agent.id, token)) // monitor metadata for all agents
67+
}
68+
return new WorkspaceTreeItem(workspace, this.getWorkspacesQuery === WorkspaceQuery.All, showMetadata)
69+
})
4570
}
4671

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

0 commit comments

Comments
 (0)