@@ -14,6 +14,7 @@ export enum WorkspaceQuery {
14
14
export class WorkspaceProvider implements vscode . TreeDataProvider < vscode . TreeItem > {
15
15
private workspaces : WorkspaceTreeItem [ ] = [ ]
16
16
private agentWatchers : Record < WorkspaceAgent [ "id" ] , { dispose : ( ) => void ; metadata ?: AgentMetadataEvent [ ] } > = { }
17
+ private fetching = false
17
18
18
19
constructor (
19
20
private readonly getWorkspacesQuery : WorkspaceQuery ,
@@ -22,26 +23,50 @@ export class WorkspaceProvider implements vscode.TreeDataProvider<vscode.TreeIte
22
23
this . fetchAndRefresh ( )
23
24
}
24
25
25
- // fetchAndRefrehsh fetches new workspaces then re-renders the entire tree.
26
+ // fetchAndRefresh fetches new workspaces then re-renders the entire tree.
27
+ // Trying to call this while already refreshing is a no-op and will return
28
+ // immediately.
26
29
async fetchAndRefresh ( ) {
27
- const token = await this . storage . getSessionToken ( )
28
- const workspacesTreeItem : WorkspaceTreeItem [ ] = [ ]
30
+ if ( this . fetching ) {
31
+ return
32
+ }
33
+ this . fetching = true
34
+
29
35
Object . values ( this . agentWatchers ) . forEach ( ( watcher ) => watcher . dispose ( ) )
30
- // If the URL is set then we are logged in.
31
- if ( this . storage . getURL ( ) ) {
32
- const resp = await getWorkspaces ( { q : this . getWorkspacesQuery } )
33
- resp . workspaces . forEach ( ( workspace ) => {
34
- const showMetadata = this . getWorkspacesQuery === WorkspaceQuery . Mine
35
- if ( showMetadata && token ) {
36
- const agents = extractAgents ( workspace )
37
- agents . forEach ( ( agent ) => this . monitorMetadata ( agent . id , token ) ) // monitor metadata for all agents
38
- }
39
- const treeItem = new WorkspaceTreeItem ( workspace , this . getWorkspacesQuery === WorkspaceQuery . All , showMetadata )
40
- workspacesTreeItem . push ( treeItem )
41
- } )
36
+
37
+ try {
38
+ this . workspaces = await this . fetch ( )
39
+ this . refresh ( )
40
+ } catch ( error ) {
41
+ this . workspaces = [ ]
42
+ }
43
+
44
+ this . fetching = false
45
+ }
46
+
47
+ async fetch ( ) : Promise < WorkspaceTreeItem [ ] > {
48
+ // Assume that no URL or no token means we are not logged in.
49
+ const url = this . storage . getURL ( )
50
+ const token = await this . storage . getSessionToken ( )
51
+ if ( ! url || ! token ) {
52
+ throw new Error ( "not logged in" )
53
+ }
54
+
55
+ const resp = await getWorkspaces ( { q : this . getWorkspacesQuery } )
56
+
57
+ // We could have logged out while waiting for the query.
58
+ if ( ! url || ! token ) {
59
+ throw new Error ( "not logged in" )
42
60
}
43
- this . workspaces = workspacesTreeItem
44
- this . refresh ( )
61
+
62
+ return resp . workspaces . map ( ( workspace ) => {
63
+ const showMetadata = this . getWorkspacesQuery === WorkspaceQuery . Mine
64
+ if ( showMetadata && token ) {
65
+ const agents = extractAgents ( workspace )
66
+ agents . forEach ( ( agent ) => this . monitorMetadata ( agent . id , token ) ) // monitor metadata for all agents
67
+ }
68
+ return new WorkspaceTreeItem ( workspace , this . getWorkspacesQuery === WorkspaceQuery . All , showMetadata )
69
+ } )
45
70
}
46
71
47
72
private _onDidChangeTreeData : vscode . EventEmitter < vscode . TreeItem | undefined | null | void > =
0 commit comments