Skip to content

Commit 4d599d2

Browse files
authored
Refresh workspaces when logging in and out (#124)
1 parent 3ab3aad commit 4d599d2

File tree

3 files changed

+44
-31
lines changed

3 files changed

+44
-31
lines changed

src/commands.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ export class Commands {
108108
vscode.commands.executeCommand("coder.open")
109109
}
110110
})
111+
vscode.commands.executeCommand("coder.refreshWorkspaces")
111112
} catch (error) {
112113
vscode.window.showErrorMessage("Failed to authenticate with Coder: " + error)
113114
}
@@ -122,6 +123,7 @@ export class Commands {
122123
vscode.commands.executeCommand("coder.login")
123124
}
124125
})
126+
vscode.commands.executeCommand("coder.refreshWorkspaces")
125127
}
126128

127129
public async createWorkspace(): Promise<void> {

src/extension.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,8 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
138138
commands.navigateToWorkspaceSettings.bind(commands),
139139
)
140140
vscode.commands.registerCommand("coder.refreshWorkspaces", () => {
141-
myWorkspacesProvider.refresh()
142-
allWorkspacesProvider.refresh()
141+
myWorkspacesProvider.fetchAndRefresh()
142+
allWorkspacesProvider.fetchAndRefresh()
143143
})
144144

145145
// Since the "onResolveRemoteAuthority:ssh-remote" activation event exists

src/workspacesProvider.ts

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,38 +13,40 @@ export enum WorkspaceQuery {
1313

1414
export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
1515
private workspaces: WorkspaceTreeItem[] = []
16-
private agentMetadata: Record<WorkspaceAgent["id"], AgentMetadataEvent[]> = {}
16+
private agentWatchers: Record<WorkspaceAgent["id"], { dispose: () => void; metadata?: AgentMetadataEvent[] }> = {}
1717

1818
constructor(private readonly getWorkspacesQuery: WorkspaceQuery, private readonly storage: Storage) {
19-
getWorkspaces({ q: this.getWorkspacesQuery })
20-
.then((workspaces) => {
21-
const workspacesTreeItem: WorkspaceTreeItem[] = []
22-
workspaces.workspaces.forEach((workspace) => {
23-
const showMetadata = this.getWorkspacesQuery === WorkspaceQuery.Mine
24-
if (showMetadata) {
25-
const agents = extractAgents(workspace)
26-
agents.forEach((agent) => this.monitorMetadata(agent.id)) // monitor metadata for all agents
27-
}
28-
const treeItem = new WorkspaceTreeItem(
29-
workspace,
30-
this.getWorkspacesQuery === WorkspaceQuery.All,
31-
showMetadata,
32-
)
33-
workspacesTreeItem.push(treeItem)
34-
})
35-
return workspacesTreeItem
36-
})
37-
.then((workspaces) => {
38-
this.workspaces = workspaces
39-
this.refresh()
19+
this.fetchAndRefresh()
20+
}
21+
22+
// fetchAndRefrehsh fetches new workspaces then re-renders the entire tree.
23+
async fetchAndRefresh() {
24+
const token = await this.storage.getSessionToken()
25+
const workspacesTreeItem: WorkspaceTreeItem[] = []
26+
Object.values(this.agentWatchers).forEach((watcher) => watcher.dispose())
27+
// If the URL is set then we are logged in.
28+
if (this.storage.getURL()) {
29+
const resp = await getWorkspaces({ q: this.getWorkspacesQuery })
30+
resp.workspaces.forEach((workspace) => {
31+
const showMetadata = this.getWorkspacesQuery === WorkspaceQuery.Mine
32+
if (showMetadata && token) {
33+
const agents = extractAgents(workspace)
34+
agents.forEach((agent) => this.monitorMetadata(agent.id, token)) // monitor metadata for all agents
35+
}
36+
const treeItem = new WorkspaceTreeItem(workspace, this.getWorkspacesQuery === WorkspaceQuery.All, showMetadata)
37+
workspacesTreeItem.push(treeItem)
4038
})
39+
}
40+
this.workspaces = workspacesTreeItem
41+
this.refresh()
4142
}
4243

4344
private _onDidChangeTreeData: vscode.EventEmitter<vscode.TreeItem | undefined | null | void> =
4445
new vscode.EventEmitter<vscode.TreeItem | undefined | null | void>()
4546
readonly onDidChangeTreeData: vscode.Event<vscode.TreeItem | undefined | null | void> =
4647
this._onDidChangeTreeData.event
4748

49+
// refresh causes the tree to re-render. It does not fetch fresh workspaces.
4850
refresh(item: vscode.TreeItem | undefined | null | void): void {
4951
this._onDidChangeTreeData.fire(item)
5052
}
@@ -62,7 +64,7 @@ export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeIte
6264
)
6365
return Promise.resolve(agentTreeItems)
6466
} else if (element instanceof AgentTreeItem) {
65-
const savedMetadata = this.agentMetadata[element.agent.id] || []
67+
const savedMetadata = this.agentWatchers[element.agent.id]?.metadata || []
6668
return Promise.resolve(savedMetadata.map((metadata) => new AgentMetadataTreeItem(metadata)))
6769
}
6870

@@ -71,30 +73,39 @@ export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeIte
7173
return Promise.resolve(this.workspaces)
7274
}
7375

74-
async monitorMetadata(agentId: WorkspaceAgent["id"]): Promise<void> {
76+
// monitorMetadata opens an SSE endpoint to monitor metadata on the specified
77+
// agent and registers a disposer that can be used to stop the watch.
78+
monitorMetadata(agentId: WorkspaceAgent["id"], token: string): void {
7579
const agentMetadataURL = new URL(`${this.storage.getURL()}/api/v2/workspaceagents/${agentId}/watch-metadata`)
7680
const agentMetadataEventSource = new EventSource(agentMetadataURL.toString(), {
7781
headers: {
78-
"Coder-Session-Token": await this.storage.getSessionToken(),
82+
"Coder-Session-Token": token,
7983
},
8084
})
8185

86+
this.agentWatchers[agentId] = {
87+
dispose: () => {
88+
delete this.agentWatchers[agentId]
89+
agentMetadataEventSource.close()
90+
},
91+
}
92+
8293
agentMetadataEventSource.addEventListener("data", (event) => {
8394
try {
8495
const dataEvent = JSON.parse(event.data)
8596
const agentMetadata = AgentMetadataEventSchemaArray.parse(dataEvent)
8697

8798
if (agentMetadata.length === 0) {
88-
agentMetadataEventSource.close()
99+
this.agentWatchers[agentId].dispose()
89100
}
90101

91-
const savedMetadata = this.agentMetadata[agentId]
102+
const savedMetadata = this.agentWatchers[agentId].metadata
92103
if (JSON.stringify(savedMetadata) !== JSON.stringify(agentMetadata)) {
93-
this.agentMetadata[agentId] = agentMetadata // overwrite existing metadata
104+
this.agentWatchers[agentId].metadata = agentMetadata // overwrite existing metadata
94105
this.refresh()
95106
}
96107
} catch (error) {
97-
agentMetadataEventSource.close()
108+
this.agentWatchers[agentId].dispose()
98109
}
99110
})
100111
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy