Skip to content

Commit

Permalink
Prevent refreshing in parallel
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
code-asher committed Feb 1, 2024
1 parent 5054d75 commit dd7a77d
Showing 1 changed file with 42 additions and 17 deletions.
59 changes: 42 additions & 17 deletions src/workspacesProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export enum WorkspaceQuery {
export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
private workspaces: WorkspaceTreeItem[] = []
private agentWatchers: Record<WorkspaceAgent["id"], { dispose: () => void; metadata?: AgentMetadataEvent[] }> = {}
private fetching = false

constructor(
private readonly getWorkspacesQuery: WorkspaceQuery,
Expand All @@ -22,26 +23,50 @@ export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeIte
this.fetchAndRefresh()
}

// fetchAndRefrehsh fetches new workspaces then re-renders the entire tree.
// fetchAndRefresh fetches new workspaces then re-renders the entire tree.
// Trying to call this while already refreshing is a no-op and will return
// immediately.
async fetchAndRefresh() {
const token = await this.storage.getSessionToken()
const workspacesTreeItem: WorkspaceTreeItem[] = []
if (this.fetching) {
return
}
this.fetching = true

Object.values(this.agentWatchers).forEach((watcher) => watcher.dispose())
// If the URL is set then we are logged in.
if (this.storage.getURL()) {
const resp = await getWorkspaces({ q: this.getWorkspacesQuery })
resp.workspaces.forEach((workspace) => {
const showMetadata = this.getWorkspacesQuery === WorkspaceQuery.Mine
if (showMetadata && token) {
const agents = extractAgents(workspace)
agents.forEach((agent) => this.monitorMetadata(agent.id, token)) // monitor metadata for all agents
}
const treeItem = new WorkspaceTreeItem(workspace, this.getWorkspacesQuery === WorkspaceQuery.All, showMetadata)
workspacesTreeItem.push(treeItem)
})

try {
this.workspaces = await this.fetch()
this.refresh()
} catch (error) {
this.workspaces = []
}

this.fetching = false
}

async fetch(): Promise<WorkspaceTreeItem[]> {
// Assume that no URL or no token means we are not logged in.
const url = this.storage.getURL()
const token = await this.storage.getSessionToken()
if (!url || !token) {
throw new Error("not logged in")
}

const resp = await getWorkspaces({ q: this.getWorkspacesQuery })

// We could have logged out while waiting for the query.
if (!url || !token) {
throw new Error("not logged in")
}
this.workspaces = workspacesTreeItem
this.refresh()

return resp.workspaces.map((workspace) => {
const showMetadata = this.getWorkspacesQuery === WorkspaceQuery.Mine
if (showMetadata && token) {
const agents = extractAgents(workspace)
agents.forEach((agent) => this.monitorMetadata(agent.id, token)) // monitor metadata for all agents
}
return new WorkspaceTreeItem(workspace, this.getWorkspacesQuery === WorkspaceQuery.All, showMetadata)
})
}

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

0 comments on commit dd7a77d

Please sign in to comment.