diff --git a/src/workspacesProvider.ts b/src/workspacesProvider.ts index f485b9d5..fba0f65a 100644 --- a/src/workspacesProvider.ts +++ b/src/workspacesProvider.ts @@ -14,6 +14,7 @@ export enum WorkspaceQuery { export class WorkspaceProvider implements vscode.TreeDataProvider { private workspaces: WorkspaceTreeItem[] = [] private agentWatchers: Record void; metadata?: AgentMetadataEvent[] }> = {} + private fetching = false constructor( private readonly getWorkspacesQuery: WorkspaceQuery, @@ -22,26 +23,63 @@ export class WorkspaceProvider implements vscode.TreeDataProvider 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() + } catch (error) { + this.workspaces = [] } - this.workspaces = workspacesTreeItem + this.refresh() + this.fetching = false + } + + /** + * Fetch workspaces and turn them into tree items. Throw an error if not + * logged in or the query fails. + */ + async fetch(): Promise { + // 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, or logged into a + // different deployment. + const url2 = this.storage.getURL() + const token2 = await this.storage.getSessionToken() + if (!url2 || !token2) { + throw new Error("not logged in") + } else if (url !== url2) { + // In this case we need to fetch from the new deployment instead. + // TODO: It would be better to cancel this fetch when that happens, + // because this means we have to wait for the old fetch to finish before + // finally getting workspaces for the new one. + return this.fetch() + } + + return resp.workspaces.map((workspace) => { + const showMetadata = this.getWorkspacesQuery === WorkspaceQuery.Mine + if (showMetadata) { + const agents = extractAgents(workspace) + agents.forEach((agent) => this.monitorMetadata(agent.id, url, token2)) // monitor metadata for all agents + } + return new WorkspaceTreeItem(workspace, this.getWorkspacesQuery === WorkspaceQuery.All, showMetadata) + }) } private _onDidChangeTreeData: vscode.EventEmitter = @@ -78,8 +116,8 @@ export class WorkspaceProvider implements vscode.TreeDataProvider