@@ -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,54 @@ 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
+ } catch ( error ) {
40
+ this . workspaces = [ ]
42
41
}
43
- this . workspaces = workspacesTreeItem
42
+
44
43
this . refresh ( )
44
+ this . fetching = false
45
+ }
46
+
47
+ /**
48
+ * Fetch workspaces and turn them into tree items. Throw an error if not
49
+ * logged in or the query fails.
50
+ */
51
+ async fetch ( ) : Promise < WorkspaceTreeItem [ ] > {
52
+ // Assume that no URL or no token means we are not logged in.
53
+ const url = this . storage . getURL ( )
54
+ const token = await this . storage . getSessionToken ( )
55
+ if ( ! url || ! token ) {
56
+ throw new Error ( "not logged in" )
57
+ }
58
+
59
+ const resp = await getWorkspaces ( { q : this . getWorkspacesQuery } )
60
+
61
+ // We could have logged out while waiting for the query.
62
+ if ( ! url || ! token ) {
63
+ throw new Error ( "not logged in" )
64
+ }
65
+
66
+ return resp . workspaces . map ( ( workspace ) => {
67
+ const showMetadata = this . getWorkspacesQuery === WorkspaceQuery . Mine
68
+ if ( showMetadata ) {
69
+ const agents = extractAgents ( workspace )
70
+ agents . forEach ( ( agent ) => this . monitorMetadata ( agent . id , token ) ) // monitor metadata for all agents
71
+ }
72
+ return new WorkspaceTreeItem ( workspace , this . getWorkspacesQuery === WorkspaceQuery . All , showMetadata )
73
+ } )
45
74
}
46
75
47
76
private _onDidChangeTreeData : vscode . EventEmitter < vscode . TreeItem | undefined | null | void > =
0 commit comments