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

+2
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

+2-2
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

+40-29
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)