Skip to content

Commit cc212db

Browse files
committed
feat: enhance CosmosDBWorkspaceBranchDataProvider with caching and parent retrieval functionality
1 parent fa82436 commit cc212db

File tree

2 files changed

+72
-9
lines changed

2 files changed

+72
-9
lines changed

src/tree/workspace-view/cosmosdb/CosmosDBWorkspaceBranchDataProvider.ts

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ export class CosmosDBWorkspaceBranchDataProvider
2626
{
2727
private readonly onDidChangeTreeDataEmitter = new vscode.EventEmitter<TreeElement | undefined>();
2828

29+
private readonly childrenCache = new Map<string, TreeElement>();
30+
private resourcesCache = ext.state.wrapItemInStateHandling(new CosmosDBWorkspaceItem(), (item: TreeElement) =>
31+
this.refresh(item),
32+
) as TreeElement;
33+
2934
constructor() {
3035
super(() => this.onDidChangeTreeDataEmitter.dispose());
3136
}
@@ -61,9 +66,29 @@ export class CosmosDBWorkspaceBranchDataProvider
6166

6267
const children = (await element.getChildren?.()) ?? [];
6368
return children.map((child) => {
64-
return ext.state.wrapItemInStateHandling(child, (child: TreeElement) =>
69+
if (!this.isAncestorOf(element, child.id)) {
70+
child = createGenericElement({
71+
contextValue: 'cosmosDB.workspace.item.error',
72+
label: l10n.t(
73+
'Child element "{0}" is not a child of parent element "{1}".',
74+
child.id,
75+
element.id,
76+
),
77+
}) as TreeElement;
78+
}
79+
if (this.childrenCache.has(child.id)) {
80+
return this.childrenCache.get(child.id)!;
81+
}
82+
const wrapped = ext.state.wrapItemInStateHandling(child, (child: TreeElement) =>
6583
this.refresh(child),
6684
) as TreeElement;
85+
if (
86+
!isTreeElementWithContextValue(child) ||
87+
child.contextValue !== 'cosmosDB.workspace.item.error'
88+
) {
89+
this.childrenCache.set(child.id, wrapped);
90+
}
91+
return wrapped;
6792
});
6893
},
6994
);
@@ -85,26 +110,63 @@ export class CosmosDBWorkspaceBranchDataProvider
85110
async getResourceItem(): Promise<TreeElement> {
86111
const resourceItem = await callWithTelemetryAndErrorHandling(
87112
'CosmosDBWorkspaceBranchDataProvider.getResourceItem',
88-
() => new CosmosDBWorkspaceItem(),
113+
() => {
114+
ext.cosmosDBWorkspaceBranchDataResource = this.resourcesCache as CosmosDBWorkspaceItem;
115+
return this.resourcesCache;
116+
},
89117
);
90118

91119
if (resourceItem) {
92120
// Workspace picker relies on this value
93-
ext.cosmosDBWorkspaceBranchDataResource = resourceItem;
94-
95-
return ext.state.wrapItemInStateHandling(resourceItem, (item: TreeElement) =>
96-
this.refresh(item),
97-
) as TreeElement;
121+
ext.cosmosDBWorkspaceBranchDataResource = this.resourcesCache as CosmosDBWorkspaceItem;
122+
return resourceItem;
98123
}
99124

100125
return null as unknown as TreeElement;
101126
}
102127

128+
getParent(element: TreeElement): TreeElement | null | undefined {
129+
const parentId = element.id.substring(0, element.id.lastIndexOf('/'));
130+
if (this.resourcesCache.id === parentId) {
131+
return this.resourcesCache;
132+
}
133+
if (parentId) {
134+
const parent = this.childrenCache.get(parentId);
135+
if (parent) {
136+
return parent;
137+
}
138+
}
139+
return undefined;
140+
}
141+
103142
async getTreeItem(element: TreeElement): Promise<vscode.TreeItem> {
104143
return element.getTreeItem();
105144
}
106145

107146
refresh(element?: TreeElement): void {
147+
if (element) {
148+
// Get the cache key for this element
149+
const cacheKey = element.id;
150+
151+
// Clear this element's children from cache
152+
this.childrenCache.delete(cacheKey);
153+
154+
// Also clear any potential child caches using prefix
155+
const elementId = element.id;
156+
for (const key of this.childrenCache.keys()) {
157+
if (key.startsWith(`${elementId}/`)) {
158+
this.childrenCache.delete(key);
159+
}
160+
}
161+
} else {
162+
// If no element specified, clear the entire cache
163+
this.childrenCache.clear();
164+
}
108165
this.onDidChangeTreeDataEmitter.fire(element);
109166
}
167+
168+
protected isAncestorOf(element: TreeElement, id: string): boolean {
169+
const elementId = element.id + '/';
170+
return id.toLowerCase().startsWith(elementId.toLowerCase());
171+
}
110172
}

src/tree/workspace-view/cosmosdb/CosmosDBWorkspaceItem.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { type CosmosDBAttachedAccountModel } from './CosmosDBAttachedAccountMode
2222
import { LocalCoreEmulatorsItem } from './LocalEmulators/LocalCoreEmulatorsItem';
2323

2424
export class CosmosDBWorkspaceItem implements TreeElement, TreeElementWithContextValue {
25-
public readonly id: string = WorkspaceResourceType.AttachedAccounts;
25+
public readonly id: string = `${WorkspaceResourceType.AttachedAccounts}/accounts`;
2626
public readonly contextValue: string = 'treeItem.accounts';
2727

2828
constructor() {
@@ -33,7 +33,7 @@ export class CosmosDBWorkspaceItem implements TreeElement, TreeElementWithContex
3333
// TODO: remove after a few releases
3434
await this.pickSupportedAccounts(); // Move accounts from the old storage format to the new one
3535

36-
const items = await SharedWorkspaceStorage.getItems(this.id);
36+
const items = await SharedWorkspaceStorage.getItems(WorkspaceResourceType.AttachedAccounts);
3737
const children = await this.getChildrenNoEmulatorsImpl(items);
3838

3939
if (isEmulatorSupported) {
@@ -97,6 +97,7 @@ export class CosmosDBWorkspaceItem implements TreeElement, TreeElementWithContex
9797
return callWithTelemetryAndErrorHandling(
9898
'CosmosDBAttachedAccountsResourceItem.pickSupportedAccounts',
9999
async () => {
100+
//TODO: migrate to new schema!
100101
const serviceName = 'ms-azuretools.vscode-cosmosdb.connectionStrings';
101102
const value: string | undefined = ext.context.globalState.get(serviceName);
102103

0 commit comments

Comments
 (0)