diff --git a/extensions/arc/src/models/postgresModel.ts b/extensions/arc/src/models/postgresModel.ts index ff22486af6..e5b08c68cb 100644 --- a/extensions/arc/src/models/postgresModel.ts +++ b/extensions/arc/src/models/postgresModel.ts @@ -9,6 +9,7 @@ import * as vscode from 'vscode'; import * as loc from '../localizedConstants'; import { ControllerModel, Registration } from './controllerModel'; import { ResourceModel } from './resourceModel'; +import { Deferred } from '../common/promise'; import { parseIpAndPort } from '../common/utils'; export class PostgresModel extends ResourceModel { @@ -19,6 +20,8 @@ export class PostgresModel extends ResourceModel { public onConfigUpdated = this._onConfigUpdated.event; public configLastUpdated?: Date; + private _refreshPromise?: Deferred; + constructor(private _controllerModel: ControllerModel, info: ResourceInfo, registration: Registration) { super(info, registration); this._azdataApi = vscode.extensions.getExtension(azdataExt.extension.name)?.exports; @@ -81,9 +84,23 @@ export class PostgresModel extends ResourceModel { /** Refreshes the model */ public async refresh() { - await this._controllerModel.azdataLogin(); - this._config = (await this._azdataApi.azdata.arc.postgres.server.show(this.info.name)).result; - this.configLastUpdated = new Date(); - this._onConfigUpdated.fire(this._config); + // Only allow one refresh to be happening at a time + if (this._refreshPromise) { + return this._refreshPromise.promise; + } + this._refreshPromise = new Deferred(); + + try { + await this._controllerModel.azdataLogin(); + this._config = (await this._azdataApi.azdata.arc.postgres.server.show(this.info.name)).result; + this.configLastUpdated = new Date(); + this._onConfigUpdated.fire(this._config); + this._refreshPromise.resolve(); + } catch (err) { + this._refreshPromise.reject(err); + throw err; + } finally { + this._refreshPromise = undefined; + } } } diff --git a/extensions/arc/src/ui/dashboards/postgres/postgresComputeAndStoragePage.ts b/extensions/arc/src/ui/dashboards/postgres/postgresComputeAndStoragePage.ts index 6b6548920b..a1a3f36fc6 100644 --- a/extensions/arc/src/ui/dashboards/postgres/postgresComputeAndStoragePage.ts +++ b/extensions/arc/src/ui/dashboards/postgres/postgresComputeAndStoragePage.ts @@ -118,13 +118,10 @@ export class PostgresComputeAndStoragePage extends DashboardPage { computeInfoAndLinks.addItem(infoComputeStorage_p6, { CSSStyles: { 'margin-right': '5px' } }); content.addItem(computeInfoAndLinks, { CSSStyles: { 'min-height': '30px' } }); - content.addItem(this.modelView.modelBuilder.text().withProperties({ - value: loc.workerNodes, - CSSStyles: { ...cssStyles.title, 'margin-top': '25px' } - }).component()); + this.workerContainer = this.modelView.modelBuilder.divContainer().component(); - this.workerContainer.addItems(this.createUserInputSection(), { CSSStyles: { 'min-height': '30px' } }); + this.handleServiceUpdated(); content.addItem(this.workerContainer, { CSSStyles: { 'min-height': '30px' } }); this.initialized = true; @@ -143,6 +140,12 @@ export class PostgresComputeAndStoragePage extends DashboardPage { this.disposables.push( this.saveButton.onDidClick(async () => { this.saveButton!.enabled = false; + this.discardButton!.enabled = false; + this.workerBox!.value = ''; + this.coresRequestBox!.value = ''; + this.coresLimitBox!.value = ''; + this.memoryRequestBox!.value = ''; + this.memoryLimitBox!.value = ''; try { await vscode.window.withProgress( { @@ -160,8 +163,6 @@ export class PostgresComputeAndStoragePage extends DashboardPage { vscode.window.showInformationMessage(loc.instanceUpdated(this._postgresModel.info.name)); - this.discardButton!.enabled = false; - } catch (error) { vscode.window.showErrorMessage(loc.instanceUpdateFailed(this._postgresModel.info.name, error)); } @@ -198,8 +199,7 @@ export class PostgresComputeAndStoragePage extends DashboardPage { this.workerBox = this.modelView.modelBuilder.inputBox().withProperties({ readOnly: false, validationErrorMessage: loc.workerValidationErrorMessage, - inputType: 'number', - placeHolder: loc.loading + inputType: 'number' }).component(); this.disposables.push( @@ -216,8 +216,7 @@ export class PostgresComputeAndStoragePage extends DashboardPage { readOnly: false, min: 1, validationErrorMessage: loc.coresValidationErrorMessage, - inputType: 'number', - placeHolder: loc.loading + inputType: 'number' }).component(); this.disposables.push( @@ -234,8 +233,7 @@ export class PostgresComputeAndStoragePage extends DashboardPage { readOnly: false, min: 1, validationErrorMessage: loc.coresValidationErrorMessage, - inputType: 'number', - placeHolder: loc.loading + inputType: 'number' }).component(); this.disposables.push( @@ -252,8 +250,7 @@ export class PostgresComputeAndStoragePage extends DashboardPage { readOnly: false, min: 0.25, validationErrorMessage: loc.memoryLimitValidationErrorMessage, - inputType: 'number', - placeHolder: loc.loading + inputType: 'number' }).component(); this.disposables.push( @@ -270,8 +267,7 @@ export class PostgresComputeAndStoragePage extends DashboardPage { readOnly: false, min: 0.25, validationErrorMessage: loc.memoryRequestValidationErrorMessage, - inputType: 'number', - placeHolder: loc.loading + inputType: 'number' }).component(); this.disposables.push( @@ -286,24 +282,6 @@ export class PostgresComputeAndStoragePage extends DashboardPage { } - private createUserInputSection(): azdata.Component[] { - if (this._postgresModel.configLastUpdated) { - this.editWorkerNodeCount(); - this.editCores(); - this.editMemory(); - } - - return [ - this.createWorkerNodesSectionContainer(), - this.createCoresMemorySection(), - this.createConfigurationSectionContainer(loc.coresRequest, this.coresRequestBox!), - this.createConfigurationSectionContainer(loc.coresLimit, this.coresLimitBox!), - this.createConfigurationSectionContainer(loc.memoryRequest, this.memoryRequestBox!), - this.createConfigurationSectionContainer(loc.memoryLimit, this.memoryLimitBox!) - - ]; - } - private createWorkerNodesSectionContainer(): azdata.FlexContainer { const inputFlex = { flex: '0 1 150px' }; const keyFlex = { flex: `0 1 250px` }; @@ -483,8 +461,30 @@ export class PostgresComputeAndStoragePage extends DashboardPage { } private handleServiceUpdated() { - this.editWorkerNodeCount(); - this.editCores(); - this.editMemory(); + if (this._postgresModel.configLastUpdated) { + this.editWorkerNodeCount(); + this.editCores(); + this.editMemory(); + + // Workaround https://github.com/microsoft/azuredatastudio/issues/13134 + // by only adding these once the model has data. After the bug is fixed, + // use loading indicators instead of keeping the page blank. + if (this.workerContainer?.items.length === 0) { + this.workerContainer.addItem(this.modelView.modelBuilder.text().withProperties({ + value: loc.workerNodes, + CSSStyles: { ...cssStyles.title, 'margin-top': '25px' } + }).component()); + + this.workerContainer.addItems([ + this.createWorkerNodesSectionContainer(), + this.createCoresMemorySection(), + this.createConfigurationSectionContainer(loc.coresRequest, this.coresRequestBox!), + this.createConfigurationSectionContainer(loc.coresLimit, this.coresLimitBox!), + this.createConfigurationSectionContainer(loc.memoryRequest, this.memoryRequestBox!), + this.createConfigurationSectionContainer(loc.memoryLimit, this.memoryLimitBox!) + + ]); + } + } } }