Improve Azure startup time and fix command palette (#5761)

* Improve Azure startup time and fix command palette
- Improvement (but not full fix) for #4732 where Azure startup is very slow.
This speeds the startup by up to 5 seconds by
  - Changing from fixed 5 second initial wait time to a promise to check for accounts
  - Using the accounts changed notification to send a message when accounts are ready. This is usually what will "win out" since Azure seems to load before the Account Providers are set up.
- Remove right-click actions from the command palette.
- Rename Azure actions so it's clear what they are in the command palette.

* Remove coveralls task while investigating how to make optional task

* Add void return type
This commit is contained in:
Kevin Cunnane
2019-05-31 10:22:01 -07:00
committed by GitHub
parent a364af5c4c
commit ae0603c041
6 changed files with 85 additions and 59 deletions

View File

@@ -6,7 +6,7 @@
'use strict';
import { TreeDataProvider, EventEmitter, Event, TreeItem } from 'vscode';
import { setInterval, clearInterval } from 'timers';
import * as azdata from 'azdata';
import { AppContext } from '../../appContext';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
@@ -16,13 +16,40 @@ import { AzureResourceAccountTreeNode } from './accountTreeNode';
import { AzureResourceAccountNotSignedInTreeNode } from './accountNotSignedInTreeNode';
import { AzureResourceMessageTreeNode } from '../messageTreeNode';
import { AzureResourceContainerTreeNodeBase } from './baseTreeNodes';
import { AzureResourceErrorMessageUtil } from '../utils';
import { AzureResourceErrorMessageUtil, equals } from '../utils';
import { IAzureResourceTreeChangeHandler } from './treeChangeHandler';
import { IAzureResourceAccountService } from '../../azureResource/interfaces';
import { AzureResourceServiceNames } from '../constants';
export class AzureResourceTreeProvider implements TreeDataProvider<TreeNode>, IAzureResourceTreeChangeHandler {
public isSystemInitialized: boolean = false;
private accountService: IAzureResourceAccountService;
private accounts: azdata.Account[];
private _onDidChangeTreeData = new EventEmitter<TreeNode>();
private loadingAccountsPromise: Promise<void>;
public constructor(public readonly appContext: AppContext) {
if (appContext) {
this.hookAccountService(appContext);
}
}
private hookAccountService(appContext: AppContext): void {
this.accountService = appContext.getService<IAzureResourceAccountService>(AzureResourceServiceNames.accountService);
if (this.accountService) {
this.accountService.onDidChangeAccounts((e: azdata.DidChangeAccountsParams) => {
// the onDidChangeAccounts event will trigger in many cases where the accounts didn't actually change
// the notifyNodeChanged event triggers a refresh which triggers a getChildren which can trigger this callback
// this below check short-circuits the infinite callback loop
this.setSystemInitialized();
if (!equals(e.accounts, this.accounts)) {
this.accounts = e.accounts;
this.notifyNodeChanged(undefined);
}
});
}
}
public async getChildren(element?: TreeNode): Promise<TreeNode[]> {
@@ -30,34 +57,16 @@ export class AzureResourceTreeProvider implements TreeDataProvider<TreeNode>, IA
return element.getChildren(true);
}
if (!this.isSystemInitialized && !this._loadingTimer) {
this._loadingTimer = setInterval(async () => {
try {
// Call azdata.accounts.getAllAccounts() to determine whether the system has been initialized.
await this.appContext.getService<IAzureResourceAccountService>(AzureResourceServiceNames.accountService).getAccounts();
// System has been initialized
this.isSystemInitialized = true;
if (this._loadingTimer) {
clearInterval(this._loadingTimer);
}
this._onDidChangeTreeData.fire(undefined);
} catch (error) {
// System not initialized yet
this.isSystemInitialized = false;
}
}, AzureResourceTreeProvider.loadingTimerInterval);
return [AzureResourceMessageTreeNode.create(AzureResourceTreeProvider.loadingLabel, undefined)];
if (!this.isSystemInitialized) {
if (!this.loadingAccountsPromise) {
this.loadingAccountsPromise = this.loadAccounts();
}
return [AzureResourceMessageTreeNode.create(localize('azure.resource.tree.treeProvider.loadingLabel', 'Loading ...'), undefined)];
}
try {
const accounts = await this.appContext.getService<IAzureResourceAccountService>(AzureResourceServiceNames.accountService).getAccounts();
if (accounts && accounts.length > 0) {
return accounts.map((account) => new AzureResourceAccountTreeNode(account, this.appContext, this));
if (this.accounts && this.accounts.length > 0) {
return this.accounts.map((account) => new AzureResourceAccountTreeNode(account, this.appContext, this));
} else {
return [new AzureResourceAccountNotSignedInTreeNode()];
}
@@ -66,6 +75,23 @@ export class AzureResourceTreeProvider implements TreeDataProvider<TreeNode>, IA
}
}
private async loadAccounts(): Promise<void> {
try {
this.accounts = await this.appContext.getService<IAzureResourceAccountService>(AzureResourceServiceNames.accountService).getAccounts();
// System has been initialized
this.setSystemInitialized();
this._onDidChangeTreeData.fire(undefined);
} catch (err) {
// Skip for now, we can assume that the accounts changed event will eventually notify instead
this.isSystemInitialized = false;
}
}
private setSystemInitialized(): void {
this.isSystemInitialized = true;
this.loadingAccountsPromise = undefined;
}
public get onDidChangeTreeData(): Event<TreeNode> {
return this._onDidChangeTreeData.event;
}
@@ -87,12 +113,4 @@ export class AzureResourceTreeProvider implements TreeDataProvider<TreeNode>, IA
public getTreeItem(element: TreeNode): TreeItem | Thenable<TreeItem> {
return element.getTreeItem();
}
public isSystemInitialized: boolean = false;
private _loadingTimer: NodeJS.Timer = undefined;
private _onDidChangeTreeData = new EventEmitter<TreeNode>();
private static readonly loadingLabel = localize('azure.resource.tree.treeProvider.loadingLabel', 'Loading ...');
private static readonly loadingTimerInterval = 5000;
}