@@ -13,23 +13,25 @@ export enum WorkspaceQuery {
13
13
14
14
export class WorkspaceProvider implements vscode . TreeDataProvider < vscode . TreeItem > {
15
15
private workspaces : WorkspaceTreeItem [ ] = [ ]
16
- private agentMetadata : Record < WorkspaceAgent [ "id" ] , AgentMetadataEvent [ ] > = { }
16
+ private agentWatchers : Record < WorkspaceAgent [ "id" ] , { dispose : ( ) => void ; metadata ?: AgentMetadataEvent [ ] } > = { }
17
17
18
18
constructor ( private readonly getWorkspacesQuery : WorkspaceQuery , private readonly storage : Storage ) {
19
19
this . fetchAndRefresh ( )
20
20
}
21
21
22
22
// fetchAndRefrehsh fetches new workspaces then re-renders the entire tree.
23
23
async fetchAndRefresh ( ) {
24
+ const token = await this . storage . getSessionToken ( )
24
25
const workspacesTreeItem : WorkspaceTreeItem [ ] = [ ]
26
+ Object . values ( this . agentWatchers ) . forEach ( ( watcher ) => watcher . dispose ( ) )
25
27
// If the URL is set then we are logged in.
26
28
if ( this . storage . getURL ( ) ) {
27
29
const resp = await getWorkspaces ( { q : this . getWorkspacesQuery } )
28
30
resp . workspaces . forEach ( ( workspace ) => {
29
31
const showMetadata = this . getWorkspacesQuery === WorkspaceQuery . Mine
30
- if ( showMetadata ) {
32
+ if ( showMetadata && token ) {
31
33
const agents = extractAgents ( workspace )
32
- agents . forEach ( ( agent ) => this . monitorMetadata ( agent . id ) ) // monitor metadata for all agents
34
+ agents . forEach ( ( agent ) => this . monitorMetadata ( agent . id , token ) ) // monitor metadata for all agents
33
35
}
34
36
const treeItem = new WorkspaceTreeItem ( workspace , this . getWorkspacesQuery === WorkspaceQuery . All , showMetadata )
35
37
workspacesTreeItem . push ( treeItem )
@@ -62,7 +64,7 @@ export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeIte
62
64
)
63
65
return Promise . resolve ( agentTreeItems )
64
66
} else if ( element instanceof AgentTreeItem ) {
65
- const savedMetadata = this . agentMetadata [ element . agent . id ] || [ ]
67
+ const savedMetadata = this . agentWatchers [ element . agent . id ] ?. metadata || [ ]
66
68
return Promise . resolve ( savedMetadata . map ( ( metadata ) => new AgentMetadataTreeItem ( metadata ) ) )
67
69
}
68
70
@@ -71,30 +73,39 @@ export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeIte
71
73
return Promise . resolve ( this . workspaces )
72
74
}
73
75
74
- async monitorMetadata ( agentId : WorkspaceAgent [ "id" ] ) : Promise < void > {
76
+ // monitorMetadata opens a web socket 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 {
75
79
const agentMetadataURL = new URL ( `${ this . storage . getURL ( ) } /api/v2/workspaceagents/${ agentId } /watch-metadata` )
76
80
const agentMetadataEventSource = new EventSource ( agentMetadataURL . toString ( ) , {
77
81
headers : {
78
- "Coder-Session-Token" : await this . storage . getSessionToken ( ) ,
82
+ "Coder-Session-Token" : token ,
79
83
} ,
80
84
} )
81
85
86
+ this . agentWatchers [ agentId ] = {
87
+ dispose : ( ) => {
88
+ delete this . agentWatchers [ agentId ]
89
+ agentMetadataEventSource . close ( )
90
+ } ,
91
+ }
92
+
82
93
agentMetadataEventSource . addEventListener ( "data" , ( event ) => {
83
94
try {
84
95
const dataEvent = JSON . parse ( event . data )
85
96
const agentMetadata = AgentMetadataEventSchemaArray . parse ( dataEvent )
86
97
87
98
if ( agentMetadata . length === 0 ) {
88
- agentMetadataEventSource . close ( )
99
+ this . agentWatchers [ agentId ] . dispose ( )
89
100
}
90
101
91
- const savedMetadata = this . agentMetadata [ agentId ]
102
+ const savedMetadata = this . agentWatchers [ agentId ] . metadata
92
103
if ( JSON . stringify ( savedMetadata ) !== JSON . stringify ( agentMetadata ) ) {
93
- this . agentMetadata [ agentId ] = agentMetadata // overwrite existing metadata
104
+ this . agentWatchers [ agentId ] . metadata = agentMetadata // overwrite existing metadata
94
105
this . refresh ( )
95
106
}
96
107
} catch ( error ) {
97
- agentMetadataEventSource . close ( )
108
+ this . agentWatchers [ agentId ] . dispose ( )
98
109
}
99
110
} )
100
111
}
0 commit comments